How to fix org.hibernate.LazyInitializationException - could not initialize proxy - no Session
What is wrong here is that your session management configuration is set to close session when you commit transaction. Check if you have something like:
<property name="current_session_context_class">thread</property>
in your configuration.
In order to overcome this problem you could change the configuration of session factory or open another session and only than ask for those lazy loaded objects. But what I would suggest here is to initialize this lazy collection in getModelByModelGroup itself and call:
Hibernate.initialize(subProcessModel.getElement());
when you are still in active session.
And one last thing. A friendly advice. You have something like this in your method:
for (Model m : modelList) {
if (m.getModelType().getId() == 3) {
model = m;
break;
}
}
Please insted of this code just filter those models with type id equal to 3 in the query statement just couple of lines above.
Some more reading:
session factory configuration
problem with closed session
How to solve the “failed to lazily initialize a collection of role” Hibernate exception
If you know that you'll want to see all Comment
s every time you retrieve a Topic
then change your field mapping for comments
to:
@OneToMany(fetch = FetchType.EAGER, mappedBy = "topic", cascade = CascadeType.ALL)
private Collection<Comment> comments = new LinkedHashSet<Comment>();
Collections are lazy-loaded by default, take a look at this if you want to know more.
Hibernate LazyInitializationException using Spring CrudRepository
So you can do it by initializing businessCategoruSet in Service so instead of using @Transactional
in Repository use it in Service.
Let write some method like get business by id or list of business in repository and access that method from service.
@Transactional
public Class BusinessService{
@resource
BusinessRepository businessRepository;
public Business getBusiness(){
Business business = businessRepository.getBusiness();
//Here you should initialize BusinessCategorySet
Object object = business.getBusinessCategoriesSet().size();
}
}
For more details about @Transactional
Refer this link
LazyInitializationException in JPA and Hibernate
Thanks to Shailendra I started to look closely at the transaction and noticed that the transaction was never starting. With that information I did some investigation and found this: Spring @Transaction not starting transactions. I put <tx:annotation-driven/>
in my servlet-context.xml file and suddenly the transaction for logDOI started up and everything worked correctly; I no longer got the LazyInitializationException. I am not at all clear as to why that worked. Any information on that would be appreciated.
Update:
I figured it out. A critical piece of my problem was in the servlet-context.xml file. This is what it looked like
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="org.myapp.doi" />
</beans:beans>
The major problem was in that context:component-scan line. Spring MVC creates two context which beans are instantiated in: the root application context defined with the contextConfigLocation parameter in the web.xml file and the servlet context defined in the DispatcherServlet in the web.xml file. The servlet context could see the application context but not the other way around. Now, as a result of context:component-scan being defined in the servlet context and scanning the entire application namespace, my DAO was being instantiated in the servlet context. However, the transaction annotation scanning was being done in the application context and the AOP proxy stuff for it could not be done from there. Simply modifying the context:component-scan in the servlet context to scan only the MVC controllers (<context:component-scan base-package="org.myapp.doi.web" />
fixed everything; the DAO was being created in the application context and properly setup for transactions.
Hibernate Lazy Initialization Exception for loading lazy list
I’m going to start by assuming you want your collection to be lazy loaded.
Hibernate’s session can be closed in a lot of contexts, and once the session is closed, it won’t be able to fetch any lazy loaded collections.
Generally Hibernate is very good at keeping sessions open for the lifecycle of HTTP threads in a web app context (Spring’s “open session in view”). Reasons the session could be closed include that the object was handed off from one thread to another, or the object was cached and then accessed by another thread.
But it can be more difficult if your code is running in a job or a non-web application context.
Fixes
1. Create a repository method to explicitly fetch the collection
Using @Query
and join fetch
, add a repository method that explicitly eager-loads the collection.
2. Call .toString() on the collection after fetching the object.
This is a nasty hack that I’ve seen many people use in the real world before. Basically, before caching the object or handing it off to an executor or somewhere where it would be accessed by another thread, call .toString() on the collection to load it. Usually leave a comment explaining why.
3. Add @Transactional to a method that is both fetching the data and accessing the collection
This has many implications other than keeping the session alive (e.g. database operations succeed and fail together), but can be a quick fix to keep the session alive in for example a job method.
Hope this helps.
Related Topics
How to Get the Filename Without the Extension in Java
In Log4J, Does Checking Isdebugenabled Before Logging Improve Performance
Convert Base64 String to Image
How to Find the Jvm Version from a Program
Java.Io.Ioexception: Mark/Reset Not Supported
Run Java Application at Windows Startup
Error: Javafx Runtime Components Are Missing, and Are Required to Run This Application with Jdk 11
Differencebetween the Float and Integer Data Type When the Size Is the Same
How to Specify a Byte Literal in Java
What Is the Fastest Way to Compare Two Sets in Java
How Does Java's System.Exit() Work with Try/Catch/Finally Blocks
Should Private Helper Methods Be Static If They Can Be Static
Should I Use String.Isempty() or "".Equals(String)