一尘不染

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

hibernate

我读到它getOne()是延迟加载的,并立即findOne()获取整个实体。我检查调试日志,我甚至能监视我的SQL服务器上看到的语句被执行的东西,我发现,无论getOne()findOne()生成和执行相同的查询。但是,当我使用时,getOne()这些值最初为null(当然,除了id)。

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

编辑1:

实体代码

道代码:

@Repository
public interface FlightDao extends JpaRepository<Flight, Long> {
}

调试日志findOne()vs getOne()

编辑2:

感谢Chlebik,我得以找到问题所在。如Chlebik所述,如果您尝试访问由getOne()完整查询获取的实体的任何属性,则将执行该查询。就我而言,我在调试时检查行为,一次只移动一行,但我完全忘记了在调试IDE时出于调试目的而尝试访问对象属性(或者至少是我认为的那样),因此调试触发器完整的查询执行。我停止调试,然后检查了日志,一切似乎都正常。

getOne()vs findOne()(此日志取自MySQL general_log,不hibernate。

调试日志

没有调试日志


阅读 375

收藏
2020-06-20

共1个答案

一尘不染

只是一个猜测,但是在“纯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圣经中的 AFAIR-Mike Keith和MerrickSchincariol编写的Pro JPA2- 几乎每个段落都包含类似“行为取决于卖方”的内容。

编辑:

我已经设定好自己的设定。最后,我得出的结论是,如果您以任何方式干扰使用 getOne
提取的实体(甚至转到entity.getId()),它将导致SQL被执行。尽管如果仅使用它来创建代理(例如,如上面代码中所示的关系指示符),则什么也不会发生,也不会执行其他SQL。因此,我假设在您的服务类中您对此实体进行了某些操作(使用getter进行记录),这就是为什么这两种方法的输出看起来相同的原因。

具有示例代码的ChlebikGitHub
有用的问题#1
有用的问题#2

2020-06-20