【问题标题】:Spring is using the same SessionFactory and ignoring configured transaction managersSpring 使用相同的 SessionFactory 并忽略配置的事务管理器
【发布时间】:2016-03-21 21:53:21
【问题描述】:

我有 2 个不同的数据库。我配置每一个,然后将 TransactionManager 与各自的 @Transactional 服务相关联。问题是,每当我尝试保存它时,它都会尝试仅使用其中一个事务管理器。它完全忽略了其他事务管理器。以下是配置: 另请注意,这 2 个保存操作几乎同时在 2 个单独的 Spring 集成异步进程中运行,因为使用接收者列表将请求发送到 save(Product) 和 save(User)。这可能是问题的原因吗?

   @Configuration
   @EnableTransactionManagement
   @ComponentScan("com.edx.db2")
   @PropertySource(value=....)
   public class DB2Config {
   @Autowired
   private Environment env;



    @Bean 
    public UserDao UserDao(){
        UserDao UserDao=new UserService();
        return UserDao;
    }

    @Bean
    @Qualifier(value="db2SessionFactory")
    public SessionFactory sessionFactory(){
        return db2DBSessionfactory().getObject();
    }

    @Bean
    public LocalSessionFactoryBean db2DBSessionfactory() {
        LocalSessionFactoryBean sessionFactoryBean = 
          new LocalSessionFactoryBean();
        sessionFactoryBean.setDataSource(db2DataSource());
        sessionFactoryBean.setPackagesToScan("com.edx");
        sessionFactoryBean.
        setHibernateProperties(hibernateProperties());
        return sessionFactoryBean;
    }

    @Bean
    public Properties hibernateProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.dialeCT...
        properties.put("hibernate.show_sql", true);
        properties.put("hibernate.connection.d
        properties.put("hibernate.connection.url
        properties.put("hibernate.connection.username", e
        properties.put("hibernate.connection.passwor
        return properties;
    }


    @Bean(destroyMethod="close")
    public DataSource db2DataSource() {
        try {
            DriverManage..
            return dataSource;
        } catch (Exception e) {
            LOG.error("Unable to create connection pool",e);
            return null;
        }

    }



    @Bean
    @Qualifier(value="db2TransactionManager")
    public PlatformTransactionManager db2TransactionManager() {
        HibernateTransactionManager htm=new 
        HibernateTransactionManager(db2DBSessionfactory().getObject());
        htm.setDataSource(db2DataSource());
        return htm;
    }

}

@Configuration
@EnableTransactionManagement
@ComponentScan("com.edx.oracle")
@PropertySource(value={"classpath:...)
public class ORAConfig {
@Autowired
private Environment env;

    @Bean
    public ProductDao productDao(){
        return new ProductService();
    }


    @Bean
    public SessionFactory oracleSessionFactory(){
        return oracleDBSessionfactory().getObject();
    }

    @Bean
    public LocalSessionFactoryBean oracleDBSessionfactory() {
        LocalSessionFactoryBean sessionFactoryBean = 
            new LocalSessionFactoryBean();
        sessionFactoryBean.setDataSource(oracleDataSource());
        sessionFactoryBean.setPackagesToScan("com.edx.oracle");
        sessionFactoryBean.setHibernateProperties(hibernateProperties());
        return sessionFactoryBean;
    }


    @Bean
    @Qualifier(value="oracleTransactionManager")
    public PlatformTransactionManager oracleTransactionManager() {
        HibernateTransactionManager htm=new 
        HibernateTransactionManager
          (oracleDBSessionfactory().getObject());
        htm.setDataSource(oracleDataSource());
        return htm;
    }

    @Bean
    public Properties hibernateProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.dialect"
        ,env.getProperty("hibernate.dialect"));
        properties.put("hibernate.show_sql", true);
        properties.put("hibernate.connection.driver_class",
        env.getProperty("jdbc.driverClassName"));
        properties.put("hibernate.connection.url", 
        env.getProperty("jdbc.url"));
        properties.put("hibernate.connection.username",
        env.getProperty("jdbc.username"));
        properties.put("hibernate.connection.password",
        env.getProperty("jdbc.password"));
        return properties;
    }



    @Bean
    public DataSource oracleDataSource() {
        try {
            DriverManagerDataSource dm=new DriverManagerDataSource();
            dm.setDriverClassName(env.getProperty("jdbc.driverClassName"));
            dm.setUsername(env.getProperty("jdbc.username"));
            dm.setPassword(env.getProperty("jdbc.password"));
            dm.setUrl(env.getProperty("jdbc.url"));
            return dm;
        } catch (Exception e) {
            e.printStackTrace();
            LOG.error("Unable to create connection pool",e);
            return null;
        }

    }

}

  @Repository
  @Import(ORAConfig.class)
  @Transactional("oracleTransactionManager")
   public class UserService implements UserDao{

  @Autowired
  private SessionFactory oracleSessionFactory;
  private Logger LOG=LoggerFactory.getLogger(UserService.class);
  private PayloadIndexExtractor payloadIndexExtractor;
  public UserService() {
  }

  public UserService() {
  }


  public void save(final UserInfo user) {
   try{
     //Changed from getCurrentSession()         
     Session session=oracleSessionFactory.openSession();
      session.save(user) ;


   }catch(Exception e){
       e.printStackTrace();
       LOG.error("Failed to save user",e);
   }
}

}

 @Repository
 @Import(DB2Config.class)
 @Transactional("db2TransactionManager")
 public class ProductService implements ProductDao {

 public ProducrService() {

 }
    @Autowired
    private SessionFactory db2SessionFactory;



    public void saveProduct(Product) {
        sessionFactory.getCurrentSession().save(product);
    }

知道我的配置有什么问题吗?请帮忙

【问题讨论】:

  • ORAConfig类中,能不能在oracleSessionFactory()方法上面加上@Qualifier(value="oracleSessionFactory")试试。
  • 我试过没有解决问题

标签: spring hibernate


【解决方案1】:

您需要一个 ChainedTransactionManager 作为名称为 transactionManager 的 bean。它必须包含其他两个 HibernateTransactionManager,并且会注意两者都使用 @Transactional 启动和提交事务

代码应该是这样的

@Bean(name = "transactionManager")
public PlatformTransactionManager transactionManager(PlatformTransactionManager oracleTransactionManager, PlatformTransactionManager db2TransactionManager)
        throws Exception {
    return new ChainedTransactionManager(oracleTransactionManager,
           db2TransactionManager);
}

【讨论】:

  • 两个事务正在交错。原因是两个事务在两个完全不相关的独立异步进程中同时运行。所以当 save(Product) 运行时, save(User) 也在运行并加入 save(Product) 事务。由于它们是 2 个不同的数据库并且正在使用相同的事务管理器,因此它失败了。
  • 我没有提到答案,但是您必须从 @Transactional 注释中删除值。没有加入事务的概念,所以它们是同时开始的。
猜你喜欢
  • 2014-02-22
  • 2017-07-30
  • 2011-07-05
  • 2010-10-18
  • 1970-01-01
  • 2015-04-24
  • 2013-12-01
  • 1970-01-01
  • 2014-05-22
相关资源
最近更新 更多