如何在 spring 启动时管理事务
How to manage transactions in spring boot
我有一个 spring 引导应用程序并使用 camel,我读取了一个文件,然后尝试插入我的数据库,一切正常,唯一的问题是我尝试使用 @transactional
或 transactionTemplate
发生错误但不回滚时进行回滚,
使用 @transactional
我将 @EnableTransactionManagement(proxyTargetClass=true)
添加到我的 SpringBootApplication 并在我的 class 中添加 @Transactional(rollbackFor = Exception.class)
这些是我的 classes:
@SpringBootApplication
@EnableDiscoveryClient
@EnableTransactionManagement(proxyTargetClass=true)
public class MsArchivo510Application {
public static void main(String[] args) {
SpringApplication.run(MsArchivo510Application.class, args);
}
}
@Service
public class ArchivoBS implements Processor{
@Transactional(rollbackFor = Exception.class)
@Override
public void process(Exchange exchange) throws Exception {
//Here I execute stored procedure and one of them fail
}
}
使用 transactioTemplate 我的 class 最终是这样的:
@Service
public class ArchivoBS implements Processor{
@Override
public void process(Exchange exchange) throws Exception {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
try {
//Here I execute stored procedure and one of them fail
} catch (Exception e) {
e.printStackTrace();
status.setRollbackOnly();
}
}
});
}
}
我是不是遗漏了什么?有人可以帮我解决这个问题吗?,
提前致谢
您处于骆驼环境中,Spring-boot 可能难以正常工作。
您可以尝试在 spring 服务中进行事务操作并将其注入处理器,然后在服务方法上添加 @Transaction 并从处理器调用它。
最后我注意到我需要为我的数据源指定 DataSourceTransactionManager,我有一个带有注释 @Configuration 的 class 并且我可以在那里创建多个数据源,所以我的 class 是这样的:
@Configuration
public class Configuracion {
@Bean(name = "mysqlNocturno")
@ConfigurationProperties(prefix = "spring.nocturno")
public DataSource mysqlDataSourceNocturno() {
return DataSourceBuilder.create().build();
}
@Bean(name = "jdbcTemplateNocturno")
public JdbcTemplate jdbcTemplateNocturno(@Qualifier("mysqlNocturno") DataSource dsMySQL) {
return new JdbcTemplate(dsMySQL);
}
@Bean(name = "mysqlProduccion")
@Primary
@ConfigurationProperties(prefix = "spring.produccion")
public DataSource mysqlDataSourceProduccion() {
return DataSourceBuilder.create().build();
}
@Bean(name = "jdbcTemplateProduccion")
public JdbcTemplate jdbcTemplateProduccion(@Qualifier("mysqlProduccion") DataSource dsMySQL) {
return new JdbcTemplate(dsMySQL);
}
}
文档提到注解@EnableTransactionManagement 需要添加到我的 SpringBootApplication class 但这不是必需的,它需要添加到我的配置 class,所以我的 class 像这样结束:
@Configuration
@EnableTransactionManagement
public class Configuracion {
@Bean(name = "mysqlNocturno")
@ConfigurationProperties(prefix = "spring.nocturno")
public DataSource mysqlDataSourceNocturno() {
return DataSourceBuilder.create().build();
}
@Bean(name = "jdbcTemplateNocturno")
public JdbcTemplate jdbcTemplateNocturno(@Qualifier("mysqlNocturno") DataSource dsMySQL) {
return new JdbcTemplate(dsMySQL);
}
@Bean(name = "transactionManagerNocturno")
public PlatformTransactionManager transactionManagerNocturno() {
return new DataSourceTransactionManager(mysqlDataSourceNocturno());
}
@Bean(name = "mysqlProduccion")
@Primary
@ConfigurationProperties(prefix = "spring.produccion")
public DataSource mysqlDataSourceProduccion() {
return DataSourceBuilder.create().build();
}
@Bean(name = "jdbcTemplateProduccion")
public JdbcTemplate jdbcTemplateProduccion(@Qualifier("mysqlProduccion") DataSource dsMySQL) {
return new JdbcTemplate(dsMySQL);
}
@Bean(name = "transactionManagerProduccion")
public PlatformTransactionManager transactionManagerProduccion() {
return new DataSourceTransactionManager(mysqlDataSourceProduccion());
}
}
使用此配置,我只需要将@transactional 注释添加到我的 class 中,例如 @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
@Override
public void altaArchivo(Mensaje objMensaje, ArchivoCarnet objArchivoCarnet, ArchivoCarnetTrailer objArchivoCarnetTrailer, List<ArchivoCarnetDetalle> lstArchivoCarnetDetalle) {
if (objMensaje.getStrCodigo().equals(ArchivoErrorEnum.OPERACION_EXITOSA.getStrCodigo())) {
archivoDAO.altaArchivoCarnet(objArchivoCarnet);
archivoDAO.altaArchivoCarnetTrailer(objArchivoCarnetTrailer);
archivoDAO.altaArchivoCarnetDetalle(lstArchivoCarnetDetalle);
} else {
archivoDAO.altaBitacoraArchivo510(new BitacoraArchivo510(objMensaje, objArchivoCarnet.getStrNombre()));
}
}
希望这对其他人有帮助:)
我有一个 spring 引导应用程序并使用 camel,我读取了一个文件,然后尝试插入我的数据库,一切正常,唯一的问题是我尝试使用 @transactional
或 transactionTemplate
发生错误但不回滚时进行回滚,
使用 @transactional
我将 @EnableTransactionManagement(proxyTargetClass=true)
添加到我的 SpringBootApplication 并在我的 class 中添加 @Transactional(rollbackFor = Exception.class)
这些是我的 classes:
@SpringBootApplication
@EnableDiscoveryClient
@EnableTransactionManagement(proxyTargetClass=true)
public class MsArchivo510Application {
public static void main(String[] args) {
SpringApplication.run(MsArchivo510Application.class, args);
}
}
@Service
public class ArchivoBS implements Processor{
@Transactional(rollbackFor = Exception.class)
@Override
public void process(Exchange exchange) throws Exception {
//Here I execute stored procedure and one of them fail
}
}
使用 transactioTemplate 我的 class 最终是这样的:
@Service
public class ArchivoBS implements Processor{
@Override
public void process(Exchange exchange) throws Exception {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
try {
//Here I execute stored procedure and one of them fail
} catch (Exception e) {
e.printStackTrace();
status.setRollbackOnly();
}
}
});
}
}
我是不是遗漏了什么?有人可以帮我解决这个问题吗?,
提前致谢
您处于骆驼环境中,Spring-boot 可能难以正常工作。 您可以尝试在 spring 服务中进行事务操作并将其注入处理器,然后在服务方法上添加 @Transaction 并从处理器调用它。
最后我注意到我需要为我的数据源指定 DataSourceTransactionManager,我有一个带有注释 @Configuration 的 class 并且我可以在那里创建多个数据源,所以我的 class 是这样的:
@Configuration
public class Configuracion {
@Bean(name = "mysqlNocturno")
@ConfigurationProperties(prefix = "spring.nocturno")
public DataSource mysqlDataSourceNocturno() {
return DataSourceBuilder.create().build();
}
@Bean(name = "jdbcTemplateNocturno")
public JdbcTemplate jdbcTemplateNocturno(@Qualifier("mysqlNocturno") DataSource dsMySQL) {
return new JdbcTemplate(dsMySQL);
}
@Bean(name = "mysqlProduccion")
@Primary
@ConfigurationProperties(prefix = "spring.produccion")
public DataSource mysqlDataSourceProduccion() {
return DataSourceBuilder.create().build();
}
@Bean(name = "jdbcTemplateProduccion")
public JdbcTemplate jdbcTemplateProduccion(@Qualifier("mysqlProduccion") DataSource dsMySQL) {
return new JdbcTemplate(dsMySQL);
}
}
文档提到注解@EnableTransactionManagement 需要添加到我的 SpringBootApplication class 但这不是必需的,它需要添加到我的配置 class,所以我的 class 像这样结束:
@Configuration
@EnableTransactionManagement
public class Configuracion {
@Bean(name = "mysqlNocturno")
@ConfigurationProperties(prefix = "spring.nocturno")
public DataSource mysqlDataSourceNocturno() {
return DataSourceBuilder.create().build();
}
@Bean(name = "jdbcTemplateNocturno")
public JdbcTemplate jdbcTemplateNocturno(@Qualifier("mysqlNocturno") DataSource dsMySQL) {
return new JdbcTemplate(dsMySQL);
}
@Bean(name = "transactionManagerNocturno")
public PlatformTransactionManager transactionManagerNocturno() {
return new DataSourceTransactionManager(mysqlDataSourceNocturno());
}
@Bean(name = "mysqlProduccion")
@Primary
@ConfigurationProperties(prefix = "spring.produccion")
public DataSource mysqlDataSourceProduccion() {
return DataSourceBuilder.create().build();
}
@Bean(name = "jdbcTemplateProduccion")
public JdbcTemplate jdbcTemplateProduccion(@Qualifier("mysqlProduccion") DataSource dsMySQL) {
return new JdbcTemplate(dsMySQL);
}
@Bean(name = "transactionManagerProduccion")
public PlatformTransactionManager transactionManagerProduccion() {
return new DataSourceTransactionManager(mysqlDataSourceProduccion());
}
}
使用此配置,我只需要将@transactional 注释添加到我的 class 中,例如 @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
@Override
public void altaArchivo(Mensaje objMensaje, ArchivoCarnet objArchivoCarnet, ArchivoCarnetTrailer objArchivoCarnetTrailer, List<ArchivoCarnetDetalle> lstArchivoCarnetDetalle) {
if (objMensaje.getStrCodigo().equals(ArchivoErrorEnum.OPERACION_EXITOSA.getStrCodigo())) {
archivoDAO.altaArchivoCarnet(objArchivoCarnet);
archivoDAO.altaArchivoCarnetTrailer(objArchivoCarnetTrailer);
archivoDAO.altaArchivoCarnetDetalle(lstArchivoCarnetDetalle);
} else {
archivoDAO.altaBitacoraArchivo510(new BitacoraArchivo510(objMensaje, objArchivoCarnet.getStrNombre()));
}
}
希望这对其他人有帮助:)