为什么在使用指定的事务管理器时,Spring Data JPA 查询会失败?

问题描述

我有一个使用 2 个数据源的服务 - 一个处理读取,一个处理修改操作(插入、删除、更新)。对于每个数据源,我都配置了一个不同的事务管理器。

名为 transactionManager认事务管理器处理读取,而另一个名为 writeTransactionManager 的处理写入。

读取时一切正常,但我有一个 custom delete query 根本没有被正确的事务管理器接收。

这是我的仓库:

public interface DeviceWriteRepository extends JpaRepository<Device,String> {
    @Transactional
    @Modifying
    @Query("DELETE FROM Device d WHERE d.userId = ?1 AND d.tenantId = ?2 AND d.appId = ?3")
    void unregisterDevices(String userId,String tenantId,String appId);
}

启用调试和跟踪 JPA/Hibernate 日志后,当我调用 unregisterDevices 设备时,我得到以下日志:

Creating new transaction with name [com.my.app.repository.softDeleteCrudRepositoryImpl.unregisterDevice]: PROPAGATION_required,ISOLATION_DEFAULT
Opened new EntityManager [SessionImpl(1270255427<open>)] for JPA transaction
Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@464a9dcc]
delete from device where user_id=? and tenant_id=? and app_id=?
delete from device where user_id=? and tenant_id=? and app_id=?
binding parameter [1] as [VARCHAR] - [user1]
binding parameter [2] as [VARCHAR] - [someTenant]
binding parameter [3] as [VARCHAR] - [someApp]
Initiating transaction commit
Committing JPA transaction on EntityManager [SessionImpl(1270255427<open>)]
Closing JPA EntityManager [SessionImpl(1270255427<open>)] after transaction

一切都很好,如果我检查数据库删除查询有效,但它没有被 writeTransactionManager 执行。

为了强制使用我想要的事务管理器,我更新了 @Transactional 注释以包含管理器的名称,例如 @Transactional("writeTransactionManager"),我得到以下异常:

org.springframework.dao.InvalidDataAccessApiUsageException: Executing an update/delete query; nested exception is javax.persistence.TransactionrequiredException: Executing an update/delete query

此外,如果我再次检查日志,我可以看到与第一次尝试不同,writeTransactionManager 实际上是根据以下日志选择的,重点是第一行

Creating new transaction with name [com.my.app.repository.softDeleteCrudRepositoryImpl.unregisterDevice]: PROPAGATION_required,ISOLATION_DEFAULT; 'writeTransactionManager'
Opened new EntityManager [SessionImpl(1868680430<open>)] for JPA transaction
Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@1c459897]
opening JPA EntityManager
Initiating transaction rollback
Rolling back JPA transaction on EntityManager [SessionImpl(1868680430<open>)]
Closing JPA EntityManager [SessionImpl(1868680430<open>)] after transaction

这怎么可能不在交易中,而在初始交易中呢?为什么指定事务管理器的名称会破坏行为?

我还想提到的另一件事是我也尝试过使用 DSL 并定义不同的存储库方法,如下所示:

@Transactional("writeTransactionManager")
void deleteByUserIdAndTenantIdAndAppIdAndplatform(String userId,String appId,PlatformType platform);

当我使用此方法时,writeTransactionManager 被选取,但它首先执行 SELECT 查询以引入托管实体 - 令人惊讶的是 - 删除从未发生。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)