An object I mapped with hibernate has strange behavior. In order to know why the object behaves strangely, I need to know what makes that object dirty. Can somebody help and give me a hint?
The object is a Java class in a Java/Spring context. So I would prefer an answer targetting the Java platform.
Edit: I would like to gain access to the Hibernate dirty state and how it changes on an object attached to a session. I don't know how a piece of code would help.
As for the actual problem: inside a transaction managed by a Spring TransactionManager I do some (read) queries on Objects and without doing an explicit save on these Objects they are saved by the TransactionManager because Hibernate thinks that some of these (and not all) are dirty. Now I need to know why Hibernate thinks those Objects are dirty.
I would use an interceptor. The onFlushDirty method gets the current and previous state so you can compare them. Implement the Interceptor interface and extend EmptyInterceptor, overriding onFlushDirty. Then add an instance of that class using configuration.setInterceptor (Spring may require you to do this differently). You can also add an interceptor to the session rather than at startup.
Here is the documentation on interceptors.
create a Test Case or similar, so you can reproduce the problem with a single click.
enable logging for org.hibernate check the logging for the string "dirty" (actually you don't need all of org.hibernate, but I don't know the exact logger.
Find to spots in the program, one where the entity is not dirty, one where it is dirty. Find the middle of the code between the two points, and put a logging statement there, for logging the isdirty Value. Continue with the strategy until you have reduced the code to a single line.
Check out the hibernate code. Find the code that does the dirty checking. Use a debugger to step through it.
Assuming that the state of the object cannot be accessed directly (e.g. no public or package protected fields) and is not fiddled with by reflection, you can put a breakpoint at the start of all of the object's methods and run through the scenario that makes the object dirty in the debugger.
Related
I have some old code that basically uses singleton services inside entities to perform some tasks, and to start cleaning up thinks, I want to inject those services on entities, so at least I can break that hard dependencies for now.
I'm trying to find some place in Hibernate where I can control entities instantiation, by now I've found some possible hooks, like:
- org.hibernate.tuple.Instantiator
- org.hibernate.Interceptor
I need to control that instantiation when an object is first loaded from database, as well as when it's loaded from cache... Also, maybe a global PreLoadEvent may help, I just need to make sure that when an object is returned from Hibernate, it has all it's (service) dependencies injected (spring is already here).
Can someone please point me to where to continue the search?
You could use #Configurable annotation,
see this blog post for more info.
Well, after some testing, an instance of org.hibernate.event.PreLoadEventListener does the trick.
It gets called always, no matter where the instance came from. This way I'm not controlling instantiation, but at least I have a place to inject dependencies befor the instance is returned to client code.
Thanks all for your time!
I was wondering if there was a way to tell Hibernate to generate some kind of console warning when it has too many objects of a certain type in the session cache. I would like to do this for load testing as we have OutOfMemoryException problems on occasion with BLOB loading from Oracle.
We are still using Hibernate 3.6.10 for now. Our best approach for this testing at the moment is to just generate more data than the system would be able to handle in a normal use case and try to load the parent object and see if it crashes. Doing it this way just feels kind of bad.
Any suggestions are welcome.
One note that I forgot to mention is that this "logging" idea is something I would like to be able to leave in production code to pinpoint specific problems.
- EDIT -
Here's an example of what I'm trying to do:
Say I have an #Entity ClassX that has a lazy loaded list of #Entity ClassY objects. Some how, I would like to have a log message spit out when 100 or more instances of ClassY are loaded into the session cache. This way, during development I can load a ClassX object and notice if I (or another developer on the team) happen to be accessing that list when I shouldn't be.
You could attach an Interceptor to listen to object load events, maintaining a count for each unique entity type and logging a warning whenever it goes past a certain threshold. The documentation shows you how to define a session-scoped interceptor, by passing it in at creation time:
Session session = sf.openSession( new AuditInterceptor() );
Most likely you're not creating your Session manually so this may not be helpful, but possibly the way that you are declaring your session has some way of passing an Interceptor through.
It's easier to declare a SessionFactory-scoped Interceptor but it doesn't seem to give you any reference back to the Session that the object is being created within, otherwise you'd be able to knock up some sort of counter in a WeakHashMap (with Session as the key so that you don't leak memory). If you're using the default Thread-local session strategy then you could always ask sessionFactory.getCurrentSession().
I'm having a difficult time understanding Spring Transactions. First off, I am trying to use as little of Spring as possible. Basically, I want to use #Transactional and some of its injection capabilities with JPA/Hibernate. My transactional usage is in my service layer. I try to keep them out of test cases. I use CTW and am spring-configured. I have component scan on the root of my packages right now. I also am using Java configuration for my datasource, JpaTransactionManager, and EntityManagerFactory. My configuration for the JpaTransactionFactory uses:
AnnotationTransactionAspect.aspectOf().setTransactionManager( txnMgr );
I do not use #EnableTransactionManagement.
Unfortunately, I'm having a hard time understanding the rules for #Transactional and can't find an easy page that describes them simply. Especially with regards to Session usage. For example, what if I want to use #Transactional on a class that does not have a default no-arg constructor?
The weirdest problem I'm having is that in some of the POJO service classes Transacitonal works great while in others I can see the transactions being created but operations ultimately fall saying that there is "no session or the session has been closed". I apologize for not having code to reproduce this, I can't get it down to a small set. This is why I am looking for the best resources so I can figure it out myself.
For example, I can have a method that gets a lazily fetched collection of children, iterates through it and puts it into a Set and returns that set. In one class it will work fine while in another class also marked with #Transactional it will fail while trying to iterate through the PersistentSet saying that there is no session (even though there IS a transaction).
Maybe this is because I create both of these service objects in a test case and the first one is somehow hijacking the session?
By the way, I have read through the spring source transaction documents. I'm looking for a clear set of rules and tips for debugging issues like this. Thanks.
Are you sure you loaded your parent entity in the scope of the very transaction where you try to load the lazy children? If it was passed in as parameter for example (that is, loaded from outside your #Transactional method) then it might not be bound to a persistence context anymore...
Note that when no #Transactional context is given, any database-related action may have a short tx to be created, then immediately closed - disabling subsequent lazy-loading calls. It depends on your persistence context and auto-commit configurations.
To put it simply, the behaviour with no transactional context being sometimes unexpected, the ground rule is to always have one. If you access your database, then you give yourself a well-defined tx - period. With spring-tx, it means all your #Repository's and #Services are #Transactional. This way you should avoid most of tx-related issues.
I am getting this exception in a controller of a web application based on spring framework using hibernate. I have tried many ways to counter this but could not resolve it.
In the controller's method, handleRequestInternal, there are calls made to the database mainly for 'read', unless its a submit action.
I have been using, Spring's Session but moved to getHibernateTemplate() and the problem still remains.
basically, this the second call to the database throws this exception. That is:
1) getEquipmentsByNumber(number) { firstly an equipment is fetched from the DB based on the 'number', which has a list of properties and each property has a list of values. I loop through those values (primitive objects Strings) to read in to variables)
2) getMaterialById(id) {fetches materials based on id}
I do understand that the second call, most probably, is making the session to "flush", but I am only 'reading' objects, then why does the second call throws the stale object state exception on the Equipment property if there is nothing changed?
I cannot clear the cache after the call since it causes LazyExceptions on objects that I pass to the view.
I have read this:
https://forums.hibernate.org/viewtopic.php?f=1&t=996355&start=0
but could not solve the problem based on the suggestions provided.
How can I solve this issue? Any ideas and thoughts are appreciated.
UPDATE:
What I just tested is that in the function getEquipmentsByNumber() after reading the variables from list of properties, I do this: getHibernateTemplate().flush(); and now the exception is on this line rather then the call to fetch material (that is getMaterialById(id)).
UPDATE:
Before explicitly calling flush, I am removing the object from session cache so that no stale object remains in the cache.
getHibernateTemplate().evict(equipment);
getHibernateTemplate().flush();
OK, so now the problem has moved to the next fetch from DB after I did this. I suppose I have to label the methods as synchronized and evict the Objects as soon as I am finished reading their contents! it doesn't sound very good.
UPDATE:
Made the handleRequestInternal method "synchronized". The error disappeared. Ofcourse, not the best solution, but what to do!
Tried in handleRequestInternal to close the current session and open a new one. But it would cause other parts of the app not to work properly. Tried to use ThreadLocal that did not work either.
You're mis-using Hibernate in some way that causes it to think you're updating or deleting objects from the database.
That's why calling flush() is throwing an exception.
One possibility: you're incorrectly "sharing" Session or Entities, via member field(s) of your servlet or controller. This is the main reason 'synchronized' would change your error symptoms.. Short solution: don't ever do this. Sessions and Entities shouldn't & don't work this way -- each Request should get processed independently.
Another possibility: unsaved-value defaults to 0 for "int" PK fields. You may be able to type these as "Integer" instead, if you really want to use 0 as a valid PK value.
Third suggestion: use Hibernate Session explicitly, learn to write simple correct code that works, then load the Java source for Hibernate/ Spring libraries so you can read & understand what these libraries are actually doing for you.
I also have been struggling with this exception, but when it continued to recur even when I put a lock on the object (and in a test environment, where I knew I was the only process touching the object), I decided to give the parenthetical in the stack trace its due consideration.
org.hibernate.StaleObjectStateException: Row was updated or deleted by
another transaction (or unsaved-value mapping was incorrect):
[com.rc.model.mexp.MerchantAccount#59132]
In our case it turned out that the mapping was wrong; we had type="text" in the mapping for one field that was a mediumtext type in the database, and it seems that Hibernate really hates that, at least under certain circumstances. We removed the type specification altogether from the mapping for this field, and the problem was resolved.
Now the weird thing is that in our production environment, with the supposedly problematic mapping in place, we do NOT get this exception. Does anybody have any idea why this might be? We are using the same version of MySQL - "5.0.22-log" (I don't know what the "-log" means) - in dev and production envs.
Here are 3 possibilities (as I do not know exactly, which kind of hibernate session handling you are using). Add one after another and test:
Use bi-directional mapping with inverse=true between parent object and child object, so the change in parent or child will get propagate to the other end of relation properly.
Add support for Optimistic Locking using TimeStamp or Version column
Use join query to fetch the whole object graph [ parent+children] together to avoid the second call altogether.
Lastly, if and only if nothing works:
Load the parent again by Id (you have that already) and populate modified data then update.
Life will be good! :)
This problem was something that I had experienced and was quite frustrating, although there has to be something a little odd going on in your DAO/Hibernate calls, because if you're doing a lookup by ID there is no reason to get a stale state, since that is just a simple lookup for an object.
First, make sure all your methods are annotated with #Transaction(required=true) // you'll have to look up the exact syntax
However, this exception is usually thrown when you try to make changes to an object that has been detached from the session it was retrieved from. The solution to this is often not simple and would require more code posted so we can see exactly what is going on; my general suggestion would be to create a #Service that performs these kinds of things within a single transaction
If you have a call in a Dao method like (pseudo code):
return ..getHibernateTemplate( get by id );
Now say that entity has a lazy-loaded collection. Once you return from your Dao using the hibernateTemplate helper method, how come the session stays in scope and allows you to lazy-load a collection?
Is the session initialized and committed at a global level on a per request basis?
Update
Please explain where exactly the call to 'getcurrentsession' is made, and when is it actually closed/committed?
From what I understand, the spring framework has to handle the session lifecycle, where does it do this? at what point the in the requests lifecycle?
It is handling the Unit of work also, where/how?
Once you return from your Dao using the hibernateTemplate helper method, how come the session stays in scope and allows you to lazy-load a collection?
Because the Session hasn't been closed yet and your entity is thus still Persistent (as opposed to the Detached object state). As long as your entity has not been detached, you can lazy load collections and proxies. See chapter 10.1. Hibernate object states for more details on these states (it's very important to understand them and the terminology used).
Is the session initialized and committed at a global level on a per request basis?
With web applications, it's typically per request. As mentioned in the javadoc of HibernateTemplate:
Lazy loading will also just work with an open Hibernate Session, either within a transaction or within OpenSessionInViewFilter/Interceptor.
And if you look at the javadoc of OpenSessionInViewFilter or OpenSessionInViewInterceptor, you'll read that they are slightly different but both binds a Hibernate Session to the thread for the entire processing of the request and provide an implementation of the "Open Session in View" pattern.
Please explain where exactly the call to 'getcurrentsession' is made, and when is it actually closed/committed?
You could look at the sources and use a debugger for this you know :) Look at HibernateTemplate, more precisely the doExecute() method, this is where the session is obtained. For the close/commit, look at the previously mentioned OpenSessionInViewFilter/Interceptor, both have methods for this purpose.
From what I understand, the spring framework has to handle the session lifecycle, where does it do this? at what point the in the requests lifecycle?
I think I covered that part: the session is created at the start of a request and closed at the end.
It is handling the Unit of work also, where/how?
I'm not sure to get this one. To me, Hibernate's Session is an implementation of the unit of work pattern. So this question is actually the same as the previous one.
PS: I provided some links that show that everything is actually clearly documented. Spring and Hibernate have extremely nice documentation and javadoc. Take advantage of that, look at them by yourself, look at the code by yourself, use your debugger, you'll learn a lot more.
Hibernate returns a custom implementation of the collection which does the loading only whenever any of the collection methods is been invoked. This collection has been constructed with the session as argument.
Do a sysout of getSomeCollection().getClass() to see which Hibernate custom class it is and check the appropriate javadocs/sourcecode to see how exactly they did it.
If you ever questioned the sense/use/value of interfaces and declaring against interfaces, now, this is a good example. You didn't see anything from it, did you? ;)
Is the session initialized and committed at a global level on a per request basis?
It's typically initialized on a per-request basis using ... (wait for it)
Please explain where exactly the call to 'getcurrentsession' is made, and when is it actually closed/committed?
It: org.springframework.orm.hibernate3.HibernateTemplate
... is the heart of Spring's integration with Hibernate. HibernateTemplate will initialize the session as necessary (or pull an already existing one from a ThreadLocal store) and provide it to any callbacks you give to the HibernateTemplate#execute* methods.
From what I understand, the spring framework has to handle the session lifecycle, where does it do this? at what point the in the requests lifecycle?
Also done by HibernateTemplate, and ...
It is handling the Unit of work also, where/how?
Done by HibernateTransactionManager, if you have one configured in your applicationContext.
If this was a web application I would use the OpenSessionInViewFilter