简体   繁体   English

使用两个交易,一个似乎工作,但另一个没有。 为什么?

[英]working with two transactions, one seem to work but the other does not. why?

I'm working with two transactions on spring which has reference to two entitymanagers and hence two datasources, while using @Transactional("transaction1") it works fine but @Transactional("transaction2") throws out an error saying no active transactions found. 我正在使用spring上的两个事务,它引用了两个实体管理器,因此引用了两个数据源,而使用@Transactional("transaction1")它工作正常,但@Transactional("transaction2")抛出一个错误,表示没有找到活动事务。 following is the piece of code: 以下是一段代码:

    @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;
        }

respective entitymanagers: 各实体管理人员:

    @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;
        }

respective datasources: 各自的数据源:

@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;
    }

My genericDaoImpl has the following to link respective entitymanagers: 我的genericDaoImpl具有以下链接各自的实体管理者:

@PersistenceContext(unitName = "entitymanager1")
    private EntityManager em1;

    @PersistenceContext(unitName = "entitymanager2")
    private EntityManager em2;

when i do @Transactional("transaction1") it works fine, but when i do @Transactional("transaction2") it says no active transactions. 当我做@Transactional(“transaction1”)它工作正常,但当我做@Transactional(“transaction2”)时,它说没有活动的交易。 and when i dont mention the qualifier for the transactions, error says two transactions found (transaction1, transaction2). 当我没有提到交易的限定符时,错误说找到了两个交易(transaction1,transaction2)。 any help would be great. 任何帮助都会很棒。

There is an issue with the config: 配置存在问题:

The problem is that when the beans are initialized like this: 问题是当bean初始化时如下:

transactionManager.setEntityManagerFactory(entityManagerFactoryBean2().getObject());

The call to entityManagerFactoryBean2() will create a new entity manager factory, and then the @Bean annotation will trigger the creation of another entity manager factory, with the same config. entityManagerFactoryBean2()的调用将创建一个新的实体管理器工厂,然后@Bean注释将触发创建另一个实体管理器工厂,具有相同的配置。

When you inject the entity manager factory with @Autowired in a bean, you are injecting the instance created with @Bean, and not the instance passed to the transaction manager. 当您在bean中注入带有@Autowired的实体管理器工厂时,您将注入使用@Bean创建的实例,而不是传递给事务管理器的实例。

One warning concerning the config: 关于配置的一个警告:

The config above allows to do transactions in two separate datasources, but it's not possible with this config to do transactions that span the two databases. 上面的配置允许在两个单独的数据源中进行事务处理,但是这个配置不可能执行跨两个数据库的事务。 For example: 例如:

@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;
    }
}

This code will only persist f14, because the only entity manager that has an ongoing transaction is em1 (due to @Transactional("transactionManager1") ). 此代码仅保留f14,因为具有正在进行的事务的唯一实体管理器是em1(由于@Transactional("transactionManager1") )。 The call to em2.persist() will be ignored (em2 can still do reads though). em2.persist()的调用将被忽略(虽然em2仍然可以读取)。

If you want to do transactions that include both databases you need a JTA transaction manager. 如果要执行包含两个数据库的事务,则需要JTA事务管理器。

An example of a working config: 工作配置的示例:

This an example of a configuration that fixes the above injection issues: 这是一个修复上述注入问题的配置示例:

@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;
    }
}

By splitting the config in several @Configuration classes and autowiring them, we ensure that it's always the same beans being used (singletons). 通过在几个@Configuration类中拆分配置并自动装配它们,我们确保它始终与所使用的bean相同(单例)。

Notice the @EnableTransactionManagement annotation, that enables @Transactional. 注意@EnableTransactionManagement注释,它启用了@Transactional。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 BufferedImage有两种类似的方法,一种有效,一种没有。 为什么? - Two similar methods with BufferedImage, one working, one not. Why? Java 类路径 - 一个 jar 可访问,其他不可访问。 为什么? - Java classpath - one jar accessible, other not. Why? 为什么此正则表达式似乎不起作用? - Why does this regex not seem to work? 为什么一个Swing按键有效,而另一个无效? - Why does one Swing keystroke work but not the other? 为什么一个代码工作而另一个代码不工作? - Why does one code work but not the other? 为什么我的arraylist的一次迭代工作,而另一次没有? - Why does one iteration of my arraylist work, while the other does not? 下面的代码返回给定数字是否为2的幂。 它是如何工作的? - The code below returns whether the given number is a power of two or not. How does it work? 为什么 autoReconnect=true 似乎不起作用? - Why does autoReconnect=true not seem to work? For 循环有效,但 For Each 无效。 为什么? - For loop works, but For Each does not. Why? 为什么并发散列映射在被两个线程访问时正常工作,一个使用 clear() ,另一个使用 putifAbsent() 方法? - Why does a concurrent hash map work properly when accessed by two thread, one using the clear() and other using the putifAbsent() methods?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM