如何使用 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-plugin
和 com.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;成功=假
此外,对originalRound
和updatedRound
的身份测试表明这两个变量是同一个实例。
我检查了数据库:值确实更新了。如果我取消注释以下行
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 关系建模谓词?