Polymorphic "get" using sleep mode, many to one, InheritanceType.JOINED

I have something like this.

A class car that has one seat with many seats. Seat has a subclass of LeatherSeat.

public class Car { private Seat seat; ... @ManyToOne(fetch = FetchType.LAZY) public Seat getSeat() { return seat; } ... } @Entity @Inheritance(strategy=InheritanceType.JOINED) public class Seat { private String id; private String color; } @Entity public class LeatherSeat extends Seat { private String leatherType; } 

When I create my car and make my LeatherSeat car seat, it will save everything right on db. When I want to get my car (using a list of criteria or queries), and I read getSeat (), Seat is always just a Seat, not LeatherSeat. I cannot use (exception) and apparently should manually get LeatherSeat by id.

Is this a limitation of using the JOINED inheritance type or am I missing something. How to get Seat as LeatherSeat?

+4
source share
2 answers

It seems that if you make lazy choices, like you do with getSeat, you will only get the parent, not the subclass. I tried the same example with FetchType.EAGER and getSeat correctly returns LeatherSeat.

I'm not sure why sleep mode can get a car with LeatherSeat when for EAGER fetch, but sleep mode can not get it when it does a LAZY fetch. Something seems to be broken there.

There is a ticket about discriminator columns in InheritanceType.JOINED where a dot is made regarding this scenario. https://hibernate.onjira.com/browse/ANN-140 , but the ticket was rejected, indicating that sleep mode was too elegant to require a discriminator for InheritanceType.JOINED. However, it cannot correctly return subclasses to lazy samples.

Then this ticket https://hibernate.onjira.com/browse/HHH-271?focusedCommentId=44089#comment-44089 is more specific for this problem, and the answer was “how do we expect to know which subclass to get lazy choice?

Both tickets are old and were rejected. It seems to be a problem for me. But for now, you’ll have to switch to a different type of inheritance or use the desired type of fetch, since this matches the design of the sleep mode.

+1
source

In the case of LAZY, the place will be a "proxy" that is created when the Car instance is created. At that time, Hibernate did not know whether the seat would be leather or not.

When you cross the property and boot lazily, Hibernate will know that Seat is skin, but it cannot retrospectively change the proxy class. However, all the data is there. The seat will react like LeatherSeat if you override any methods.

If you really need to pass this object to LeatherSeat, you can unzip the proxy server using http://docs.jboss.org/hibernate/orm/3.2/api/org/hibernate/engine/PersistenceContext.html#unproxy(java. lang.Object )

Check out this blog to learn more about why the proxy will always be Seat and not LeatherSeat: http://sessionfactory.blogspot.co.uk/2010/08/hacking-lazy-loaded-inheritance.html

This is briefly described in the Hibernate docs: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html#performance-fetching-proxies

+2
source

All Articles