如何验证Spring + AspectJ事务?

时间:2014-10-09 19:44:46

标签: java spring spring-boot spring-transactions

我非常确定我的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());拨打电话,declarativeTransactiontrue

有关如何设置@Transactions /验证它们是否正常工作的任何建议?

1 个答案:

答案 0 :(得分:0)

您的配置自相矛盾。

@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)

表示您正在使用方面的加载时间或编译时编织。判断您的配置,您没有使用它。如果我必须判断你的配置你只是使用基本代理而不是编织。只需删除AdviceMode.ASPECTJ它就可以了,你也不需要@EnableAspectJAutoProxy因为申请交易与我们无关它(没有它可以工作)。

此外,您的配置基本上没有使用Spring Boot。你已经自动配置了很多弹簧启动已经为你做的事情。

Spring Boot已经为您配置了以下内容(仅指定@EnableAutoConfiguration

  1. 的EntityManagerFactory
  2. 数据源
  3. 的JdbcTemplate
  4. 交易设置
  5. OpenEntityManagerInView
  6. Spring Web Sockets
  7. 超媒体支持
  8. Spring Data JPA设置
  9. 您可以移除大量配置并在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参考指南,了解已经自动配置的内容。

相关问题