在使用spring-data-jpa单元测试时getOne()方法报错:
查找资料发现是因为“懒加载”导致的;
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;
}
package com.wn.test;
import com.wn.dao.CustomerRepository;
import com.wn.domain.Customer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import java.util.Optional;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDataJpaTest {
@Autowired
CustomerRepository repository;
/**
* 根据id查询一个
*/
@Test
@Transactional
public void testFindOne() {
Customer customer = repository.getOne(2L);
System.out.println(customer);
}
}
package com.wn.test;
import com.wn.dao.CustomerRepository;
import com.wn.domain.Customer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import java.util.Optional;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDataJpaTest {
@Autowired
CustomerRepository repository;
/**
* 根据id查询一个
*/
@Test
public void testFindOne() {
// 如果调用方法的返回值为Optional对象则不会报错
Optional<Customer> optionalCustomer = repository.findById(5L);
Customer customer = optionalCustomer.get();
System.out.println(customer);
}
}
首先要知道的时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));
}
}