Весенний ботинок. Выбор динамического или статического подключения компонента влияет на транзакционную (распространение JAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Гость
 Весенний ботинок. Выбор динамического или статического подключения компонента влияет на транзакционную (распространение

Сообщение Гость »


Can not understand why choice of Dynamic or Static Bean Wiring affects on Transactional(propagation = Propagation.REQUIRES_NEW) logic.

Input: Spring Boot 3.2.3 ( the same can happen in 2.3.3+), java 21 Config :

server: port: 9118 spring: datasource: driverClassName: org.postgresql.Driver url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5555}/${DB_NAME:test}?ApplicationName=test username: ${DB_USERNAME:test} password: ${DB_PASSWORD:test} hikari: maxLifetime: 120000 metrics: enable: true leakDetectionThreshold: 30000 maximumPoolSize: 3 jpa: open-in-view: false hibernate: ddl-auto: none properties: hibernate: generate_statistics: true default_schema: test dialect: org.hibernate.dialect.PostgreSQLDialect logging: level: root: INFO org.springframework.orm.jpa: DEBUG org.springframework.transaction: DEBUG com: zaxxer: hikari: DEBUG (After text descr full code, can skip)
  • InnerTrx : interface, this interface implemented by two classes annotated as Service. Implemented method annotated with @Transactional(propagation = Propagation.REQUIRES_NEW).
  • OuterTrx: class annotated as Service + injected InnerTrx implementation + method annotated with @Transactional. This method call InnerTrx method.

public interface InnerTrx { void test(); } @Service @RequiredArgsConstructor public class InnerTrxService implements InnerTrx { private final ExchangeRepository repository; private final HikariDataSource dataSource; @Transactional(propagation = Propagation.REQUIRES_NEW) public void test() { log.info(" inside test() method :: hikari pool : active: {} idle: {} wait :{}", dataSource.getHikariPoolMXBean().getActiveConnections(), dataSource.getHikariPoolMXBean().getIdleConnections(),dataSource.getHikariPoolMXBean().getThreadsAwaitingConnection()); repository.save(ExchangeEntity.builder() .test("test") .build()); } } @Service @RequiredArgsConstructor public class InnerTrxService2 implements InnerTrx { private final ExchangeRepository repository; private final HikariDataSource dataSource; @Transactional(propagation = Propagation.REQUIRES_NEW) public void test() { log.info(" inside test() method :: hikari pool : active: {} idle: {} wait :{}", dataSource.getHikariPoolMXBean().getActiveConnections(), dataSource.getHikariPoolMXBean().getIdleConnections(),dataSource.getHikariPoolMXBean().getThreadsAwaitingConnection()); repository.save(ExchangeEntity.builder() .test("test") .build()); } } @Repository public interface ExchangeRepository extends JpaRepository { } case: Dynamic Wiring injection of InnerTrx implementation with @Qualifier

@Slf4j @Service public class OuterTrxService { private final InnerTrx innerTrx; private final HikariDataSource dataSource; public OuterTrxService(@Qualifier("innerTrxService") InnerTrx innerTrx, HikariDataSource dataSource) { this.innerTrx = innerTrx; this.dataSource = dataSource; } @Transactional public void testOuterTrx() { log.info(" inside test() method :: hikari pool : active: {} idle: {} wait :{}", dataSource.getHikariPoolMXBean().getActiveConnections(), dataSource.getHikariPoolMXBean().getIdleConnections(), dataSource.getHikariPoolMXBean().getThreadsAwaitingConnection()); innerTrx.test(); } } when we call testOuterTrx() all is ok as expected = 2 trx = 2 active connection max:

image result log 2trx expected call

case: Static Wiring choose implemetation in configuration class using @Bean ( In my real project i choose implementation by condition from config). Now we dont need to use @Qualifier when inject

@Configuration @RequiredArgsConstructor public class TestConfiguration { private final InnerTrxService2 testService2; @Bean public InnerTrx innerTrx() { return testService2; } } @Slf4j @Service public class OuterTrxService { private final InnerTrx innerTrx; private final HikariDataSource dataSource; public OuterTrxService(InnerTrx innerTrx, HikariDataSource dataSource) { this.innerTrx = innerTrx; this.dataSource = dataSource; } @Transactional public void testOuterTrx() { log.info(" inside test() method :: hikari pool : active: {} idle: {} wait :{}", dataSource.getHikariPoolMXBean().getActiveConnections(), dataSource.getHikariPoolMXBean().getIdleConnections(), dataSource.getHikariPoolMXBean().getThreadsAwaitingConnection()); innerTrx.test(); } } when we call testOuterTrx() = 3 trx = 3 active connection max:

image result log 3trx

So i just changed Wiring type and have useless transaction with one lost connection per method call. Why is this happening?

P.S.

I know we can can solve this by not annotating test() method implemetation with @Transactional(propagation = Propagation.REQUIRES_NEW). And create additional service class, where we call test() method inside new service class method annotated with @Transactional(propagation = Propagation.REQUIRES_NEW)
@Slf4j @Service @RequiredArgsConstructor public class InnerTrxAdditionalService { private final InnerTrx innerTrx; @Transactional(propagation = Propagation.REQUIRES_NEW) public void test() { innerTrx.test(); } } @Slf4j @Service public class OuterTrxService { private final InnerTrxAdditionalService innerTrx; private final HikariDataSource dataSource; public OuterTrxService(InnerTrxAdditionalService innerTrx, HikariDataSource dataSource) { this.innerTrx = innerTrx; this.dataSource = dataSource; } @Transactional public void testOuterTrx() { log.info(" inside test() method :: hikari pool : active: {} idle: {} wait :{}", dataSource.getHikariPoolMXBean().getActiveConnections(), dataSource.getHikariPoolMXBean().getIdleConnections(), dataSource.getHikariPoolMXBean().getThreadsAwaitingConnection()); innerTrx.test(); } }

Источник: https://stackoverflow.com/questions/781 ... actionalpr
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «JAVA»