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

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

编辑1:

Entity code

道代码:

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


Debugging log findOne() vs getOne()

编辑2:

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

getOne() vs findOne()(此日志来自MySQL general_log,而不是休眠状态。

Debugging log

No debugging log

最佳答案

这只是一个猜测,但是在“纯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进行记录),这就是为什么这两种方法的输出看起来相同的原因。

ChlebikGitHub with example code
SO helpful question #1
SO helpful question #2

08-05 09:58