@Transactional 即使使用编译时编织插件也会抛出 TransactionRequiredException 与 ASPECTJ ?

发布于 2025-01-18 03:48:16 字数 6963 浏览 4 评论 0原文

@Transactional 抛出 TransactionRequiredException:没有可用于当前线程的实际事务的 EntityManager - 无法可靠地处理持久性 使用 AspectJ 时,即使安装了编译时编织插件并安装了所有 AspectJ 依赖项和开发工具。

可能类似的问题: 为什么要从 AspectJ 切换到代理模式导致“TransactionRequiredException:执行更新/删除查询”不再发生?

我打算使用AspectJ而不是Spring AOP提高我的应用程序的性能。

这里我展示了三个文件的一部分。 AspectJ 开发工具包已安装。

pom.xml:

...

      <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.9.8</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.8</version>
        </dependency>
        <dependency>
            <groupId>dev.aspectj</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.13.1</version>
            <type>maven-plugin</type>
        </dependency>


...


            <build>
                <plugins>                  
                    <plugin>
                        <groupId>org.codehaus.mojo</groupId>
                        <artifactId>aspectj-maven-plugin</artifactId>
                        <version>1.6</version>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>compile</goal>
                                    <!-- <goal>test-compile</goal> -->
                                </goals>
                            </execution>
                        </executions>
                        <configuration>
                            <complianceLevel>17</complianceLevel>
                            <forceAjcCompile>true</forceAjcCompile>
                            <weaveDirectories>
                                <weaveDirectory>${project.build.outputDirectory}</weaveDirectory>
                            </weaveDirectories>
                            <aspectLibraries>
                                <aspectLibrary>
                                    <groupId>org.springframework</groupId>
                                    <artifactId>spring-aspects</artifactId>
                                </aspectLibrary>
                            </aspectLibraries>
                        </configuration>
                    </plugin>
            </plugins>
        </build>

XService.java:

@Service
@Transactional(propagation = Propagation.SUPPORTS)
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class BridgeService {
...
    @Transactional
    private void persistAvatarResource(String resCode, String start) {
        AvatarRes avatarRes = new AvatarRes();
        avatarRes.setClient(client);
        avatarRes.setAvatar(avatar);
        avatarRes.setRes(getResource(resCode));
        avatarRes.setStart(PHPHelper.toInt(start));

        entityManager.persist(avatarRes);

    }
...
}

DatabaseConfig.java:

@Configuration
@EnableJpaRepositories("com.lixar.apba.repository")
@EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware")
@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)
public class DatabaseConfiguration {

    private final Logger log = LoggerFactory.getLogger(DatabaseConfiguration.class);

    @Inject
    private Environment env;

    @Autowired(required = false)
    private MetricRegistry metricRegistry;

    @Bean(destroyMethod = "close")
    @ConditionalOnExpression("!environment.acceptsProfiles('cloud') && !environment.acceptsProfiles('heroku')")
    public DataSource dataSource(DataSourceProperties dataSourceProperties, JHipsterProperties jHipsterProperties, CacheManager cacheManager) {
        log.debug("Configuring Datasource");
        if (dataSourceProperties.getUrl() == null) {
            log.error("Your database connection pool configuration is incorrect! The application" +
                    " cannot start. Please check your Spring profile, current profiles are: {}",
                Arrays.toString(env.getActiveProfiles()));

            throw new ApplicationContextException("Database connection pool is not configured correctly");
        }
        HikariConfig config = new HikariConfig();
        config.setDataSourceClassName(dataSourceProperties.getDriverClassName());
        config.addDataSourceProperty("url", dataSourceProperties.getUrl());
        if (dataSourceProperties.getUsername() != null) {
            config.addDataSourceProperty("user", dataSourceProperties.getUsername());
        } else {
            config.addDataSourceProperty("user", ""); // HikariCP doesn't allow null user
        }
        if (dataSourceProperties.getPassword() != null) {
            config.addDataSourceProperty("password", dataSourceProperties.getPassword());
        } else {
            config.addDataSourceProperty("password", ""); // HikariCP doesn't allow null password
        }
        
        config.setConnectionTimeout(jHipsterProperties.getDatasource().getConnectionTimeout());
        config.setMaximumPoolSize(jHipsterProperties.getDatasource().getMaximumPoolSize());

        //MySQL optimizations, see https://github.com/brettwooldridge/HikariCP/wiki/MySQL-Configuration
        if ("com.mysql.jdbc.jdbc2.optional.MysqlDataSource".equals(dataSourceProperties.getDriverClassName())) {
            config.addDataSourceProperty("cachePrepStmts", jHipsterProperties.getDatasource().isCachePrepStmts());
            config.addDataSourceProperty("prepStmtCacheSize", jHipsterProperties.getDatasource().getPrepStmtCacheSize());
            config.addDataSourceProperty("prepStmtCacheSqlLimit", jHipsterProperties.getDatasource().getPrepStmtCacheSqlLimit());
        }
        if (metricRegistry != null) {
            config.setMetricRegistry(metricRegistry);
        }
        return new HikariDataSource(config);
    }

   
    
    @Bean
    public Hibernate5Module hibernate5Module() {
        return new Hibernate5Module();
    }
}

@Transactional throws TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process persist
when using AspectJ even with compile-time weaving plugin and all AspectJ dependencies and Development tools installed.

Possibly similar question: Why would switching from AspectJ to Proxy mode cause a "TransactionRequiredException: Executing an update/delete query" to no longer occur?

I intend to use AspectJ instead of Spring AOP to increase the performance of my app.

Here I presented part of three files. AspectJ Development Toolkit is installed.

pom.xml:

...

      <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.9.8</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.8</version>
        </dependency>
        <dependency>
            <groupId>dev.aspectj</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.13.1</version>
            <type>maven-plugin</type>
        </dependency>


...


            <build>
                <plugins>                  
                    <plugin>
                        <groupId>org.codehaus.mojo</groupId>
                        <artifactId>aspectj-maven-plugin</artifactId>
                        <version>1.6</version>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>compile</goal>
                                    <!-- <goal>test-compile</goal> -->
                                </goals>
                            </execution>
                        </executions>
                        <configuration>
                            <complianceLevel>17</complianceLevel>
                            <forceAjcCompile>true</forceAjcCompile>
                            <weaveDirectories>
                                <weaveDirectory>${project.build.outputDirectory}</weaveDirectory>
                            </weaveDirectories>
                            <aspectLibraries>
                                <aspectLibrary>
                                    <groupId>org.springframework</groupId>
                                    <artifactId>spring-aspects</artifactId>
                                </aspectLibrary>
                            </aspectLibraries>
                        </configuration>
                    </plugin>
            </plugins>
        </build>

XService.java:

@Service
@Transactional(propagation = Propagation.SUPPORTS)
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class BridgeService {
...
    @Transactional
    private void persistAvatarResource(String resCode, String start) {
        AvatarRes avatarRes = new AvatarRes();
        avatarRes.setClient(client);
        avatarRes.setAvatar(avatar);
        avatarRes.setRes(getResource(resCode));
        avatarRes.setStart(PHPHelper.toInt(start));

        entityManager.persist(avatarRes);

    }
...
}

DatabaseConfig.java:

@Configuration
@EnableJpaRepositories("com.lixar.apba.repository")
@EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware")
@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)
public class DatabaseConfiguration {

    private final Logger log = LoggerFactory.getLogger(DatabaseConfiguration.class);

    @Inject
    private Environment env;

    @Autowired(required = false)
    private MetricRegistry metricRegistry;

    @Bean(destroyMethod = "close")
    @ConditionalOnExpression("!environment.acceptsProfiles('cloud') && !environment.acceptsProfiles('heroku')")
    public DataSource dataSource(DataSourceProperties dataSourceProperties, JHipsterProperties jHipsterProperties, CacheManager cacheManager) {
        log.debug("Configuring Datasource");
        if (dataSourceProperties.getUrl() == null) {
            log.error("Your database connection pool configuration is incorrect! The application" +
                    " cannot start. Please check your Spring profile, current profiles are: {}",
                Arrays.toString(env.getActiveProfiles()));

            throw new ApplicationContextException("Database connection pool is not configured correctly");
        }
        HikariConfig config = new HikariConfig();
        config.setDataSourceClassName(dataSourceProperties.getDriverClassName());
        config.addDataSourceProperty("url", dataSourceProperties.getUrl());
        if (dataSourceProperties.getUsername() != null) {
            config.addDataSourceProperty("user", dataSourceProperties.getUsername());
        } else {
            config.addDataSourceProperty("user", ""); // HikariCP doesn't allow null user
        }
        if (dataSourceProperties.getPassword() != null) {
            config.addDataSourceProperty("password", dataSourceProperties.getPassword());
        } else {
            config.addDataSourceProperty("password", ""); // HikariCP doesn't allow null password
        }
        
        config.setConnectionTimeout(jHipsterProperties.getDatasource().getConnectionTimeout());
        config.setMaximumPoolSize(jHipsterProperties.getDatasource().getMaximumPoolSize());

        //MySQL optimizations, see https://github.com/brettwooldridge/HikariCP/wiki/MySQL-Configuration
        if ("com.mysql.jdbc.jdbc2.optional.MysqlDataSource".equals(dataSourceProperties.getDriverClassName())) {
            config.addDataSourceProperty("cachePrepStmts", jHipsterProperties.getDatasource().isCachePrepStmts());
            config.addDataSourceProperty("prepStmtCacheSize", jHipsterProperties.getDatasource().getPrepStmtCacheSize());
            config.addDataSourceProperty("prepStmtCacheSqlLimit", jHipsterProperties.getDatasource().getPrepStmtCacheSqlLimit());
        }
        if (metricRegistry != null) {
            config.setMetricRegistry(metricRegistry);
        }
        return new HikariDataSource(config);
    }

   
    
    @Bean
    public Hibernate5Module hibernate5Module() {
        return new Hibernate5Module();
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文