Spring MVC 3.1.2 + Jackson 2: LazyInitializationException on lazy collection initialization - session or session closed

I'm crazy about the error I'm using Spring MVC 3.1.2 and Jackson 2.

I have the following class model:

@Entity @Table(name = "USER") @JsonIgnoreProperties(ignoreUnknown=true) public class User implements Serializable { @Id @SequenceGenerator(name = "USER_ID", sequenceName = "USER_ID_SEQ", allocationSize = 1) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USER_ID") private Long id; @Column(length = 50, nullable = false) private String firstName; @Column(length = 50, nullable = false) private String lastName; @ManyToMany @JoinTable(name = "FRIENDS", joinColumns = @JoinColumn(name = "personId"), inverseJoinColumns = @JoinColumn(name = "friendId") ) @JsonManagedReference private List<User> friends; @ManyToMany @JoinTable(name="FRIENDS", joinColumns=@JoinColumn (name="friendId"), inverseJoinColumns=@JoinColumn (name="personId") ) @JsonIgnore private List<User> friendOf; // Other attributes and methods... } 

When I get one user instance, it is correctly serialized by Jackson. But when I try to get a User instance that contains friends, the following exception is thrown:

org.hibernate.LazyInitializationException: failed to lazily initialize role collection: com.frooid.model.User.friends, session or session closed

I get this instance using one HQL:

 select u from User u left join fetch u.friends f where u.id = :id 

Thanks everyone!

+3
source share
3 answers

Try using OpenSessionInViewFilter , while it is designed to access lazy initialized fields in your view, it can keep the session open so that Jackson can access the collection.

OpenSessionInViewFilter associates a Hibernate session with a thread for all request processing. Designed for the "Open Session in View" template, i.e. Allow lazy loading in web views even though the original transactions are already completed.

In Web.xml

 <filter> <filter-name>OpenSessionInViewFilter</filter-name> <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class> </filter> <filter-mapping> <filter-name>OpenSessionInViewFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> 

API Documentation

+5
source

ToMany mappings load lazily by default. This means that your users' jokes will only be loaded from the database when you call the friends list method.

This lazy loading can only happen when the session used to load the user is open. Therefore, if you return the user from your transactional method without loading the list of friends, the session will be closed and an attempt to load the list of friends will result in the exception that you get.

So, if the client needs a freinds downloadable list, he selects friends using HQL or forcefully initializes the list inside the service method by calling the method in the list or calling Hibernate.initialize(user.getFriends()) .

EDIT: since you have a selection in your HQL, it should work. Another problem is that bidirectional communication is displayed twice: once in the friends field and once in the friendOf field. One of these associations should be marked as the inverse of the other using the mappedBy attribute:

 @ManyToMany(mappedBy = "friends") @JsonIgnore private List<User> friendOf; 
+5
source

I had a similar problem. The approach was to create a new class (view) and add this class to @JsonView({NewClass1.class,NewClass2.class}) for each property in Entity where your properties are defined. You can select the variables you want to load as part of your answer and include the class in @JsonView . Just as easy!

0
source

Source: https://habr.com/ru/post/1484275/


All Articles