I\'m enhancing an old Spring/Hibernate application and im stuck. I have a method that reads a file 3000+ lines long, each line has a record which has to be compared with somethi
You're getting a lazy initialization exception because your session is being closed before you access Product's member variables. When the following line is executed:
Product product= (Product) super.find(Product.class, id)
Hibernate opens a sessions, retrieves what you're looking for, then closes then session. Any fields that have lazy=true are not retrieved at this time; instead, these fields are populated by proxies. When you try to retrieve the actual value of proxied object, it will attempt to go back to the database using the active session to retrieve the data. If no session can be found, you get the exception that you're seeing. Setting lazy=true has advantages because it prevents the entire object graph from being loaded immediately; nested objects are left alone until you specifically ask for them.
There are two common techniques to deal with your problem. The first you've already identified, which is setting lazy=false. This is fine if a product always has product attributes, and you typically use a product and it's attributes together. If you often need just the Product object without its attributes, you're creating unnecessary database load.
The second technique is to mark a method as transactional using Spring annotations.
@Transactional
public Product find(Integer id) throws DataAccessException {
}
A few notes:
I've had the same problem before, and fixed it by using different hibernate methods. I use
getHibernateTemplate().loadAll(class)
for getting all of something, and
getHibernateTemplate().get(class, id)
to find a single thing. Both of those I use with no problems. I found that .find() gives me that session was closed error.
I haven't really looked into why this is though.
The only other option I can think of aside from using another method is to open and close sessions yourself, but I presume you prefer not to do that.
Replace the load method with the get method..
I found out after doing more research that the load method doesn't really load the object from the database. Instead it automatically returns a proxy object. Load assumes the object has already been "gotten with get" from the database and is in the cache.
Just use get instead of load if you want to make sure you hit the database, and make sure you know the difference between these 2 methods.
Source: this spring forum comment
I've personally test this and it is right, the load method don't retrieve all the wanted data from the DB. Using get fixed my problem.