Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate returns proxy for base class

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?

like image 964
pnescior Avatar asked Jul 20 '17 09:07

pnescior


People also ask

Which method returns proxy object from the session?

Hibernate session get method returns proxy object.

How does Hibernate proxy work?

By definition, a proxy is “a function authorized to act as the deputy or substitute for another”. This applies to Hibernate when we call Session. load() to create what is called an uninitialized proxy of our desired entity class. This subclass will be the one to be returned instead of querying the database directly.

What is JPA proxy?

The JPA lazy loading mechanism can either be implemented using Proxies or Bytecode Enhancement so that calls to lazy associations can be intercepted and relationships initialized prior to returning the result back to the caller.

What is proxy object in Java?

Proxy is a structural design pattern that provides an object that acts as a substitute for a real service object used by a client. A proxy receives client requests, does some work (access control, caching, etc.) and then passes the request to a service object.


1 Answers

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.

like image 130
df778899 Avatar answered Oct 05 '22 10:10

df778899