gpt4 book ai didi

java - 使用两个事务,一个似乎有效,但另一个无效。为什么?

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:06:17 25 4
gpt4 key购买 nike

我在 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com