如何使用 Querydsl 更新 JPA 实体?

Posted

技术标签:

【中文标题】如何使用 Querydsl 更新 JPA 实体?【英文标题】:How to update a JPA entity using Querydsl? 【发布时间】:2017-11-06 19:45:41 【问题描述】:

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

更新实体时遇到问题:更新后的值未显示在 Java 代码中。这是更新实体中的布尔属性(名为success)的相关代码sn-p:

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

这打印:

原始 JpaUpdateRoundid=3;瞬间=2017-11-06T19:27:01.141Z; 成功=false 更新了 JpaUpdateRoundid=3; 瞬间=2017-11-06T19:27:01.141Z;成功=假

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

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

    entityManager.clear(); // Workaround

程序打印

原始 JpaUpdateRoundid=3;瞬间=2017-11-06T19:39:01.038Z; 成功=false 更新了 JpaUpdateRoundid=3; 瞬间=2017-11-06T19:39:01.038Z;成功=真

这是我期望的结果。

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

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

【问题讨论】:

【参考方案1】:

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

见Force refresh of collection JPA entityManager

【讨论】:

这是最好的解决方案。另请注意 entityManager.flush() 也不起作用。

以上是关于如何使用 Querydsl 更新 JPA 实体?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 BooleanBuilder (QueryDSL) 为可选的 OnetoOne JPA/Hibernate 关系建模谓词?

Spring Data JPA中使用QueryDSL进行查询

JPA 之 QueryDSL-JPA 使用指南

springboot-jpa-querydsl

如何使用 querydsl 测试更新?

通过 REST 控制器使用 Spring Data JPA 和 QueryDsl 的异常