What does eclipse do when you inspect variables (while debugging)
I have an instance of org.hibernate.envers.entities.mapper.relation.lazy.proxy.ListProxy
that is causing some grief: whenever I programmatically try to access it I get a null pointer exception (ie calling list.size()
) but when I first inspect the object using Eclipse's variable inspector I see Hibernate generate a SQL statement and the list changes dynamically. Then everything works. How can I do the same thing programmatically? I've tried list.toString()
but that doesn't seem to help.
Update 1
Don't know if this helps but when I first click on the list instance I see in the display:
com.sun.jdi.InvocationException occurred invoking method.
Then database query runs and when I click again I get the correct .toString()
result.
Update 2
Here is the original exception I get (when I don't inspect the element in debug mode).
java.lang.NullPointerException
at org.hibernate.envers.query.impl.EntitiesAtRevisionQuery.list(EntitiesAtRevisionQuery.java:72)
at org.hibernate.envers.query.impl.AbstractAuditQuery.getSingleResult(AbstractAuditQuery.java:104)
at org.hibernate.envers.entities.mapper.r开发者_如何学JAVAelation.OneToOneNotOwningMapper.mapToEntityFromMap(OneToOneNotOwningMapper.java:74)
at org.hibernate.envers.entities.mapper.MultiPropertyMapper.mapToEntityFromMap(MultiPropertyMapper.java:118)
at org.hibernate.envers.entities.EntityInstantiator.createInstanceFromVersionsEntity(EntityInstantiator.java:93)
at org.hibernate.envers.entities.mapper.relation.component.MiddleRelatedComponentMapper.mapToObjectFromFullMap(MiddleRelatedComponentMapper.java:44)
at org.hibernate.envers.entities.mapper.relation.lazy.initializor.ListCollectionInitializor.addToCollection(ListCollectionInitializor.java:67)
at org.hibernate.envers.entities.mapper.relation.lazy.initializor.ListCollectionInitializor.addToCollection(ListCollectionInitializor.java:39)
at org.hibernate.envers.entities.mapper.relation.lazy.initializor.AbstractCollectionInitializor.initialize(AbstractCollectionInitializor.java:67)
at org.hibernate.envers.entities.mapper.relation.lazy.proxy.CollectionProxy.checkInit(CollectionProxy.java:50)
at org.hibernate.envers.entities.mapper.relation.lazy.proxy.CollectionProxy.size(CollectionProxy.java:55)
at <MY CODE HERE, which checks list.size()>
Final Solution (Actually more of a temporary hack)
boolean worked = false;
while (!worked) {
try {
if(list.size() == 1) {
// do stuff
}
worked = true;
} catch (Exception e) {
// TODO: exception must be accessed or the loop will be infinite
e.getStackTrace();
}
}
Well what happends there is you're seing Hibernate's lazy loading in deep action :)
Basically hibernate loads proxy classes for you lazily associated relations, such that instead of a List of classes C you get a List (actually a PersistenceBag implementation) of Hibernate autogenerated proxie for your C class. THis is hibernate's way of deferring load of that association's values until they are actually accessed. So that's why when you access it in the eclipse debugger (which basically accesses an instance's fields/methids via introspection) you see the sql hibernate triggers to fetch the needed data.
The trick here is that depending on WHEN you access a lazy collection you might get different results. If you access it using the eclipse debugger you're more likely still in the Hibernate session that started loading that thing, so everything works as expected, an sql is (lazily) triggered when the thing is accessed and the data is loaded). Problem is that if you wanna access that same data in your code, but at a point where the session is already closed, you'll either get a LazyInitializationException or null (the latter if you're using some library for cleaning put hibenrate proxises such as Gilead)
精彩评论