解决延迟加载的异常(noSession)
1、noSession异常的原因
在使用Jpa时,当表与表之间有关联关系的时候,我们在设计表的关联关系,使用注解设置的时候,如果在注解上添加了一个***fetch = FetchType.LAZY***属性,就是设置为一个懒加载的模式,即什么时候需要使用这个数据,什么时候在在去查询,这个有时候就会出现问题:下面以Employee员工和Dept部门为例
员工与部门是多对一的关系,我们在员工表设置单向多对一关系:
@Entity
@Table(name="employee")
public class Employee extends BaseDomain{
@Id
@GeneratedValue
private Long id; //主键
private String username;
private String email;
@ManyToOne(fetch = FetchType.LAZY) //设置为懒加载的模式
@JoinColumn(name="department_id")
private Dept dept;
如上面代码我们在设置关系的时候,使用@ManyToOne添加这个属性就设置为懒加载,后面我在页面上拿数据的时候会报错:
报错信息:500错误,no-Session,即没有会话,因为我们在后台查询到employee的数据以后要在前台显示,在显示部门的时候,我们需要显示部门名称,但是因为懒加载,所以查询employee的时候并没有查询部门的数据,然后前台在展示的需要将部门数据转换为部门名称,此时会发出一条新的请求去查询部门的数据,但是我们在service层操作完以后会将事务关闭,所以这个时候发出请求会报上面的500错误。
2、如何解决
2.1 在web.xml配置文件设置openentityManger过滤器
<!-- 加上OpenEntityManager -->
<filter>
<filter-name>openEntity</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>openEntity</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
上面设置完以后,运行还是会报错:500错误,没有序列化
这是因为你需要序列化对象有一个属性是一类类型,而你使用了Hibernate的延迟加载所以这里是个Hibernate的代理对象。该代理对象有些属性不能被序列化所以会报错。
2.2 要解决上面的报错,使用@JsonIgnoreProperties设置一下
在我们关联的字段即设置了@ManyToOne的注解的字段上设置一下上面注解,代码如下:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="department_id")
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
private Dept dept;
总结:通过上面就可以将解决懒加载出现的问题,其实解决问题的思路:就是把事务提到controller层管理,因为事务一般都是在service层操作完以后就会关闭,我们配置的那个过滤器就是将开启事务管理的过滤器。
但将事务都提到Controller层进行管理,是非常消耗性能的,而且在多对一关系中,我们肯定是要使用到一方数据的,所以完全没有必要设置懒加载,在实际开发中不建议你这样使用