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?

3
  • I'm having the same problem using directly spring-data Repository class. Commented Jul 4, 2018 at 14:35
  • Why do you care? Commented Jul 4, 2018 at 18:24
  • 1
    Might be related: stackoverflow.com/a/32785467/4754790. Commented Jul 6, 2018 at 9:53

1 Answer 1

4
+50

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Yes, that sounds reasonable! I've dealt with that using Visitor pattern, btw. Thanks for this info!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.