@Transactional(propagation = Propagation.REQUIRES_NEW) 不会在 JBoss EAP 上创建新连接

问题描述 投票:0回答:1

我需要在运行时动态切换数据源(读/写多个MariaDB数据库)。我正在使用 多租户概念来实现相同的

但我无法让它适用于下面的简单场景。对于

myService.persist()
的第一次调用,Spring 请求一个连接,因此与
db1
关联的连接按预期返回。但是,对于第二次调用,不会请求新连接,并且正在使用与
db1
关联的现有连接。

public class MainClass {
    
    ..
    
    public void main() {
        TenantContext.setCurrentTenant("db1");
        myService.persist();

        TenantContext.setCurrentTenant("db2");
        myService.persist();
    }
}
@Service
public class MyService {

    ..

    // Method is correctly declared as public and is being called from another class
    // to ensure proxy application
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void persist() {
        MyEntity entity = new MyEntity();
        entity.setName(UUID.randomUUID().toString());
        entity.setLastUpdated(new Date());


        repository.save(entity);
    }
}

该应用程序基于 Spring Boot 2.7.17 构建,并部署在 JBoss EAP 7.3 容器上。数据源使用 JNDI 进行配置,并在

standalone.xml
中进行以下配置。我没有在代码中显式配置任何事务管理器。

<datasource jta="true" jndi-name="java:/datasources/db1" pool-name="db1" enabled="true" use-ccm="true" statistics-enabled="true">
    <connection-url>jdbc:mariadb://myhost:3306/db1</connection-url>
    <driver>maria</driver>
    <security>
        <user-name>*******</user-name>
        <password>******</password>
    </security>
    <validation>
        <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLValidConnectionChecker"/>
        <check-valid-connection-sql>select 1</check-valid-connection-sql>
        <validate-on-match>true</validate-on-match>
        <background-validation>false</background-validation>
        <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLExceptionSorter"/>
    </validation>
    <timeout>
        <set-tx-query-timeout>true</set-tx-query-timeout>
        <blocking-timeout-millis>300</blocking-timeout-millis>
        <idle-timeout-minutes>10</idle-timeout-minutes>
        <query-timeout>300</query-timeout>
        <allocation-retry>3</allocation-retry>
        <allocation-retry-wait-millis>300</allocation-retry-wait-millis>
    </timeout>
</datasource>

我确实看到了以下登录启动日志。会不会跟这有什么关系?

Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
spring-boot spring-data-jpa spring-transactions jboss-eap-7
1个回答
0
投票

在某些情况下,有必要放弃使用 JPA 存储库提出的 save() 方法;这是关于事务管理的。此方法通常在数据库中执行两个操作,第一个检查要保存的实体是否已存在于数据库中,另一个用于保存或更新(如果您面对大型数据库,这也可能会导致性能问题)。

在您的情况下, save() 似乎用于创建新的数据库资源。我建议在 MyEntityRepository 接口中使用 jpql 查询,如下所示:

  @Modifying
  @Query(value = "insert into my_entity (name,last_updated) VALUES 
  (:name,:lastUpdated)", nativeQuery = true)
  MyEntity saveMyEntity(String name, String lastUpdated);

使用这种方法,如果 save 可用于更新数据,则需要使用更新 jpql 查询。 (update也可以是delete和insert new的组合,也可以接受)

希望能帮到你。

© www.soinside.com 2019 - 2024. All rights reserved.