[Hibernate-JIRA] Created: (HHH-2477) lazy fetching ManyToOne produces inproper proxies when using single table inheritance strategy
by Daniel Nguyen (JIRA)
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
Type: Bug
Components: core
Versions: 3.2.1
Environment: hibernate 3.2.1-GA, postgresql 8.1
Reporter: Daniel Nguyen
Attachments: bug.zip
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
16 years, 4 months
[Hibernate-JIRA] Created: (ANN-723) Impossible to bind a SortedMap collection
by Alexandre Dutra (JIRA)
Impossible to bind a SortedMap collection
-----------------------------------------
Key: ANN-723
URL: http://opensource.atlassian.com/projects/hibernate/browse/ANN-723
Project: Hibernate Annotations
Issue Type: Bug
Affects Versions: 3.3.0.ga
Environment: hibernate: 3.2.5.ga
hibernate-annotations: 3.3.0.ga
database: HSQL 1.8.0.7
Reporter: Alexandre Dutra
Priority: Minor
See http://forum.hibernate.org/viewtopic.php?t=976437
I have the following collection declared in a persistent class:
@CollectionOfElements
@Sort(type = SortType.NATURAL)
@JoinTable(name = "delivery_option_price", joinColumns = @JoinColumn(name = "delivery_option_id"))
private SortedMap<Float, MonetaryAmount> prices = new TreeMap<Float, MonetaryAmount>();
Hibernate fails to bind it to a database table. The stack trace is:
java.lang.NullPointerException
at org.hibernate.cfg.annotations.MapBinder.bindKeyFromAssociationTable(MapBinder.java:129)
at org.hibernate.cfg.annotations.MapBinder.access$000(MapBinder.java:53)
at org.hibernate.cfg.annotations.MapBinder$1.secondPass(MapBinder.java:83)
at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:43)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1130)
at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:316)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1286)
at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:915)
...
A workaround to this is to explicitly specify the map key class by adding a org.hibernate.annotations.MapKey annotation:
@org.hibernate.annotations.MapKey(targetElement = Float.class, columns = @Column(name = "WEIGHT"))
Browsing the source code, I realized that the NullPointerException is being raised beacause the following method returns null in org.hibernate.annotations.common.reflection.java.JavaXCollectionType:
public XClass getMapKey() {
return new TypeSwitch<XClass>() {
@Override
public XClass caseParameterizedType(ParameterizedType parameterizedType) {
if ( getCollectionClass().isAssignableFrom( Map.class ) ) {
return toXClass( parameterizedType.getActualTypeArguments()[0] );
}
return null;
}
}.doSwitch( approximate() );
}
More specifically, the following expression seems misconstructed:
getCollectionClass().isAssignableFrom( Map.class )
The correct expression would be:
Map.class.isAssignableFrom( getCollectionClass() )
At least if, as I understand it, the goal is to determine whether the collection class is or is not a Map in anyone one of its implementations. The same applies to the getElementClass() method, in the same class.
If my analyzis is correct, the bug might be very easy to fix, but maybe I'm underestimating its impacts.
--
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
16 years, 4 months