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>