In my Spring MVC application error occurs when castor try to map object which was lazy initilized.
I have Entity class with relation one to many:
@Entity
@Table(name = "a")
public class A implements Serializable {
...
private Set<B> b_set=new HashSet<B>();
@OneToMany(mappedBy = "a", cascade = CascadeType.ALL, orphanRemoval = true, fetch=FetchType.LAZY)
public Set<b> getB_set() {
return b_set;
}
}
Entity with relation many to one
@Entity
@Table(name = "b")
public class B implements Serializable {
...
@ManyToOne
@JoinColumn(name = "fk", insertable=false, updatable=false)
private A a;
}
I use Castor library to map objects to xml.
<mapping>
<class name="package.a">
...
<field name="b_set" type="package.b" collection="set">
<bind-xml name="b_name" node="element"></bind-xml>
</field>
</class>
<class name="package.b">
...
</class>
</mapping>
Entity A has a lot of entities B so I have 2 options. Controller can return entity A with lazy init and can also return A with set of B.
@RequestMapping(value = "/name/{name}", method = RequestMethod.GET)
@ResponseBody
public A findAByName(@PathVariable String name) {
return aService.findByName(name);
}
@RequestMapping(value = "/b/{name}", method = RequestMethod.GET)
@ResponseBody
public A findAByNameWithB(
@PathVariable String name) {
return aService.findByNameWithB(name);
}
In both methods Castor maps returned object and try to map field b_set. In first method there is lazy initialization. Problem occurs when I use first method because castor can not map field b_set:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: package.A.b_set, no session or session was closed
I understand this error but I have no idea how to resolve this situation in smart way. I want to have both methods.
I use Spring 3.1.0 Release, castor 1.3.2 and hibernate-entitymanager 3.6.8 Final
I will be grateful for help.
It happens because your hibenrate session is closed before your HTTP response finished.
To solve it you can do the following:
1) Mark collection as EAGER. 2) use Open Session In View pattern.
You can read more about it here:
https://community.jboss.org/wiki/OpenSessionInView
Spring come with out of the box Open Session In View solution. Which is very easy to use:
http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/orm/hibernate3/support/OpenSessionInViewInterceptor.html