我目前正在重构一些遗留代码。
我们正在从.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
1条答案
按热度按时间slhcrj9b1#
在发布的类中,method 1()正在调用method 2(),并且都用transactional注解。正如我在我的应用程序中使用的那样,您可以在method 1()上添加@Transactional(propagation = Propagation.REQUIRES_NEW,readOnly = true),它将同时适用于method 1()和method 2()。因为method 2()是在method 1()内部调用的。