@PersistenceContext 在两个不同的 LocalContainerEntityManagerFactoryBean 上抛出 TransactionRequiredException
@PersistenceContext on two different LocalContainerEntityManagerFactoryBean throws 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();
}
其中一个可以完美运行,而另一个则不能(returns 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)
进行注入,但所有这些尝试都会导致完全相同的错误。
为什么 'secondary' @PersistenceContext
没有放入交易?
在 @Transactional
中使用多个事务管理器时,您需要显式声明要使用的事务管理器,否则总是会选择 @Primary
管理器,而您的辅助 EntityManager
不可能加入它的交易。
尝试在注入第二个持久性上下文的地方使用@Transactional("dbBTransactionManager")
,看看问题是否消失。
我设置了两个 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();
}
其中一个可以完美运行,而另一个则不能(returns 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)
进行注入,但所有这些尝试都会导致完全相同的错误。
为什么 'secondary' @PersistenceContext
没有放入交易?
在 @Transactional
中使用多个事务管理器时,您需要显式声明要使用的事务管理器,否则总是会选择 @Primary
管理器,而您的辅助 EntityManager
不可能加入它的交易。
尝试在注入第二个持久性上下文的地方使用@Transactional("dbBTransactionManager")
,看看问题是否消失。