无法使用@Transactional(propagation = Propagation.REQUIRES_NEW)和HibernateTransactionManager创建新事务

6ojccjat  于 2023-03-30  发布在  其他
关注(0)|答案(1)|浏览(178)

我目前正在重构一些遗留代码。
我们正在从.xml spring上下文文件转移到基于java类的Spring配置。
下面是TransactionConfiguration.java我为TransactionManager的Spring初始化创建的www.example.com类。

@Configuration
@EnableTransactionManagement
public class TransactionConfiguration
{
  private String[] packagesToScan = {...redacted...};

  @Bean
  public DataSource dataSource(@Value("${db.driverClassName}") String driverClassName, @Value("${db.url}") String jdbcUrl,
          @Value("${db.usr.login}") String username, @Value("${db.usr.password}") String pwd, @Value("${db.maxPoolSize}") int maxPoolSize)
  {
    HikariDataSource dataSource = new HikariDataSource();
    dataSource.setDriverClassName(driverClassName);
    dataSource.setJdbcUrl(jdbcUrl);
    dataSource.setUsername(username);
    dataSource.setPassword(pwd);
    dataSource.setMaximumPoolSize(maxPoolSize);
    return dataSource;
  }

  @Bean
  public LocalSessionFactoryBean sessionFactory(DataSource dataSource, @Value("${db.schema}") String dbSchema, @Value("${db.dialect}") String dbDialect,
          @Value("${db.show.sql}") Boolean dbShowSql, @Value("${db.hbm2ddl.auto}") String hbm2dll)
  {
    LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
    sessionFactory.setDataSource(dataSource);
    sessionFactory.setPackagesToScan(packagesToScan);

    Properties hibernateProperties = new Properties();
    hibernateProperties.put("hibernate.default_schema", dbSchema);
    hibernateProperties.put("hibernate.dialect", dbDialect);
    hibernateProperties.put("hibernate.show_sql", dbShowSql);
    hibernateProperties.put("hibernate.hbm2ddl.auto", hbm2dll);

    sessionFactory.setHibernateProperties(hibernateProperties);

    return sessionFactory;
  }

  @Bean
  public PlatformTransactionManager transactionManager(LocalSessionFactoryBean sessionFactory)
  {
    HibernateTransactionManager transactionManager = new HibernateTransactionManager();
    transactionManager.setSessionFactory(sessionFactory.getObject());
    return transactionManager;
  }

这工作正常,我的应用程序能够在数据库中读/写。
但是,在某些时候,我需要从readOnly事务创建一个写事务。
我尝试使用@Transactional(propagation = Propagation.REQUIRES_NEW)注解来确保创建一个新的写事务,但它不起作用。

@Service
public class Service1{

  @Autowired
  private Service2 service2;

  @Transactional(readOnly = true)
  public void method1()
  {
    [... read only treatment...]

    service2.method2();

    [... read only treatment...]
  }

}

@Service
public class Service2{

  @Autowired
  private Service3 service3;

  
  public void method2()
  {
    [... read only treatment...]

    method3();

    [... read only treatment...]
  }

  private void method3()
  {
    [... read only treatment...]

    service3.method4();

    [... read only treatment...]
  }

}

@Service
public class Service3{

  @Value("${my.test.prop}")
  private String myTestProp;

  @Transactional(propagation = Propagation.REQUIRES_NEW)
  public void method4()
  {
    System.out.println(myTestProp);    

    [... write treatment...]
  }

}

它确实可以在带有.xml配置和TransactionProxyFactoryBean声明的遗留代码中工作

<bean class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="transactionManager" ref="transactionManager" />
        <property name="transactionAttributes">
            <props>
                <prop key="method1">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="method2">PROPAGATION_REQUIRES_NEW</prop>
            </props>
        </property>
    </bean>

我哪里做错了?
我确保这两个方法在不同的类中,以便SpringAop与第二个@Transactional注解交互
我确实激活了logback来记录事务创建,但我看到没有创建新的事务。
我曾试图切换到JPATransactionManager,但它并没有改善我的问题(事实上,它做得很差,因为readOnly指令被忽略了...)
我还尝试了一个NESTED传播,但它同样没有启动一个新的嵌套事务
编辑:
Spring版本5.3.6
Hibernate版本5.4.33

slhcrj9b

slhcrj9b1#

在发布的类中,method 1()正在调用method 2(),并且都用transactional注解。正如我在我的应用程序中使用的那样,您可以在method 1()上添加@Transactional(propagation = Propagation.REQUIRES_NEW,readOnly = true),它将同时适用于method 1()和method 2()。因为method 2()是在method 1()内部调用的。

@Service
public class Foo{

  @Autowired
  private Bar bar;

  @Transactional(propagation = Propagation.REQUIRES_NEW,readOnly = true)
  public void method1()
  {
    bar.method2();
  }

}

@Service
public class Bar{

 
     public void method2()
      {
        ...
      }

   }

相关问题