В Spring используется неправильный менеджер транзакций - PullRequest
0 голосов
/ 08 апреля 2019

У меня есть два весенних менеджера транзакций.

  1. txManager1 - ChainedKafkaTransactionManager (KafkaTransactionManager, JpaTransactionManager), сконфигурированный с источником данных DB1
  2. txManager2 - JpaTransactionManager, сконфигурированный с DB2 sourceManager1011 *

    Проблема в том, что я выполняю некоторые операции с использованием txManager2, но каким-то образом txManager1 используется вместо txManager2, и данные передаются в DB1 вместо DB2.

    @Autowired
    @Qualifier("common-tx")
    private PlatformTransactionManager txManager2 ;
    
    @KafkaListener(topics = "${kafka.topic.name}", groupId = "group-1", containerFactory = "customKafkaListenerContainerFactory")
    public void topicListener(String message, Acknowledgment ack)
            throws InterruptedException, ClassNotFoundException, IOException {
    
    
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setName(domainEvent.getEventId());
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
    
        TransactionStatus commonStatus = txManager2 .getTransaction(def);
    
        someService.doSomething();
    
        txManager2 .commit(commonStatus);
    
    
        ack.acknowledge();
    }
    

    В doSomething() IЯ просто сохраняю сущность, после отладки обнаруживается, что при сохранении сущности через репозиторий данных Spring менеджер транзакций, определенный в invokeWithinTransaction() из org.springframework.transaction.interceptor.TransactionAspectSupport, неверен, т.е. вместо txManager2 выбран txManager1, это проблема конфигурации илия что-то упустил?

    Конфигурация txManager1:

        @Configuration
        @EnableTransactionManagement
        @PropertySource(value = {"classpath:application-${spring.profiles.active}.properties"})
        @Profile({"development","production","qa"})
        @EnableJpaRepositories(basePackages={"xxx.xxx.xxxx"},excludeFilters=@ComponentScan.Filter(type=FilterType.REGEX, pattern="xxx.xxx.xxxx.module2.*"))
        public class JPAConfig1 {
    
        @Value("${jndi.name}")
        private String jndiName;
    
        @Value("${hibernate.dialect}")
        private String hibernateDialect;
    
        @Value("${hibernate.show_sql}")
        private String showSql;
    
        @Value("${hibernate.format_sql}")
        private String formatSql;
    
        @Value("${hibernate.hbm2ddl.auto}")
        private String hiberanteUpdate;
    
        @Value("${javax.persistence.validation.mode}")
        private String hibernateValidation;
    
    
    
        @Bean
        @Primary
        public LocalContainerEntityManagerFactoryBean entityManagerFactory(MultiTenantConnectionProviderImpl tenantConnection, CurrentTenantIdentifierResolver currentTenantIdentifierResolver)
        {
            LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
            JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
            emf.setJpaVendorAdapter(vendorAdapter);
            emf.setJpaProperties(jpaProperties(tenantConnection, currentTenantIdentifierResolver));
            emf.setPackagesToScan(new String[] {"xxx.xxx.xxxx"});
    
            return emf;
        }
    
        private Properties jpaProperties(MultiTenantConnectionProviderImpl tenantConnection, CurrentTenantIdentifierResolver currentTenantIdentifierResolver) {
            Properties properties = new Properties();
            properties.setProperty("hibernate.dialect",hibernateDialect);        
            properties.setProperty("hibernate.show_sql",showSql);
            properties.setProperty("hibernate.format_sql",formatSql);
            properties.setProperty("hibernate.hbm2ddl.auto",hiberanteUpdate);
            properties.setProperty("javax.persistence.validation.mode",hibernateValidation);
    
            properties.put(Environment.MULTI_TENANT, MultiTenancyStrategy.DATABASE);
            properties.put(Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, currentTenantIdentifierResolver);
            properties.put(Environment.MULTI_TENANT_CONNECTION_PROVIDER, tenantConnection);
    
            return properties;
        }
    
        @Bean
        public CurrentTenantIdentifierResolver getCurrentTenantIdentifierResolver(TenantContext tenantContext) {
            return new CurrentTenantIdentifierResolverImpl(tenantContext);
        }
    
        @Bean(name="tenantConnection")
        public MultiTenantConnectionProviderImpl getMultiTenantConnectionProvider(TenantContext tenantContext) {
            return new MultiTenantConnectionProviderImpl(false,tenantContext);
        }
    
        @Bean
        @Primary
        public PlatformTransactionManager transactionManager(EntityManagerFactory factory,ProducerFactory producerFactory){
    
            JpaTransactionManager transactionManager = new JpaTransactionManager();
            transactionManager.setEntityManagerFactory(factory);
            KafkaTransactionManager tm = new KafkaTransactionManager(producerFactory);
    
            return new ChainedKafkaTransactionManager(tm,transactionManager);
        }
    
        @Bean
        public TenantContext getTenantContext() {
            return new TenantContextImpl();
        }
    }
    

    Конфигурация txManager2:

     @Configuration
     @EnableTransactionManagement
     @EnableJpaRepositories(basePackages="xxx.xxx.xxxx.module2",
     entityManagerFactoryRef="common-factory",transactionManagerRef="common-tx")
     @PropertySource(value = {"classpath:common-${spring.profiles.active}.properties"})
     @Profile({"development","production","qa"})
     public class JPAConfig2 {
    
    @Value("${common.jndi.name}")
    private String jndiName;
    
    @Value("${common.hibernate.dialect}")
    private String hibernateDialect;
    
    @Value("${common.hibernate.show_sql}")
    private String showSql;
    
    @Value("${common.hibernate.format_sql}")
    private String formatSql;
    
    @Value("${common.hibernate.hbm2ddl.auto}")
    private String hiberanteUpdate;
    
    @Value("${common.javax.persistence.validation.mode}")
    private String hibernateValidation;
    
    @Bean(name="common-factory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Qualifier("common-ds") DataSource dataSource) {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource);
        em.setPackagesToScan(new String[] {"xxx.xxx.xxxx.module2"});
    
        JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        em.setJpaProperties(jpaProperties());
        em.setPersistenceUnitName("common");
        return em;
    }
    
    @Bean("common-ds")
    public DataSource dataSource() throws NamingException {
        return (DataSource) new JndiTemplate().lookup(jndiName);
    }
    
    private Properties jpaProperties() {
        Properties properties = new Properties();
        properties.setProperty("hibernate.dialect",hibernateDialect);        
        properties.setProperty("hibernate.show_sql",showSql);
        properties.setProperty("hibernate.format_sql",formatSql);
        properties.setProperty("hibernate.hbm2ddl.auto",hiberanteUpdate);
        properties.setProperty("javax.persistence.validation.mode",hibernateValidation);
    
        return properties;
    }
    
    @Bean(name="common-tx")
    public PlatformTransactionManager transactionManager(@Qualifier("common-factory") EntityManagerFactory factory){
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(factory);
    
        return transactionManager;
    }
    
    
    
    }
    
...