为什么在 JPA 中可以通过 id 找到对象,但不能通过 JPQL 查询找到对象?
我有一个带有 Spring @Transactional
注释的 JUnit 4 测试用例,它保存一个对象,然后尝试找到它。当我使用此实现时,测试用例通过:
@Override
public EventSummary findEventSummaryById(Integer id) {
return em.find(EventSummary.class, id);
}
当我使用此实现时,测试用例失败(然后更改我在测试用例中调用的方法):
@Override
public EventSummary findEventSummary(Integer id) {
Query query = em.createQuery("select es from EventSummary as es where es.id = :id");
query.setParameter("id", id);
EventSummary result = (EventSummary) query.getSingleResult();
return result;
}
I have a JUnit 4 test case with the Spring @Transactional
annotation that saves an object, and then attempts to find it. The test case passes when I use this implementation:
@Override
public EventSummary findEventSummaryById(Integer id) {
return em.find(EventSummary.class, id);
}
It fails when I use this implementation (and then change which method I call in the test case):
@Override
public EventSummary findEventSummary(Integer id) {
Query query = em.createQuery("select es from EventSummary as es where es.id = :id");
query.setParameter("id", id);
EventSummary result = (EventSummary) query.getSingleResult();
return result;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在第一种情况下,id 是一个整数;在
第二种情况下,id 是一个字符串,
整数永远不会等于字符串
in the first case, the id is an Integer
in the second, the id is a String
an Integer will never equal a String
如果您使用默认的刷新模式 (
AUTO
) 并且在事务中执行查询,JPA 规范保证查询不会返回陈旧或不正确的数据:假设您使用
AUTO
,请检查事务方面。If you are using the default flush mode (
AUTO
) and if you are executing your query within a transaction, the JPA specification guarantees that a Query will not return stale or incorrect data:Assuming that you are using
AUTO
, check the transactional side.该实体位于当前会话(实体管理器)中 - 它处于持久状态,等待刷新。 get方法首先检查会话的内容,如果没有找到则转向底层数据库。在您的情况下,该实体刚刚保存在同一会话中,因此可以找到并返回该实体。
更新:事实证明问题是使用了不正确的事务管理器,因此实体尚未刷新到数据库。参见帕斯卡的解释。
Тhe entity is in the current session (entity manager) - it is in persistent state, waiting to be flushed. The get method first checks the contents of the session, and if not found turns to the underlying database. In your case, the entity has just been saved in the same session, so it is found and returned.
Update: it turned out the problem is using an incorrect transaction manager, hence the entity hasn't been flushed to the database. See Pascal's explanation.