springDataJpa懒加载问题
springDataJpa懒加载
现在我有一个员工的domain,员工里有一个部门,部门是另外的一个实体。为了推迟和数据库交互的时间,推迟到真正需要这个对象数据的时候,提高系统的性能,,现在部门我要使用懒加载。
延迟加载(lazy load) (也称为懒加载,也叫延迟实例化,延迟初始化等)主要表达的思想就是:把对象的创建延迟到使用的时候创建,而不是对象实例化的时候创建。延迟加载机制是为了避免一些无谓的性能开销而提出来的,这种方式避免了性能的浪费。所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。
@Entity
@Table(name = "employee")
public class Employee extends BaseDomain {
private String username;
private String password;
private String email;
private Integer age;
private String headImage = "/images/head/1.jpg";
//部门使用懒加载
@ManyToOne(fetch = FetchType.LAZY)
//部门对应employee表中的department_id字段
@JoinColumn(name = "department_id")
private Department department;
//省略getter和setter,tostring
no session问题
如果我们只是这样做就会产生 一个no-session的问题,No Session found for current thread],那么这个问题是怎么产生的呢?
当使用hibernate框架操作数据库的时候,如果做查询的话会有立即加载(get)和延迟加载(load)的区别,延迟加载表示,当你查询某个数据(假设是对象)的时候,hibernate不会立马发送sql语句,而是当我们调用这个对象的属性的时候,也就是真正使用查询出来的数据的时候才会发送sql语句去一级缓存(即session,这里的session和域对象session没有半毛钱关系)中获取,但是正常这个session的开启核关闭是在service层执行的,但是我们真正使用查询的对象的数据时,是在web层,但是这个时候session已经关闭,就会报no-session异常。
解决办法
我们只需要在web.xml中配置一个filter。
<!--解决懒加载no session问题-->
<filter>
<filter-name>openEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>openEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
no Serializable
这时候就会产生另外一个问题,
No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ),
这是因为部门对象是一个代理对象,懒加载产生的对象都是代理对象,所以其中有些属性是不可序列化的,提供两种解决方案:
一劳永逸
新建一个类:
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
/**
* 自定义映射,解决Serializa的问题
*/
public class CustomMapper extends ObjectMapper {
public CustomMapper() {
this.setSerializationInclusion(JsonInclude.Include.NON_NULL);
// 设置 SerializationFeature.FAIL_ON_EMPTY_BEANS 为 false
this.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
}
}
再在spring-mvc.xml中配置;
<!-- Spring MVC 配置 -->
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json; charset=UTF-8</value>
<value>application/x-www-form-urlencoded; charset=UTF-8</value>
</list>
</property>
<!-- No serializer:配置 objectMapper 为我们自定义扩展后的 CustomMapper,解决了返回对象有关系对象的报错问题 -->
<property name="objectMapper">
<bean class="com.cl.easysell.common.CustomMapper"></bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
注解
这个错我们可以到网上搜索,SpringMVC与Jpa集成的时候(有懒加载)就会出现这个问题
(这是因为你需要序列化对象有一个属性是一类类型,而你使用了Hibernate的延迟加载所以这里是个Hibernate的代理对象。该代理对象有些属性不能被序列化所以会报错。)
在类上加属性:生成的时候把这个字段忽略了:
@JsonIgnoreProperties(value={“hibernateLazyInitializer”,“handler”,“fieldHandler”})