spring-data-jpa报错org.hibernate.LazyInitializationException
spring-data-jpa启动报错:
在使用spring-data-jpa单元测试时getOne()方法报错:
是因为“懒加载”导致的。
解决办法1:在实体类上添加注解:@Proxy(lazy = false),不使用懒加载
package com.wn.domain; import org.hibernate.annotations.Proxy; import javax.persistence.*; @Entity @Table(name = "customer") @Proxy(lazy = false) // 不使用懒加载 public class Customer { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "cust_id") private Long custId; @Column(name = "cust_name") private String custName; @Column(name = "cust_gender") private Boolean custGender; @Column(name = "cust_address") private String custAddress; }
解决方法2:在测试方法上加@Transactional注解
@Test public void testGetOne(){ Customer customer = customerDao.getOne(1L); customer.setCustName("张三"); customerDao.save(customer); }
解决方法3:使用findById()方法
@Test public void testFindOne(){ Customer customer = customerDao.findOne(1L); customer.setCustName("王五"); customerDao.save(customer); }
getOne()方法和findById()方法区别:
首先要知道的时spring-data-jpa会帮我们生成dao层接口的代理对象,getOne()方法和findById()最终都会执行到org.springframework.data.jpa.repository.support.SimpleJpaRepository类中,由该类负责调用jpa原始的EntityManager对象的相关方法来执行;
getOne()方法为延迟加载(懒加载),调用的是EntityManager对象的getReference()方法
public T getOne(ID id) { Assert.notNull(id, "The given id must not be null!"); return this.em.getReference(this.getDomainClass(), id); }
findById()方法是立即加载,调用的EntityManager对象的find()方法
public Optional<T> findById(ID id) { Assert.notNull(id, "The given id must not be null!"); Class<T> domainType = this.getDomainClass(); if (this.metadata == null) { // 调用find()方法 return Optional.ofNullable(this.em.find(domainType, id)); } else { LockModeType type = this.metadata.getLockModeType(); Map<String, Object> hints = this.getQueryHints().withFetchGraphs(this.em).asMap(); // 调用find()方法 return Optional.ofNullable(type == null ? this.em.find(domainType, id, hints) : this.em.find(domainType, id, type, hints)); } }