Spring CRUDEPository findOne()和JpaRepository getOne()之间的差异

Spring CRUDEPository findOne()和JpaRepository getOne()之间的差异,spring,hibernate,jpa,spring-data-jpa,Spring,Hibernate,Jpa,Spring Data Jpa,我读到getOne()是延迟加载的,findOne()立即获取整个实体。我检查了调试日志,甚至在我的sql server上启用了监视以查看执行了哪些语句,我发现getOne()和findOne()都生成并执行相同的查询。但是,当我使用getOne()时,这些值最初是空的(当然id除外) 那么有谁能告诉我,如果两个方法在数据库上执行相同的查询,为什么我要使用一个而不是另一个?我基本上是在寻找一种方法来获取一个实体,而不获取它的所有子项/属性 EDIT1: Dao代码: @Repository p

我读到
getOne()
是延迟加载的,
findOne()
立即获取整个实体。我检查了调试日志,甚至在我的sql server上启用了监视以查看执行了哪些语句,我发现
getOne()
findOne()
都生成并执行相同的查询。但是,当我使用
getOne()
时,这些值最初是空的(当然id除外)

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

EDIT1:

Dao代码:

@Repository
public interface FlightDao extends JpaRepository<Flight, Long> {
}
@存储库
公共接口FlightDao扩展了JpaRepository{
}

EDIT2:

多亏了Chlebik,我才发现了这个问题。如Chlebik所述,如果试图访问通过
getOne()
获取的实体的任何属性,将执行完整的查询。在我的例子中,我在调试时检查行为,一次移动一行,我完全忘记了,在调试IDE时,为了调试目的(或者至少我认为是这样),会尝试访问对象属性,所以调试会触发完整的查询执行。我停止了调试,然后检查了日志,一切正常

getOne()
vs
findOne()
(此日志取自MySQL
general\u log
而非hibernate


这只是一个猜测,但在“纯JPA”中有一种EntityManager方法,名为getReference。它被设计用于检索只有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圣经-Pro JPA2中,几乎每个段落都包含类似“行为取决于供应商”的内容

编辑:

我已经设置了自己的设置。最后我得出结论,如果您以任何方式干扰使用getOne获取的实体(甚至是使用entity.getId()),它会导致SQL被执行。尽管您仅使用它来创建代理(例如,对于上面代码中所示的关系指示器)因此,我假设在您的服务类中,您对这个实体做了一些事情(使用getter、log等),这就是为什么这两个方法的输出看起来是一样的




假设要按id删除
实体
。在
SQL
中,可以执行如下查询:

"delete form TABLE_NAME where id = ?". 
Hibernate
中,首先必须获取
实体的托管实例,然后将其传递给
EntityManager.remove
方法

Entity a = em.find(Entity.class, id);
em.remove(a);
但这样,您必须在删除之前从数据库中获取要删除的
实体
。这真的有必要吗

方法
EntityManager.getReference
返回一个
Hibernate
代理,而不查询数据库和设置实体的属性。除非您自己尝试获取返回代理的属性


方法
JpaRepository.getOne
使用
EntityManager.getReference
方法,而不是
EntityManager.find
方法。因此,每当您需要托管对象但实际上不需要查询数据库时,最好使用
JpaRepostory.getOne
方法来消除不必要的查询。

如果数据如果找不到特定ID的表,findOne将返回null,而getOne将抛出javax.persistence.EntityNotFoundException。 两者都有各自的优点和缺点。请参见下面的示例:

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

  • 如果您知道结果,可以根据您的要求进行更新。

    谢谢您提供的信息。
    getOne()
    实际上所做的是调用
    getReference()
    。我真的很困惑,因为正如我前面所说的,这两种方法都生成并执行了相同的查询!所以可能与您所说的MySQL有关?我真的希望有人能证实这一点。您知道在正常情况下,这两种方法的查询是否应该有所不同吗?供应商不是指MySQL,而是指Hibernate/TopLink/无论您使用什么。我假设正在执行的查询是基于实体中定义的关系,可能是由JPA实现完成的优化。IMHO对于简单实体,将处理程序提取到实体(如getReference)之间没有太大区别以及所有数据的实际检索。我必须获得一个引用,因为我试图获取的实体有很多子实体,当我只需要实体ID时,获取整个实体需要大量的工作。让我们等一会儿,也许有人可以告诉我们发生了什么。再次感谢发布您的实体代码。有几种可能想一想,但是没有代码,我什么都说不出来。检查我的第二次编辑。我真的无法给你足够的票数。我现在感觉很傻:-非常感谢Chlebik:)