开发者

Why is an object found by id in JPA, but not through a JPQL query?

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;
}


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.


Т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.


in the first case, the id is an Integer

in the second, the id is a String

an Integer will never equal a String

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜