为什么在 JPA 中可以通过 id 找到对象,但不能通过 JPQL 查询找到对象?

发布于 2024-09-12 21:48:00 字数 575 浏览 3 评论 0原文

我有一个带有 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

零崎曲识 2024-09-19 21:48:01

在第一种情况下,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

哀由 2024-09-19 21:48:00

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

3.6.2 查询和刷新模式

冲水模式设置会影响
查询结果如下。

当查询在一个
事务,如果 FlushModeType.AUTO
Query 对象上设置,或者如果
持久性的刷新模式设置
上下文是 AUTO (默认)和
冲洗模式尚未设置
Query 对象指定,
持久化提供者负责
以确保所有更新
中所有实体的状态
持久化上下文可以
可能会影响结果
查询对处理可见
查询。持久化提供者
实施可以通过以下方式实现这一目标
将这些实体冲刷到
数据库或其他方式。如果
FlushModeType.COMMIT 设置后,
对实体进行更新的效果
查询时的持久化上下文
未指定。

公共枚举 FlushModeType {
    犯罪,
    汽车
}

如果没有活跃的交易,
持久性提供者不得刷新到
数据库。

假设您使用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:

3.6.2 Queries and FlushMode

The flush mode setting affects the
result of a query as follows.

When queries are executed within a
transaction, if FlushModeType.AUTO
is set on the Query object, or if the
flush mode setting for the persistence
context is AUTO (the default) and a
flush mode setting has not been
specified for the Query object, the
persistence provider is responsible
for ensuring that all updates to the
state of all entities in the
persistence context which could
potentially affect the result of the
query are visible to the processing of
the query. The persistence provider
implementation may achieve this by
flushing those entities to the
database or by some other means. If
FlushModeType.COMMIT is set, the
effect of updates made to entities in
the persistence context upon queries
is unspecified.

public enum FlushModeType {
    COMMIT,
    AUTO
}

If there is no transaction active, the
persistence provider must not flush to
the database.

Assuming that you are using AUTO, check the transactional side.

李不 2024-09-19 21:48:00

该实体位于当前会话(实体管理器)中 - 它处于持久状态,等待刷新。 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文