Hibernate freezes or throws lazy initialization, session or session closed

I am improving the old Spring / Hibernate application and getting stuck. I have a method that reads a file longer than 3,000 lines, each line has a record that must be mapped to something in the database, and then a register must be added to the database (from many to many).

Tables and Relationships

The branch has many products , the product is in many branches .

Products have many products , and Category has many products.

And there are a few more tables that were there and working fine.

The new tables / objects I created by Branch, Product, BranchToProduct .

Products have a set of BranchToProduct objects that have 3 fields

I need to add BranchToProduct objects to the Product set, with 3 fields filled out from the information I get from each line of the file.

I add a simple line and the application throws:

product = productDAO.findByModel (stringModel);

failed to lazily initialize role collection: com.bamboo.catW3.domain.Product.products, session or session not closed

If I go to hibernate mapping (hbm file) and set the relation product_to_products lazy = false, the line works fine alone, but if I try to put it in the file loop, the application always hangs on the processed 18th line, it does not matter which file I I use either the order of the contents, the console stops working, I have to close java, killing the process.

In any case, when debugging, I get a lot of HQL for a simple find, 13 HQL lines until I get my error when lazy = true, and LOT lines when I use lazy = false and put it in a loop.

I think I should try to fix the problem with lazy = true.

This situation makes me think:

1.- When lazy = true. Why can't I run one line of this command with this method, but it works fine with other methods of the class?

By the way, this is a class called CatalogFacade that implements methods of another class: (CategoryFacade, ContainerFacade, ProductFacade, ProductOptionFacade, ProductStatusFacade, UserFacade, EmailFacade, FileFacade, BranchOfficeFacade)

This is the code for productDao.find ():

public Product find(Integer id) throws DataAccessException { Product product= (Product) super.find(Product.class, id); if(product!=null){ product.setProductAttributes(new TreeSet<ProductAttribute>(product.getProductAttributes())); for (Product ptp : product.getProducts()){ ptp.setProductAttributes(new TreeSet<ProductAttribute>(ptp.getProductAttributes())); } } 

This line throws an exception, the latter for:

 pptp.setProductAttributes(new TreeSet<ProductAttribute>(ptp.getProductAttributes())) 

in the Intelij debugger, I see that the object is incorrectly formed from the request:

product.getProducts () = { org.hibernate.collection.PersistentSet@4312 } unable to evaluate the expression The method threw an org.hibernate.LazyInitializationException.

No matter what other attributes. This product does not even contain other products in the database.

UPDATE

GETTING DEPTH on a situation inside

product.find (integer)

In the line before I get the exception, we can see on debugging that the array product.products has an error, instead of the value you can see lazyInitialitationException. As usual , if I call it from another method, the array finds. Therefore, it cannot be EVEN inside it , although the method receives only Integer.

In addition, we found that this happened throughout the entire life cycle of the application, sometimes employees replicated a method similar to it, but changing it, setting null for this damaged array. Therefore, I am 100% sure that this application consumes more resources than it should be.

It has views in Flex and later views in JSTL, where they are created, and depending on who calls the methods, exceptions are used in different ways for the same methods.

Adding more information. This is how produt.find is implemented in AbstractDAOImpl:

 public final Object find(Class clazz, Integer id) throws DataAccessException{ return getHibernateTemplate().get(clazz,id); } 

and this is my transaction manager configuration, the annotation method described in the first answer with fillip didn't work:

 <bean id="catalogFacade" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager"> <ref local="transactionManager"/> </property> <property name="target"> <ref local="catalogFacadeTarget"/> </property> <property name="transactionAttributes"> <props> <prop key="add*">PROPAGATION_REQUIRED</prop> <prop key="save*">PROPAGATION_REQUIRED</prop> <prop key="update*">PROPAGATION_REQUIRED</prop> <prop key="delete*">PROPAGATION_REQUIRED</prop> <prop key="remove*">PROPAGATION_REQUIRED</prop> <prop key="get*">PROPAGATION_SUPPORTS,readOnly</prop> <prop key="find*">PROPAGATION_SUPPORTS,readOnly</prop> <prop key="contains*">PROPAGATION_SUPPORTS,readOnly</prop> <prop key="login*">PROPAGATION_SUPPORTS,readOnly</prop> </props> </property> </bean> 
+7
source share
3 answers

You get a lazy initialization exception because your session closes before you access the variables of the Product element. When the following line is executed:

 Product product= (Product) super.find(Product.class, id) 

Hibernate opens sessions, retrieves what you are looking for, then closes the session. Any fields that have lazy = true are not received at this time; instead, these fields are populated by the proxy. When you try to get the actual value of the proxy object, it will try to return to the database using an active session to retrieve the data. If the session is not found, you get the exception that you see. Setting lazy = true has advantages because it prevents the entire chart of the object from loading immediately; nested objects remain alone until you specifically ask for them.

There are two common methods to solve your problem. The first one you already defined that sets lazy = false. This is normal if the product always has product attributes and you usually use the product and it combines the attributes. If you often only need a Product object without its attributes, you create an unnecessary load on the database.

The second method is to mark the method as transactional using Spring annotations.

 @Transactional public Product find(Integer id) throws DataAccessException { } 

A few notes:

  • You will need additional configuration for transactions to work (the @Transactional annotation is not enough). See here for more information.
  • Best practices dictate that you comment on methods at the service level, not at the data access level.
+19
source

I had the same problem earlier, and I fixed it using different sleep mode methods. I use

 getHibernateTemplate().loadAll(class) 

to get everything something, and

 getHibernateTemplate().get(class, id) 

to find one thing. I use both of them without any problems. I found that .find () gives me that the session was a closed error.

I really did not look why this is true.

The only other option that I can think of besides using another method is to open and close sessions on my own, but I suppose you prefer not to.

0
source

Replace the boot method with the get method.

I learned after doing more research that the loading method does not actually load the object from the database. Instead, it automatically returns a proxy object. Load assumes that the object has already "received with get" from the database and is in the cache.

Just use get instead of loading if you want to make sure you are in the database and make sure you know the difference between the two methods.

Source: this spring comment

I personally tested this, and rightly so, the boot method does not extract all the necessary data from the database. Using the fix for my problem.

0
source

All Articles