为什么JPA中的id找到了一个对象,而不是通过JPQL查询?

时间:2010-08-05 18:57:32

标签: hibernate spring orm jpa 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;
}

3 个答案:

答案 0 :(得分:3)

实体位于当前会话(实体管理器)中 - 它处于持久状态,等待刷新。 get方法首先检查会话的内容,如果没有找到则转向底层数据库。在您的情况下,实体刚刚保存在同一个会话中,因此找到并返回该实体。

更新:事实证明问题是使用了不正确的事务管理器,因此实体尚未刷新到数据库。见Pascal的解释。

答案 1 :(得分:3)

如果您使用的是默认刷新模式(AUTO),并且如果您在事务中执行查询,则JPA规范保证Query不会返回过时或不正确的数据:

  

3.6.2查询和FlushMode

     

刷新模式设置会影响   查询结果如下。

     

在a中执行查询时   交易,如果FlushModeType.AUTO   在Query对象上设置,或者如果是。{   持久性的刷新模式设置   上下文是AUTO(默认值)和a   冲洗模式设置尚未完成   为Query对象指定的   持久性提供者负责   确保所有更新   中的所有实体的状态   持久性上下文可以   可能会影响结果   查询对于处理是可见的   查询。持久性提供者   实施可以实现这一点   将这些实体刷新到   数据库或通过其他方式。如果   设置FlushModeType.COMMIT   更新对实体的影响   查询的持久化上下文   没有具体说明。

public enum FlushModeType {
    COMMIT,
    AUTO
}
     

如果没有活动的交易,则   持久性提供程序不得刷新   数据库。

假设您使用AUTO,请检查交易方。

答案 2 :(得分:0)

在第一种情况下,id是一个Integer

在第二个中,id是一个String

整数永远不会等于字符串