|
[
Permalink
| « Hide
]
Douglas A. Herrick added a comment - 02/Nov/06 01:58 PM
We're running into the same issue.
I need a test case which reproduces this behavior.
The only high-level caller of this method is the DefaultFlushEntityEventListener. So what happens is that somehow your use-case causes a situation where an entity is "known" to not have any db state (snapshot == NO_ROW) but is deemed to need flushing (i.e. requires an update). I need to track down how that happens. Steve,
While perhaps not directly related to the other issue you and I have been discussing, it would seem that if you, effectively, disabled snapshots (like I did by specifying Query.setReadOnly(true)), but actually changed a persistent object that you resolved, would that result in the behavior this bug describes? Any update on this issue? We're still running into it, though I've not yet isolated the run-time scenario...
I looked into this today: for us, it was bit of a red herring; however, I thought other might be interested the root cause of our snafu... In our case, the object that triggered the hibernate exception during flush processing (for us, this occurred when hibernate executed a flush before resolving a query) had not assigned a reference to an object that would have satisified a foreign key constraint. Actually, I'd argue that, in this context, that is, flushing before executing a query, hibernate should not barf the way it did, since execution of the query was not dependend upon the assignment of the foreign key. While flush processing during commit might warrant this exception (since the foreign key constraint would have failed), preprocessing (i.e., flushing) for the query does not.
Cool, you've isolated the cause so it should be trivial to come up with a small test case.
I mean if the issue is really just the "red herring"-ness, I can easily come up with a more appropriate failure message. If you want to argue that this should be allowed, I need a test case showing what it is that you are trying to do and believe to be valid. And given your description, it should be easy to come up with an example that uses one or two domain objects. I get the same exception when doing Map.remove(). The map is lazy and hasn't been initialised. If I first to Map.containsKey() the Map.remove() returns the correct object and doesn't throw a ClassCastException. The Map object is defined using generics: Map<Integer, ReporterListScore> and I expect the Map.remove() method to return a ReporterListScore object but it returns a MarkerObject. I am now using Hibernate 3.2.1. This is a new problem. I was using 3.2.0.cr3 before.
I have the same error with 3.2.1.GA, with 3.2.0.cr4 was fine.
Still have not seen a test case for this "bug". So I just made a small change to throw a more meaningful exception if getCachedDatabaseSnapshot() encounters a NO_ROW.
I still have the problem with Map.remove() using 3.2.2.GA.
java.lang.ClassCastException: org.hibernate.util.MarkerObject at org.tinymarbles.model.PType.remove(PType.java:172) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:147) The line in question is: > PAttribute attribute = this.getAttributes().remove(attName); the getter returns Map<String, PAttribute> declared as follows: > @OneToMany(mappedBy = "type", fetch = FetchType.LAZY) > @MapKey(name = "name") > @Cascade(value = {CascadeType.REMOVE, CascadeType.DELETE_ORPHAN, CascadeType.SAVE_UPDATE}) > @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) > private Map<String, PAttribute> attributes = new HashMap<String, PAttribute>(); Yes, I'm using field mapping. :-) The workaround with Map.containsKey() works for me. I'm also seeing this issue with Map.remove(), this might be the issue (see the comments I added) but I can't prove anything yet.
/** * @see java.util.Map#remove(Object) */ public Object remove(Object key) { if ( isPutQueueEnabled() ) { Object old = readElementByIndex( key ); // returns MarkerObject UNKNOWN if the object isn't in the map // add if(old == UNKNOWN) return null; queueOperation( new Remove( key, old ) ); return old; } else { // TODO : safe to interpret "map.remove(key) == null" as non-dirty? initialize( true ); if ( map.containsKey( key ) ) { dirty(); } return map.remove( key ); } } |
|||||||||||||||||||||||||||||||||||||||||||||