spring CrudRepository findOne() 和 JpaRepository getOne() 的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33218762/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Difference between CrudRepository findOne() and JpaRepository getOne()
提问by prettyvoid
I read that getOne()
is lazy loaded and findOne()
fetches the whole entity right away. I've checked the debugging log and I even enabled monitoring on my sql server to see what statements gets executed, I found that both getOne()
and findOne()
generates and executes the same query. However when I use getOne()
the values are initially null (except for the id of course).
我读到它getOne()
是延迟加载并立即findOne()
获取整个实体。我检查调试日志,我甚至能监视我的SQL服务器上看到的语句被执行的东西,我发现,无论getOne()
和findOne()
生成和执行相同的查询。但是,当我使用时,getOne()
这些值最初为空(当然,id 除外)。
So could anyone please tell me, if both methods executes the same query on the database, why should I use one over the other? I'm basically looking for a way to fetch an entity without getting all of its children/attributes.
那么谁能告诉我,如果这两种方法都在数据库上执行相同的查询,为什么我应该使用一种而不是另一种?我基本上是在寻找一种方法来获取一个实体,而无需获取其所有子项/属性。
EDIT1:
编辑1:
Dao code:
道号:
@Repository
public interface FlightDao extends JpaRepository<Flight, Long> {
}
Debugging log findOne() vs getOne()
EDIT2:
编辑2:
Thanks to Chlebik I was able to identify the problem. Like Chlebik stated, if you try to access any property of the entity fetched by getOne()
the full query will be executed. In my case, I was checking the behavior while debugging, moving one line at a time, I totally forgot that while debugging the IDE tries to access object properties for debugging purposes (or at least that's what I think is happening), so debugging triggers the full query execution. I stopped debugging and then checked the logs and everything appears to be normal.
感谢 Chlebik,我能够确定问题所在。就像 Chlebik 所说的那样,如果您尝试访问由getOne()
完整查询获取的实体的任何属性,都将被执行。就我而言,我在调试时检查行为,一次移动一行,我完全忘记了在调试 IDE 时尝试访问对象属性以进行调试(或者至少我认为这是正在发生的),因此调试触发完整的查询执行。我停止调试,然后检查日志,一切似乎都正常。
getOne()
vs findOne()
(This log is taken from MySQL general_log
and not hibernate.
getOne()
vs findOne()
(此日志取自 MySQL,general_log
而不是休眠状态。
回答by Chlebik
It is just a guess but in 'pure JPA' there is a method of EntityManager called getReference. And it is designed to retrieve entity with only ID in it. Its use was mostly for indicating reference existed without the need to retrieve whole entity. Maybe the code will tell more:
这只是一个猜测,但在“纯 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);
I assume then getOneserves the same purpose. Why the queries generated are the same you ask? Well, AFAIR in JPA bible - Pro JPA2 by Mike Keith and Merrick Schincariol- almost every paragraph contains something like 'the behaviour depends on the vendor'.
我假设然后getOne用于相同的目的。为什么生成的查询和你问的一样?好吧,JPA 圣经中的AFAIR- Mike Keith 和 Merrick Schincariol 的 Pro JPA2- 几乎每个段落都包含诸如“行为取决于供应商”之类的内容。
EDIT:
编辑:
I've set my own setup. Finally I came to conclusion that if You in any way interfere with entity fetched with getOne(even go for entity.getId()) it causes SQL to be executed. Although if You are using it only to create proxy (eg. for relationship indicator like shown in a code above), nothing happens and there is no additional SQL executed. So I assume in your service class You do something with this entity (use getter, log something) and that is why the output of these two methods looks the same.
我已经设置了自己的设置。最后我得出的结论是,如果您以任何方式干扰使用getOne获取的实体(甚至使用 entity.getId()),它会导致执行 SQL。尽管如果您仅使用它来创建代理(例如,用于上面代码中所示的关系指示器),则不会发生任何事情并且不会执行其他 SQL。所以我假设在你的服务类中你对这个实体做了一些事情(使用 getter,记录一些东西),这就是为什么这两种方法的输出看起来相同。
ChlebikGitHub with example code
SO helpful question #1
SO helpful question #2
回答by chubock
Suppose you want to remove an Entity
by id. In SQL
you can execute a query like this :
假设您要删除一个Entity
by id。在SQL
您可以执行这样的查询:
"delete form TABLE_NAME where id = ?".
And in Hibernate
, first you have to get a managed instance of your Entity
and then pass it to EntityManager.remove
method.
在 中Hibernate
,首先您必须获得您的托管实例,Entity
然后将其传递给EntityManager.remove
方法。
Entity a = em.find(Entity.class, id);
em.remove(a);
But this way, You have to fetch the Entity
you want to delete from database before deletion. Is that really necessary ?
但是这样,您必须Entity
在删除之前从数据库中获取要删除的内容。真的有必要吗?
The method EntityManager.getReference
returns a Hibernate
proxy without querying the database and setting the properties of your entity. Unless you try to get properties of the returned proxy yourself.
该方法EntityManager.getReference
返回一个Hibernate
代理而不查询数据库和设置实体的属性。除非您尝试自己获取返回代理的属性。
Method JpaRepository.getOne
uses EntityManager.getReference
method instead of EntityManager.find
method. so whenever you need a managed object but you don't really need to query database for that, it's better to use JpaRepostory.getOne
method to eliminate the unnecessary query.
方法JpaRepository.getOne
使用EntityManager.getReference
方法而不是EntityManager.find
方法。因此,每当您需要托管对象但实际上并不需要为此查询数据库时,最好使用JpaRepostory.getOne
方法来消除不必要的查询。
回答by Kailas Andhale
If data is not found the table for particular ID, findOne will return null, whereas getOne will throw javax.persistence.EntityNotFoundException. Both have their own pros and cons. Please see example below:
如果在特定 ID 的表中找不到数据,findOne 将返回 null,而 getOne 将抛出 javax.persistence.EntityNotFoundException。两者都有自己的优点和缺点。请看下面的例子:
- If data not found is not failure case for you (eg. You are just verifying if data the data is deleted and success will be data to be null), you can use findOne.
- In another case, you can use getOne.
- 如果未找到数据对您来说不是失败案例(例如,您只是验证数据是否已删除,成功将是数据为空),则可以使用 findOne。
- 在另一种情况下,您可以使用 getOne。
This can be updated as per your requirements, if you know outcomes.
如果您知道结果,这可以根据您的要求进行更新。