CrudRepository findOne()和JpaRepository getOne()之间的区别

问题描述 投票:6回答:4

我读到getOne()是懒惰的,而findOne()立即抓住了整个实体。我检查了调试日志,我甚至在我的sql server上启用了监视,看看执行了哪些语句,我发现getOne()findOne()都生成并执行相同的查询。但是,当我使用getOne()时,值最初为null(当然除了id)。

那么有人可以告诉我,如果两种方法在数据库上执行相同的查询,为什么我要使用一个而不是另一个?我基本上是在寻找一种获取实体的方法,而不会获得它的所有子/属性。

EDIT1

Entity code

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。

Debugging log

No debugging log

spring hibernate jpa spring-data-jpa
4个回答
9
投票

这只是猜测,但在'纯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


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方法来消除不必要的查询。


0
投票

请注意,如果您通过id查询实体,确实存在于数据库中,使用findOne(id),您将获得null,使用getOne(id),您将获得具有空字段的对象,因此检查getOne(id) == null将无法按预期工作。


0
投票

如果找不到特定ID的表,则findOne将返回null,而getOne将抛出javax.persistence.EntityNotFoundException。两者都各有利弊。请看下面的例子:

  1. 如果找不到数据不是您的失败案例(例如,您只是验证数据是否已删除,数据是否为null),则可以使用findOne。
  2. 在另一种情况下,您可以使用getOne。

如果您了解结果,可以根据您的要求进行更新。

© www.soinside.com 2019 - 2024. All rights reserved.