我很确定事务没有应用在我的 Spring Boot 应用程序中,即使我正在使用 @EnableTransactionManagement(mode=AdviceMode.ASPECTJ)
& 有spring-aspects
在我的应用程序中。
配置
@Configuration
public class DatastoreConfig{
@Bean
public DataSource dataSource(){ ///... }
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource){
return new JdbcTemplate(dataSource);
}
@Bean
public String databaseSchema(){
return "mySchema";
}
@Bean
public OpenSessionInViewInterceptor openSessionInViewInterceptor(SessionFactory sessionFactory){
OpenSessionInViewInterceptor result = new OpenSessionInViewInterceptor();
result.setSessionFactory(sessionFactory);
return result;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, JpaVendorAdapter vendorAdapter){
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan( Main.class.getPackage().getName() + ".model");
factory.setDataSource(dataSource);
factory.setJpaProperties(getJpaProperties());
factory.afterPropertiesSet();
return factory;
}
@Bean
public HibernateJpaVendorAdapter jpaVendorAdapter(){
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(false);
vendorAdapter.setDatabasePlatform(PostgreSQL9Dialect.class.getName());
return vendorAdapter;
}
@Bean
public SessionFactory sessionFactory(HibernateEntityManagerFactory emf){
SessionFactoryImpl sf = (SessionFactoryImpl) emf.getSessionFactory();
return sf;
}
private Properties getJpaProperties() {
Properties props = new Properties();
// props.put("hibernate.hbm2ddl.auto", "validate");
props.put("hibernate.ejb.naming_strategy", ImprovedNamingStrategy.class.getName());
props.put("hibernate.enable_lazy_load_no_trans", "true");
props.put("jadira.usertype.autoRegisterUserTypes", "true");
return props;
}
@Bean
public JpaTransactionManager transactionManager(EntityManagerFactory emf) throws PropertyVetoException {
JpaTransactionManager transactionManager = new JpaTransactionManager(emf);
transactionManager.setRollbackOnCommitFailure(true);
transactionManager.setDataSource(dataSource());
return transactionManager;
}
@Bean
public NamedParameterJdbcTemplate namedParameterJdbcTemplate(DataSource dataSource) {
return new NamedParameterJdbcTemplate(dataSource);
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
}
主类
@Configuration
@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)
@ComponentScan
@EnableAsync
@EnableScheduling
@EnableEntityLinks
@EnableAspectJAutoProxy
@EnableApiResources(apiPrefix = "")
@EnableJpaRepositories(transactionManagerRef = "transactionManager")
@EnableHypermediaSupport(type = EnableHypermediaSupport.HypermediaType.HAL)
@EnableConfigurationProperties
@EnableAutoConfiguration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
@EnableWebSocketMessageBroker
@Slf4j
public class Main extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(
SpringApplicationBuilder application) {
return application.sources(Main.class);
}
public static void main(String[] args) {
Object[] sources = {
Main.class,
TomcatConfig.class // include for embedded tomcat...
};
ConfigurableApplicationContext result = SpringApplication.run(sources, args);
}
}
尝试验证
我尝试验证的方法之一是运行
@Component
public class SomeService{
@Transactional
@Override
protected void tryItOut(){
// this is always false
boolean declarativeTransaction = TransactionSynchronizationManager.isActualTransactionActive();
// this throws an exception
TransactionStatus aspect = TransactionAspectSupport.currentTransactionStatus();
}
}
但是,如果我插入对 transactionManager.getTransaction(new DefaultTransactionDefinition());
的调用事先,declarativeTransaction
是 true
.
关于如何设置@Transactions/验证它们是否正常工作有什么建议吗?
最佳答案
您的配置自相矛盾。
@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)
意味着您正在使用方面的加载时或编译时编织。根据您的配置判断,您没有使用它。如果我必须判断您的配置,您只是使用基本代理而不是编织。只需删除 AdviceMode.ASPECTJ
即可工作,您也不需要 @EnableAspectJAutoProxy
作为应用事务与它无关(没有它它也可以工作)。
此外,您的配置做了很多工作,基本上不使用 Spring Boot。你已经配置了很多 Spring Boot 已经自动、手动为你做的事情。
Spring Boot 已经为您配置了以下内容(只需指定 @EnableAutoConfiguration
。
- EntityManagerFactory
- 数据源
- JdbcTemplate
- 交易设置
- OpenEntityManagerInView
- Spring Web 套接字
- 超媒体支持
- Spring Data JPA 设置
您可以删除大量配置并将一些属性放入 application.properties
中。
如果您确实需要 SessionFactory
而不是自己进行转换,我强烈建议使用 HibernateJpaSessionFactoryBean
。
我怀疑以下主类仍然可以工作(启用事务)。
@Configuration
@ComponentScan
@EnableAsync
@EnableScheduling
@EnableAutoConfiguration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
@EnableWebSocketMessageBroker
@Slf4j
public class Main extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(
SpringApplicationBuilder application) {
return application.sources(Main.class);
}
public static void main(String[] args) {
Object[] sources = {
Main.class,
TomcatConfig.class // include for embedded tomcat...
};
ConfigurableApplicationContext result = SpringApplication.run(sources, args);
}
}
使用这个DatastoreConfig
类
@Configuration
public class DatastoreConfig{
@Bean
public FactoryBean<SessionFactory> sessionFactory(EntityManagerFactory emf){
HibernateJpaSessionFactoryBean jpaSessionFactoryBean = new HibernateJpaSessionFactoryBean();
jpaSessionFactoryBean.setEntityManagerFactory(emf);
return jpaSessionFactoryBean;
}
}
还有这个application.properties
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
spring.jpa.properties.jadira.usertype.autoRegisterUserTypes=true
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL9Dialect
您可能需要添加一些 spring.datasource.
属性才能正确设置数据源。另外,从您有一个 OpenSessionInViewInterceptor
的事实来看,您使用它而不是 OpenEntityManagerInViewInterceptor
(或过滤器)。所以你甚至可以删除它。
不确定这是否是您的配置,但您也许可以删除/修剪更多。我建议查看 Spring Boot 引用指南,以了解已经自动配置的内容。
关于java - 如何验证 Spring + AspecJ 事务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26286736/