Spring, Hibernate - many-to-many - LazyInitializationException

I have 2 models.

User:

    @Entity
public class User implements Serializable {
    Long id;
    String name;
    List<Car> cars;
    public User() {

    }
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public List<Car> getCars() {
        return cars;
    }
    public void setCars(List<Car> cars) {
        this.cars = cars;
    }
}

      

Car:

@Entity
public class Car implements Serializable {
Long id;
String mark;
public Car() {

}
public Long getId() {
    return id;
}
public void setId(Long id) {
    this.id = id;
}
public String getMark() {
    return mark;
}
public void setMark(String mark) {
    this.mark = mark;
}
}

      

Displaying fies:

User:

    <hibernate-mapping>
<class name="com.bontade.phone_book.mvc.spring.models.User" table="USERS">
    <id name="id" type="java.lang.Long">
    <column name="ID" />
    <generator class="identity" />
    </id>        
    <property name="name" not-null="true" length="100" type="java.lang.String">
    <column name="NAME" />
    </property>       
    <list name="cars" table="USER_CAR" cascade="all">
    <key>
        <column name="USER_ID" />
    </key>
    <list-index></list-index>
    <many-to-many column="CAR_ID" class="com.bontade.phone_book.mvc.spring.models.Car" />
    </list>        
</class>
</hibernate-mapping>

      

Car:

    <hibernate-mapping>
<class name="com.bontade.phone_book.mvc.spring.models.Car" table="CARS">
    <id name="id" type="java.lang.Long">
    <column name="ID" />
    <generator class="identity" />
    </id>
    <property name="mark"  not-null="true" length="20" type="java.lang.String">
    <column name="MARK" />
    </property>     
</class>
</hibernate-mapping>

      

HomePageController:

public class HomePageController extends AbstractController {
private UserDAO userDAO;
private CarDAO carDAO;

@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request,
        HttpServletResponse response) throws Exception {        
    Car markCar = new Car();
    markCar.setId(null);
    markCar.setMark("111");
    carDAO.saveCar(markCar);

    User mark = new User();
    mark.setId(null);
    mark.setName("mark");
    List a = new ArrayList<Car>();
    a.add(markCar);
    mark.setCars(a);
    userDAO.saveUser(mark);
    List<User> users = userDAO.getAll();
    System.out.println("==" + users.size() + "===");
    System.out.println(users.get(0).getCars().get(0).getMark());

    ...
}
...
}

      

But when I execute the line:

System.out.println(users.get(0).getCars().get(0).getMark());

      

I am getting an error with the following stack trace:

        Hibernate: select user0_.ID as ID0_, user0_.NAME as NAME0_ from USERS user0_
==1==
2011-02-23 17:35:10 org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/PhoneBook] threw exception [Request processing failed; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.bontade.phone_book.mvc.spring.models.User.cars, no session or session was closed] with root cause
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.bontade.phone_book.mvc.spring.models.User.cars, no session or session was closed
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
    at org.hibernate.collection.AbstractPersistentCollection.readElementByIndex(AbstractPersistentCollection.java:173)
    at org.hibernate.collection.PersistentList.get(PersistentList.java:293)
    at com.bontade.phone_book.mvc.spring.controllers.HomePageController.handleRequestInternal(HomePageController.java:59)
    at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
    at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:306)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:244)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:108)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:558)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:379)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:259)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:281)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:662)

      

Did I create the mapping files incorrectly, especially the many-to-many relationship?

0


source to share


1 answer


By default, Hibernate will be lazy load assemblies. In other words, it won't go to the database to get a list of cars until it's needed. This means that the returned object from your dao level will not be initialized with the list of cars until you try to access it. When you try to access it, you are no longer in the session and you get an exception.



You can explicitly disable lazy fetching on this list property by setting lazy = "false" on the hibernate mapping to make sure the entire property is populated before returning from your dao level.

+3


source







All Articles