3

I am trying to query JPA with Querydsl (4.1.4) as written here http://www.querydsl.com/static/querydsl/latest/reference/html/ch02.html#jpa_integration . I use Hibernate (5.2.12.Final) as the JPA backend. I generate Querydsl query types from the JPA annotated classes using the apt-maven-plugin with the com.querydsl.apt.jpa.JPAAnnotationProcessor processor.

I have an issue while updating an entity : the updated value does not show up in the Java code. Here is the relevant code snippet that updates a boolean property (named success) in the Entity :

    final EntityManagerFactory entityManagerFactory = PersistenceTestUtils.buildEntityManagerFactory();
    final EntityManager entityManager = entityManagerFactory.createEntityManager();
    final EntityTransaction transaction = entityManager.getTransaction();
    transaction.begin();
    final QJpaUpdateRound qJpaUpdateRound = QJpaUpdateRound.jpaUpdateRound;
    final JPQLQueryFactory queryFactory = new JPAQueryFactory(entityManager);

    final QJpaUpdateRound qJpaUpdateRound = QJpaUpdateRound.jpaUpdateRound;
    final JPQLQueryFactory queryFactory = new JPAQueryFactory(entityManager);
    final long roundId = 3L;

    System.out.println("Original " +originalRound);

    queryFactory //
        .update(qJpaUpdateRound) //
        .set(qJpaUpdateRound._success, true) //
        .where(qJpaUpdateRound._id.eq(roundId)) //
        .execute();

    // entityManager.clear(); // Workaround

    // Fetch the updated value
    final UpdateRound updatedRound = queryFactory //
        .selectFrom(qJpaUpdateRound) //
        .where(qJpaUpdateRound._id.eq(roundId)) //
        .fetchOne();
    transaction.commit();
    System.out.println("Updated "+ updatedRound);

This prints :

Original JpaUpdateRound{id=3; instant=2017-11-06T19:27:01.141Z; success=false}
Updated JpaUpdateRound{id=3; instant=2017-11-06T19:27:01.141Z; success=false}

Also, an identity test on originalRound and updatedRound shows that both variables are the same instance.

I checked in the database : the value is really updated. And if I uncomment the following line

    entityManager.clear(); // Workaround

The program prints

Original JpaUpdateRound{id=3; instant=2017-11-06T19:39:01.038Z; success=false}
Updated JpaUpdateRound{id=3; instant=2017-11-06T19:39:01.038Z; success=true}

which is the result I expect.

It seems that the entity cache does not get updated when the Querydsl update is performed. Thus, it only returns the original Java object.

Why ? How can I synchronize the JPA backend and Querydsl ?

Emmanuel Guiton
  • 1,315
  • 13
  • 24

1 Answers1

2

It appears there is no other way than manually tell the entity manager that it should refresh its data. Whether using entityManager.refresh(entity) on each entity that needs to be reloaded from the database; whether by clearing the whole entity manager cache by calling entityManager.clear().

See Force refresh of collection JPA entityManager

Emmanuel Guiton
  • 1,315
  • 13
  • 24