- findById得到的是一个Optional(jdk1.8的新特性之一),之后用.get()就可以获取相应的对象
- getOne得到的是对应得实体类对象,如果需要在单元测试中使用此方法,要加上事务支持注解,即@Transactional,才可以正常使用,否则可能会抛出org.hibernate.LazyInitializationException: could not initialize prox
从源码分析
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) {
return Optional.ofNullable(this.em.find(domainType, id));
} else {
LockModeType type = this.metadata.getLockModeType();
Map<String, Object> hints = this.getQueryHints().withFetchGraphs(this.em).asMap();
return Optional.ofNullable(type == null ? this.em.find(domainType, id, hints) : this.em.find(domainType, id, type, hints));
}
}
findById实际上调用的是find方法,find方法采用的是立即加载的方式,所以findById加载方式就是立即加载,也就是执行这条查询语句的时候就从数据库进行查询
而getOne从源码上看
public T getOne(ID id) {
Assert.notNull(id, "The given id must not be null!");
return this.em.getReference(this.getDomainClass(), id);
}
调用的是getReference方法,即采用的加载策略是延迟加载(懒加载),即直到调用查询对象的时候,才从数据库中进行查询。
下面我们进行简单的测试即可得出两者的区别:
1、findById()
@Test
public void findByIdTest(){
StockPile stockPile=stockPileDao.findById("9787020002207").get();
System.out.println("==============判断采用的加载策略==============");
System.out.println(stockPile);
}
运行这个测试方法,控制台得到:
2、getOne()
@Test
@Transactional
public void getOneTest(){
StockPile stockPile=stockPileDao.getOne("9787020002207");
System.out.println("==============判断采用的加载策略==============");
System.out.println(stockPile);
}
运行这个测试方法,控制台得到:
经过测试,明显可以看出,findById()在一开始进行操作的时候就已经从数据库查询数据了,而getOne()直到调用时才从数据库查询数据
SpringDataJPA版本:2.1.17