如何解决两个不同LocalContainerEntityManagerFactoryBean上的@PersistenceContext抛出TransactionRequiredException
我设置了两个LocalContainerEntityManagerFactoryBean
,一个带有@Primary
注释,另一个没有。这是因为我必须与两个不同的数据库进行通信,并且如果删除@Primary
装饰,则会收到重复的bean错误。两者的构建方式完全相同,这里供参考:
package com.myorg.rest.config.dba;
import ...
@Configuration
@EnableJpaRepositories(
basePackages = "com.myorg.rest.dao.dbA",entityManagerFactoryRef = "dbAEntityManager",transactionManagerRef = "dbATransactionManager"
)
@EnableTransactionManagement
public class DbADataSourceConfig {
@Autowired
private EnvProperties settings;
@Bean
@Primary
public DataSource prjDataSource() {
DataSourceProperties ds = settings.getdbADatasource();
return ds.initializeDataSourceBuilder().type(BasicDataSource.class).build();
}
@Bean(name = "dbAEntityManager")
@Primary
public LocalContainerEntityManagerFactoryBean dbAEntityManager() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(prjDataSource());
em.setPackagesToScan(new String[] { "com.myorg.model.entities.dba" });
em.setPersistenceUnitName("dbAUnit");
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
// em.afterPropertiesSet();
return em;
}
@Bean(name = "dbATransactionManager")
@Primary
public PlatformTransactionManager dbATransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(dbAEntityManager().getObject());
return transactionManager;
}
Properties additionalProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.dialect","org.hibernate.dialect.MySQL5Dialect");
return properties;
}
}
它们都用@PersistenceContext(unitName = "dbAUnit")
和@PersistenceContext(unitName = "dbBUnit")
注入到DAO中,并且它们都成功地引导了内部的相应EntityManager。我可以在它们两个中创建,然后检索创建的实体。但是,当我使用以下内容检索所有实体时:
public List<T> findAll() {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<T> entityQuery = criteriaBuilder.createQuery(clazz);
entityQuery.from(clazz);
return entityManager.createQuery(entityQuery).getResultList();
}
其中一个可以完美地工作,而另一个则不能(返回0个实体)。调试之后,我意识到其中一个正在发出insert into...
sql命令,而另一个没有。我尝试用entityManager.flush()
强行得到
Caused by:
javax.persistence.TransactionRequiredException: no transaction is in progress
at org.hibernate.internal.AbstractSharedSessionContract.checkTransactionNeededForUpdateOperation(AbstractSharedSessionContract.java:413)
at org.hibernate.internal.SessionImpl.checkTransactionNeededForUpdateOperation(SessionImpl.java:3398)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1355)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1350)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:366)
at com.sun.proxy.$Proxy95.flush(Unknown Source)
然后我尝试用@Transactional
装饰DAO,并进一步用@Transactional
装饰每个方法。还尝试使用@PersistenceContext(unitName = "dbAUnit",type = PersistenceContextType.TRANSACTION)
进行注入,但是所有这些尝试都会导致完全相同的错误。
“次要” @PersistenceContext
为什么不进行交易?
解决方法
当多个事务管理器与@Transactional
一起使用时,您需要声明该事务管理器以显式使用,否则@Primary
管理器将始终被选中,并且辅助EntityManager
可能无法加入交易。
在注入第二个持久性上下文的任何地方尝试使用@Transactional("dbBTransactionManager")
,以查看问题是否消失。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。