[
http://opensource.atlassian.com/projects/hibernate/browse/HHH-2477?page=c...
]
Adam T commented on HHH-2477:
-----------------------------
See "Section 19.1.3. Single-ended association proxies" of the Hibernate
Reference Guide.
http://www.hibernate.org/hib_docs/reference/en/html/performance.html
This is a known limitation when using proxies. It is due to Java's single-inheritance
model. To work around the limitation and still use lazy loading, create interfaces for
your entity classes and program to those interfaces.
public interface Vehicle {}
public interface Car extends Vehicle {}
public class VehicleBean implements Vehicle {}
public class CarBean implements Car {}
lazy fetching ManyToOne produces inproper proxies when using single
table inheritance strategy
----------------------------------------------------------------------------------------------
Key: HHH-2477
URL:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-2477
Project: Hibernate3
Issue Type: Bug
Components: core
Affects Versions: 3.2.1
Environment: hibernate 3.2.1-GA, postgresql 8.1
Reporter: Daniel Nguyen
Attachments: bug.zip
Original Estimate: 1 hour
Remaining Estimate: 1 hour
I have entity base class Vehicle and entity class Car which extends Vehicle (using single
table inheritance strategy).
I also have entity class User which have single-ended @ManyToOne relation from User to
Vehicle with lazy fetching.
Now there is a Car instance "c" and User instance "u" with relation
to "c". Lazily fetching vehicle from "u" results with proxy object
"o" which is instanceof Vehicle but not instanceof Car as expected. So it's
impossible cast "o" to Car or at least read any of Car's property from
"o".
This is serious problem when inheritance is extensively used because inproper proxy
object remains in cache. To walkaround I'd have to resign with lazy fetching (much
performance loss) or manually replace proxy object in cache.
testing code:
SessionFactory sf = null;
Session s = null;
Transaction tx = null;
try
{
sf = cfg.buildSessionFactory();
s = sf.openSession();
tx = s.beginTransaction();
//create car
Car car = new Car();
car.setIdVehicle(1);
car.setAge(5);
s.save(car);
//create user of car
User user = new User();
user.setIdUser(1);
user.setVehicle(car);
s.save(user);
//make sure it is actually added
s.flush();
// test 1 - works ok, because we loaded vehicle before user
s.clear(); //clear cache
Vehicle vv = (Vehicle)s.get(Vehicle.class, 1);
User uu = (User)s.get(User.class, 1);
//we know that user vehicle is actually a Car
Car cc = (Car)uu.getVehicle();
// test 2 - fails, when using lazy fetching
s.clear(); //clear cache
User u = (User)s.get(User.class, 1);
Vehicle v = u.getVehicle();
//we know that user vehicle is actually a Car
//so we cast to Car but ClassCastException is raised!!!
Car c = (Car)v;
//let's check what's actual class of v
System.out.println(v.getClass().getName());
System.out.println(v.getClass().getSuperclass().getName());
//result:
// test.hibernate.Vehicle$$EnhancerByCGLIB$$12ce1883
// test.hibernate.Vehicle
//but I expected:
// test.hibernate.Car$$EnhancerByCGLIB$$xxxxx
// test.hibernate.Car
}
finally
{
if (tx!=null)
tx.rollback();
if (s!=null)
s.close();
if (sf!=null)
sf.close();
}
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira