如何使用 Querydsl 更新 JPA 实体?

How to update a JPA entity using Querydsl?

我正在尝试使用此处所写的 Querydsl (4.1.4) 查询 JPA http://www.querydsl.com/static/querydsl/latest/reference/html/ch02.html#jpa_integration。我使用 Hibernate (5.2.12.Final) 作为 JPA 后端。我使用带有 com.querydsl.apt.jpa.JPAAnnotationProcessor 处理器的 apt-maven-plugin 从注释为 类 的 JPA 生成 Querydsl 查询类型。

我在更新实体时遇到问题:Java 代码中没有显示更新的值。这是更新实体中的布尔值 属性(名为 success)的相关代码片段:

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

这会打印:

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}

此外,对 originalRoundupdatedRound 的身份测试表明这两个变量是同一个实例。

我检查了数据库:值真的更新了。如果我取消注释以下行

    entityManager.clear(); // Workaround

程序打印

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}

这是我期望的结果。

执行 Querydsl 更新时,实体缓存似乎没有更新。因此,它只是 returns 原始 Java 对象。

为什么?如何同步 JPA 后端和 Querydsl?

看来除了手动告诉实体管理器它应该刷新其数据之外别无他法。是否在需要从数据库重新加载的每个实体上使用 entityManager.refresh(entity);是否通过调用 entityManager.clear().

清除整个实体管理器缓存

Force refresh of collection JPA entityManager