6

I have a hierarchy in my domain model, which is described by classes:

@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class BaseEntity {
    @Id
    private Long id;

    // other fields
}

@DiscriminatorValue(value = "Individual")
public class IndividualEntity extends BaseEntity {
    // fields
}

@DiscriminatorValue(value = "Branch")
public class BranchEntity extends BaseEntity {
    // fields
}

I'm fetching objects like this:

Specification<BaseEntity> specification = createSpecification();
BaseEntity entity = baseRepository.findOne(specification);

(I'm using spring-data)

The problem is that Hibernate returns proxy object (what I understand), but the proxy is of BaseEntity, not the proper subclass (its' class is BaseEntity_$$_jvsted9_26, therefore entity instanceof IndividualEntity is false).

What is interesting, not all objects are returned as proxy.
I'm fetching entities in loop (common transaction), some of them are returned in normal form (i.e. IndividualEntity/BranchEntity), some as proxies.
If I change mechanism, so that every fetch is done in separate transaction - no proxy objects are returned at all.

I know that I can unwrap that proxy (e.g. like here), but what is the reason for such behaviour (kinda strange for me) and can I avoid it?

pnescior
  • 136
  • 9

1 Answers1

4

Can't be certain without seeing more of the object model, but one reason Hibernate would do this is if the BaseEntity had already had to be resolved as a proxy for the same BaseEntity.id earlier in the session.

For example, if there is another class that has a ToOne relation to a BaseEntity, it will just have a foreign key to the id, so will use a BaseEntity_$$... proxy to delay resolving the correct subclass for the other end. This then becomes the instance for that id that is managed in the Hibernate PersistenceContext.

Clearly a Hibernate.unwrap(), or one of the other options in the link above will reveal the 'true' instance. One other option is to use abstract methods on BaseEntity (e.g. isIndividual()). This can look a bit tidier, but ultimately Hibernate will still need to resolve the proxy when the method is called.

df778899
  • 10,135
  • 1
  • 18
  • 32
  • 1
    Yes, that sounds reasonable! I've dealt with that using Visitor pattern, btw. Thanks for this info! – pnescior Sep 27 '18 at 13:26