【发布时间】:2018-08-26 02:21:25
【问题描述】:
我目前正在从事一个使用 Java、Oracle 和 Hibernate 的项目。我们的许多遗留代码使用原生查询来获取和更新我们的数据库记录,但我们一直在慢慢过渡到使用 JPQL。我怀疑两者的混合会导致一些问题,并想听听您对此的看法。
在其中一个场景中,我们添加了新逻辑,以使用 JPQL 从我们的数据库中获取两个实体并对其进行修改(我们将此方法称为 A)。之后,我们通过本机查询执行更新语句以翻转数据库中相同实体的标志(让我们将此方法称为 B)。这两种方法是相互独立的,这就是为什么它们是分开的,而不是在同一个主体中完成的。
我在阅读我们的 log4j 日志时注意到的是,方法 B 中的本机查询在方法 A 运行时被执行,特别是在更新两个实体之间。产生的错误是实体 1 被更新(方法 A),本机查询同时更新实体 1 和 2(方法 B),但是当实体 2 更新时(仍然是方法 A),它会覆盖方法 B 的更新。
但是,当我将方法 B 的本机查询替换为执行完全相同操作的 JPQL 时,它会按预期运行 - 在方法 A 完全完成之后。
有人知道为什么会这样吗?
提前致谢!
编辑:感谢您的回复,伙计们!这是使用本机查询的原始代码的剥离版本:
private void handleDateChange(List<Long> dpIdList) {
for(Long dpid : dpIdList) {
updateFeeTransactionsForDateChange(dpid);
deactivateFeeTransactionsAfterUpdate(dpid);
}
}
public void updateFeeTransactionsForDateChange(final Long dealProductId) {
List<FeeTransaction> feeTransactionList = feeTransactionDAO.getActiveUnmappedFeeTransactionEntitiesForDealProduct(dealProductId);
for (FeeTransaction feeTransaction : feeTransactionList) {
//Some Logic
}
}
public void deactivateFeeTransactionsAfterUpdate(final Long dealProductId) {
String UPDATE_ACTIVE_FOR_ALLOCATIONS = "update fee_transaction ft set ft.active = 'N' where ft.deal_product_id = ?1 and ft.active = 'Y'";
entityManager.createNativeQuery(UPDATE_ACTIVE_FOR_ALLOCATIONS).setParameter(1, dealProduct.getDealProductId()).executeUpdate();
}
以下是我所做的更改,首先将 JPQL 添加到我的实体类中:
@Entity
@Table(name = "FEE_TRANSACTION")
@SequenceGenerator(name = "FEETRANSPK", sequenceName = "FEETRANSID_SEQ")
@Named("feeTransaction")
@NamedQueries({
@NamedQuery(
name = FeeTransaction.UPDATE_ACTIVE_FOR_FEE_TRANSACTIONS_BY_DEAL_PRODUCT_IDS,
query = "update FeeTransaction set active = false where dealProductId in (:dealProductIds) and active = 'Y' ")
})
public class FeeTransaction implements Serializable {
//Attributes, getters, and setters
}
我的 DAO 类:
public void updateActiveForFeeTransactionsByDealProductIds(Set<Long> dealProductIds) {
entityManager.createNamedQuery(FeeTransaction.UPDATE_ACTIVE_FOR_FEE_TRANSACTIONS_BY_DEAL_PRODUCT_IDS)
.setParameter("dealProductIds", dealProductIds)
.executeUpdate();
}
然后再次将它们捆绑在一起:
private void handleDateChange(List<Long> dpIdList) {
for(Long dpid : dpIdList) {
updateFeeTransactionsForDateChange(dpid);
}
feeTransactionDAO.updateActiveForFeeTransactionsByDealProductIds(dpIdList);
}
我还应该补充一点,在我的测试用例中,dpIdList 中只有一个元素根据其 ID 返回 2 笔费用交易。这意味着我的本机查询仍然应该在 updateFeeTransactionsForDateChange 之后运行(而不是介于两者之间)。
【问题讨论】:
-
向我们展示您的代码。你在用
executeUpdate()方法吗? -
这对我来说听起来很奇怪。如果它是具有两个不同查询的隔离方法,即使一个是本机的,另一个是 JPQL,那么它应该没问题。很可能您的查询有一些问题。也许在您的原生查询中您不小心碰到了 A。请发布您的两个查询以供进一步调查。
标签: java oracle hibernate jpql nativequery