简体   繁体   中英

Spring + Hibernate : LazyInitializationException

I am getting the LazyInitializationException when i try to retrieve information inside a POJO.

User.java

public class User  implements java.io.Serializable {

 private Set groups = new HashSet(0);

    public Set getGroups() {
       return this.groups;
   }

}

UserController.java

@RequestMapping(value = "/home", method = RequestMethod.GET)
public ModelAndView getHome(HttpServletRequest request) throws Exception {
    ModelAndView mv;
    User user = SessionUtil.getSessionUser(request);
    if (user == null) {
        mv = new ModelAndView("redirect:/user/login");
    } else {
        mv = new ModelAndView("home");
        user = this.userService.getUserById(user.getId());

        // Exception here 
        Set<Group> groups = user.getGroups();
        mv.addObject("groups", groups);

        // This work fine
        List<Group> invitation_groups = this.userService.getInvitationGroups(user);
        mv.addObject("invitation_groups", invitation_groups);

        // This work fine
        List<Group> subscription_groups = this.userService.getSubscriptionGroups(user);
        mv.addObject("subscription_groups", subscription_groups);

    }

    return mv;
}

Database

=====
-User-
id
login

=====
-Goup-
id
user (Foreign key to user)


at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:285)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
at model.pojo.User_$$_jvst464_2.getGroups(User_$$_jvst464_2.java)
at controller.UserController.getHome(UserController.java:151)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

I think I understand why I get this exception : I always close the HibernateSession after all my transaction in my DAO so the session can't be open for the POJO request.

In an other hand user.getLogin() for exemple works. I think i dont understand well where the problem is. Is that because it uses a foreign key ?

I think i found a workaround here but I dont know how to implement it and if it's really efficient.

I know that if I remove session.close() from my DAO it will works but it's not the solution.

I hope someone can help me. Thanks.

Solution

  1. Remove all the hand made transactions
  2. Add transactionnal annotation
  3. User OpenSessionInView filter.

Thanks guys.

Why are you handling your session manually? Do you need that?

If not, you should use OpenSessionInView pattern. It will keep your session open until the request ends, but, be careful, you can run in trouble with lots of queries made to the database because the lazy load of collections. So whenever you can, try to fetch your data eagerly if you know that they will be used.

Your user.getLogin() returns a string right? Even if it was the one side of a relationship mapping, it would be fetched eagerly by default.

I'm not used with spring but I think spring has an OpenSessionInView filter to manage your session.

Its normal to handle transaction in API layer and using DTO, So you have: API -> Service -> DAO.

But since you only have transactional in DAO its probably okai, but then you have to take care of lazyload object in DAO., before transaction is closed.

// after this the transaction is open and closed, user object is hibernate jpa entity you usually get this.
user = this.userService.getUserById(user.getId());

The simplest solution is to loop through and do getId() in DAO, before returning user.

Set<Group> groups = user.getGroups();

 for (Group group in groups){
   group.getId(); 
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM