java - 如何验证 Spring + AspecJ 事务?

标签 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/验证它们是否正常工作有什么建议吗?

最佳答案

您的配置自相矛盾。

@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)

意味着您正在使用方面的加载时或编译时编织。根据您的配置判断,您没有使用它。如果我必须判断您的配置,您只是使用基本代理而不是编织。只需删除 AdviceMode.ASPECTJ 即可工作,您也不需要 @EnableAspectJAutoProxy 作为应用事务与它无关(没有它它也可以工作)。

此外,您的配置做了很多工作,基本上不使用 Spring Boot。你已经配置了很多 Spring Boot 已经自动、手动为你做的事情。

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

  1. EntityManagerFactory
  2. 数据源
  3. JdbcTemplate
  4. 交易设置
  5. OpenEntityManagerInView
  6. Spring Web 套接字
  7. 超媒体支持
  8. 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/

相关文章:

java - Tomcat 推荐人锁定

java - 使用 Axis2 处理 ArrayOfAnyType (Java)

java - 使用注释的构造函数注入(inject)

java - 在 Vaadin 8 中传递和接收数据

spring-boot - Spring Boot执行器尝试建立数据库连接

Java 版本 "Pointer Pointer"

java - 搜索 anchor 标记时,Selenium findElement(s) 出现问题

java - 启动 Tomcat 7.0 时出错

java - Neo4j Java 驱动程序抛出 "connection reset by peer"异常

java - 我如何像在MySQL中那样在Spring Boot JPA中建立一对多关系?