- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我在 spring 上处理两个事务,它引用了两个实体管理器,因此引用了两个数据源,同时使用 @Transactional("transaction1")
它工作正常但是 @Transactional("transaction2")
抛出一个错误,指出未找到 Activity 事务。以下是一段代码:
@Bean(name = "transaction1")
public PlatformTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactoryBean2()
.getObject());
return transactionManager;
}
@Bean(name = "transaction2")
public PlatformTransactionManager sermaTransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager
.setEntityManagerFactory(entityManagerFactoryBean1()
.getObject());
return transactionManager;
}
各自的实体经理:
@Bean(name = "entitymanager1")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean1() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource1());
entityManagerFactoryBean
.setPackagesToScan(new String[] { this.environment
.getProperty("db.packagesToScan") });
entityManagerFactoryBean
.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter());
Map<String, Object> jpaProperties = new HashMap<String, Object>();
jpaProperties.put("eclipselink.weaving", "false");
jpaProperties.put("eclipselink.logging.level", "INFO");
jpaProperties.put("eclipselink.logging.parameters", "true");
entityManagerFactoryBean.setJpaPropertyMap(jpaProperties);
return entityManagerFactoryBean;
}
@Bean(name = "entitymanager2")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean2() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource2());
entityManagerFactoryBean
.setPackagesToScan(new String[] { this.environment
.getProperty("db.packagesToScan") });
entityManagerFactoryBean
.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter());
Map<String, Object> jpaProperties = new HashMap<String, Object>();
jpaProperties.put("eclipselink.weaving", "false");
jpaProperties.put("eclipselink.logging.parameters", "true");
jpaProperties.put("eclipselink.logging.level", "INFO");
entityManagerFactoryBean.setJpaPropertyMap(jpaProperties);
return entityManagerFactoryBean;
}
各自的数据源:
@Bean("datasource1")
public DriverManagerDataSource dataSource1() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource .setDriverClassName(this.environment.getProperty("db.driver"));
dataSource.setUrl(this.environment.getProperty("db.url"));
dataSource.setUsername(this.environment
.getProperty("db.username.abc"));
dataSource.setPassword(this.environment
.getProperty("db.password.abc"));
return dataSource;
}
@Bean("datasource2")
public DriverManagerDataSource dataSource2() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource
.setDriverClassName(this.environment.getProperty("db.driver"));
dataSource.setUrl(this.environment.getProperty("db.url"));
dataSource.setUsername(this.environment.getProperty("db.username"));
dataSource.setPassword(this.environment.getProperty("db.password"));
return dataSource;
}
我的 genericDaoImpl 具有以下链接各个实体管理器的内容:
@PersistenceContext(unitName = "entitymanager1")
private EntityManager em1;
@PersistenceContext(unitName = "entitymanager2")
private EntityManager em2;
当我执行@Transactional("transaction1") 时它工作正常,但是当我执行@Transactional("transaction2") 时它说没有 Activity 事务。当我没有提到交易的限定符时,错误说找到了两个交易(交易 1、交易 2)。任何帮助都会很棒。
最佳答案
配置有问题:
问题是当 bean 像这样初始化时:
transactionManager.setEntityManagerFactory(entityManagerFactoryBean2().getObject());
调用entityManagerFactoryBean2()
会创建一个新的实体管理器工厂,然后@Bean注解会触发另一个实体管理器工厂的创建,与配置。
当您在 bean 中注入(inject)带有 @Autowired
的实体管理器工厂时,您注入(inject)的是用 @Bean 创建的实例,不是传递给事务管理器的实例.
一个关于配置的警告:
上面的配置允许在两个单独的数据源中进行事务处理,但是使用此配置不可能进行跨越两个 数据库的事务处理。例如:
@Service
public class PlanesService {
@PersistenceContext(unitName = "entityManagerFactory1")
private EntityManager em1;
@PersistenceContext(unitName = "entityManagerFactory2")
private EntityManager em2;
@Transactional("transactionManager1")
public Plane savePlanes() {
F14 f14 = new F14("F14","f14");
F16 f16 = new F16("F16","f16");
em1.persist(f14);
em2.persist(f16);
return f14;
}
}
此代码将仅保留 f14,因为唯一具有正在进行的事务的实体管理器是 em1(由于 @Transactional("transactionManager1")
)。对 em2.persist()
的调用将被忽略(尽管 em2 仍然可以读取)。
如果您想执行包含两个数据库的事务,您需要一个 JTA 事务管理器。
工作配置示例:
这是修复上述注入(inject)问题的配置示例:
@Configuration
public class DataSourcesConfig {
@Bean(name = "datasource1")
public DriverManagerDataSource dataSource1() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
...
return dataSource;
}
@Bean(name = "datasource2")
public DriverManagerDataSource dataSource2() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
...
return dataSource;
}
}
@Configuration
public class EntityManagerFactoriesConfiguration {
@Autowired
@Qualifier("datasource1")
private DataSource dataSource1;
@Autowired
@Qualifier("datasource2")
private DataSource dataSource2;
@Bean(name = "entityManagerFactory1")
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource1);
entityManagerFactoryBean.setPackagesToScan(new String[] { "your.package.here" });
entityManagerFactoryBean.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
Map<String, Object> jpaProperties = new HashMap<String, Object>();
...
entityManagerFactoryBean.setJpaPropertyMap(jpaProperties);
return entityManagerFactoryBean;
}
@Bean(name = "entityManagerFactory2")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean2() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource2);
entityManagerFactoryBean.setPackagesToScan(new String[] { "your.package.here" });
entityManagerFactoryBean.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
Map<String, Object> jpaProperties = new HashMap<String, Object>();
entityManagerFactoryBean.setJpaPropertyMap(jpaProperties);
...
return entityManagerFactoryBean;
}
}
@Configuration
@EnableTransactionManagement
public class TransactionManagersConfig {
@Autowired
@Qualifier("entityManagerFactory1")
EntityManagerFactory entityManagerFactory1;
@Autowired
@Qualifier("entityManagerFactory2")
EntityManagerFactory entityManagerFactory2;
@Autowired
@Qualifier("datasource1")
private DataSource dataSource1;
@Autowired
@Qualifier("datasource2")
private DataSource dataSource2;
@Bean(name = "transactionManager1")
public PlatformTransactionManager transactionManager1() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory1);
transactionManager.setDataSource(dataSource1);
return transactionManager;
}
@Bean(name = "transactionManager2")
public PlatformTransactionManager transactionManager2() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory2);
transactionManager.setDataSource(dataSource2);
return transactionManager;
}
}
通过将配置拆分为多个 @Configuration
类并 Autowiring 它们,我们确保始终使用相同的 beans(单例)。
注意启用@Transactional 的@EnableTransactionManagement
注释。
关于java - 使用两个事务,一个似乎有效,但另一个无效。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21051541/
我是一名优秀的程序员,十分优秀!