模式= AdviceMode.ASPECTJ的Spring事务无法正常工作

时间:2019-07-13 09:32:26

标签: java spring spring-boot aspectj spring-transactions

我知道默认情况下,spring事务与mode = AdviceMode.PROXY一起工作,但是我们没有机会在一个服务中打开新事务。使用mode = AdviceMode.ASPECTJ解决此问题。但是我的代码无法正确使用此属性。

配置:

@Configuration
@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)
@EnableJpaRepositories(
        entityManagerFactoryRef = "mysqlEntityManagerFactory",
        transactionManagerRef = "mysqlTransactionManager",
        basePackages = {"softserve.spring.com.repository"}
)
public class TransactionConfig {

    @Bean(name = "mysqlDataSource")
    @ConfigurationProperties(prefix = "mysql.datasource")
    public DataSource dataSource() {
        return DataSourceBuilder
                .create()
                .build();
    }

    @Bean(name = "mysqlEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean mysqlEntityManagerFactory(
            EntityManagerFactoryBuilder builder,
            @Qualifier("mysqlDataSource") DataSource dataSource
    ) {
        return builder
                .dataSource(dataSource)
                .packages("softserve.spring.com.entity")
                .persistenceUnit("mysql")
                .build();
    }

    @Bean(name = "mysqlTransactionManager")
    public PlatformTransactionManager mysqlTransactionManager(
            @Qualifier("mysqlEntityManagerFactory") EntityManagerFactory mysqlEntityManagerFactory
    ) {
        return new JpaTransactionManager(mysqlEntityManagerFactory);
    }

}

属性:

spring.jpa.hibernate.ddl-auto=validate
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql=false

mysql.datasource.jdbc-url=jdbc:mysql://localhost:3306/db_transaction?useSSL=false&useUnicode=yes&characterEncoding=UTF-8
mysql.datasource.username=root
mysql.datasource.password=root
mysql.datasource.driver-class-name=com.mysql.jdbc.Driver

服务:

@Service
public class UserService {

    @Autowired
    private UserRepository userrepository;

    @Transactional
    public void createUsers() {
        create();

        User user = new User("B", 0);
        userrepository.save(user);

        throw new RuntimeException();
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void create() {
        User user = new User("A", 100);
        userrepository.save(user);
    }

    @Transactional
    public void deleteAll() {
        userrepository.deleteAll();
    }

}

执行此代码后,数据库中必须是一个用户。但是我有两个。如何正确设置?

1 个答案:

答案 0 :(得分:0)

使用代理时,您必须知道在this上调用方法时会发生什么(什么不会发生),就像使用create()一样。 阅读the documentation,了解为什么this不是事务处理bean:

  

但是,一旦调用最终到达目标对象(在本例中为SimplePojo,则为引用),它可能对其自身进行的任何方法调用(例如this.bar()或this.foo())都会进行将针对此引用而不是代理进行调用。这具有重要的意义。这意味着自调用不会导致与方法调用相关的建议得到执行的机会。

但是,在使用AspectJ时,类的字节码是与事务处理方面交织在一起的,因此即使对this的调用也可以按预期工作。