CrudRepository findOne()和JpaRepository getOne()之间的区别
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CrudRepository findOne()和JpaRepository getOne()之间的区别相关的知识,希望对你有一定的参考价值。
我读到getOne()
是懒惰的,而findOne()
立即抓住了整个实体。我检查了调试日志,我甚至在我的sql server上启用了监视,看看执行了哪些语句,我发现getOne()
和findOne()
都生成并执行相同的查询。但是,当我使用getOne()
时,值最初为null(当然除了id)。
那么有人可以告诉我,如果两种方法在数据库上执行相同的查询,为什么我要使用一个而不是另一个?我基本上是在寻找一种获取实体的方法,而不会获得它的所有子/属性。
EDIT1
DAO code:
@Repository
public interface FlightDao extends JpaRepository<Flight, Long> {
}
Debugging log findOne() vs getOne()
Aaditi:
感谢Chlebik,我能够找出问题所在。与Chlebik一样,如果您尝试访问getOne()
提取的实体的任何属性,则将执行完整查询。在我的情况下,我在调试时检查行为,一次移动一行,我完全忘记了调试IDE时尝试访问对象属性以进行调试(或者至少是我认为正在发生的事情),所以调试触发器完整的查询执行。我停止调试,然后检查日志,一切似乎都正常。
getOne()
vs findOne()
(此日志取自mysql general_log
而非hibernate。
这只是猜测,但在'纯JPA'中有一个名为getReference的EntityManager方法。它旨在检索只有ID的实体。它的用途主要是用于指示存在而无需检索整个实体。也许代码会说明更多:
// em is EntityManager
Department dept = em.getReference(Department.class, 30); // Gets only entity with ID property, rest is null
Employee emp = new Employee();
emp.setId(53);
emp.setName("Peter");
emp.setDepartment(dept);
dept.getEmployees().add(emp);
em.persist(emp);
我假设getOne服务于同一目的。为什么生成的查询与您要求的相同?嗯,JPA圣经中的AFAIR - Mike Keith和Merrick Schincariol的Pro JPA2 - 几乎每个段落都包含“行为取决于供应商”的内容。
编辑:
我已经设置了自己的设置。最后我得出结论,如果你以任何方式干扰用getOne获取的实体(甚至去了entity.getId()),它会导致执行SQL。虽然如果您仅使用它来创建代理(例如,如上面代码中所示的关系指示符),则不会发生任何事情,也不会执行其他SQL。所以我假设在你的服务类中你用这个实体做某事(使用getter,log something),这就是为什么这两个方法的输出看起来一样的原因。
ChlebikGitHub with example code SO helpful question #1 SO helpful question #2
假设您要通过id删除Entity
。在SQL
中,您可以执行如下查询:
"delete form TABLE_NAME where id = ?".
在Hibernate
中,首先你必须获得你的Entity
的托管实例,然后将其传递给EntityManager.remove
方法。
Entity a = em.find(Entity.class, id);
em.remove(a);
但是这样,你必须在删除之前获取要从数据库中删除的Entity
。这真的有必要吗?
方法EntityManager.getReference
返回Hibernate
代理而不查询数据库并设置实体的属性。除非您尝试自己获取返回代理的属性。
方法JpaRepository.getOne
使用EntityManager.getReference
方法而不是EntityManager.find
方法。所以每当你需要一个托管对象但你真的不需要查询数据库时,最好使用JpaRepostory.getOne
方法来消除不必要的查询。
请注意,如果您通过id查询实体,确实存在于数据库中,使用findOne(id)
,您将获得null,使用getOne(id)
,您将获得具有空字段的对象,因此检查getOne(id) == null
将无法按预期工作。
如果找不到特定ID的表,则findOne将返回null,而getOne将抛出javax.persistence.EntityNotFoundException。两者都各有利弊。请看下面的例子:
- 如果找不到数据不是您的失败案例(例如,您只是验证数据是否已删除,数据是否为null),则可以使用findOne。
- 在另一种情况下,您可以使用getOne。
如果您了解结果,可以根据您的要求进行更新。
以上是关于CrudRepository findOne()和JpaRepository getOne()之间的区别的主要内容,如果未能解决你的问题,请参考以下文章
CrudRepository findOne()和JpaRepository getOne()之间的区别
如何在 Spring Data JPA CRUDRepository 中添加缓存功能