Spring 多数据库事务的一致性(JTA 和 非JTA)

  1. 这里的项目是基于 Spring4.X + hibernate4.X架构的。最近的一个项目需要两个数据库,一个Oracle,一个是Sqlserver。业务中有一些需求需要跨库事务的一致,举个例子:合同签订保存到基于Oracle的ERP数据库,紧接着下发到Sqlserver的WMS数据库。
  2. 以前听说过JTA分布式事务,google到两种分布式框架:JOTM,atomikos。貌似JOTM简便点,就它了。
  3. 这种方式需要的jar包,首先在JOTM官网下面所有的jar包文件(文末提供下载),下图中选中的jar文件都是需要导入的
    Spring 多数据库事务的一致性(JTA 和 非JTA)_第1张图片
     

    首先配置DataSource和SessionFactory

 

	
		   
	          
	              
	              
	              
	          
	         
	      
	     
	
	
		   
	          
	              
	              
	              
	          
	         
	      
	      
	
	
		
		
			
				com.sy.domain
			
		
		
			
				
					org.hibernate.dialect.OracleDialect
				
				true
				true
				
			
		
	
	
	
		
		
			
				com.sy.domain
			
		
		
			
				
					org.hibernate.dialect.SQLServerDialect
				
				true
				true
				
			
		
	
	
	
		
	
	
	
		
	

  因为我们要操作两个数据库,所以配置两个datasource,两个sessionfactory。需要注意的是我们这里是JOTM和xapool实现的分布式事务。JOTM实现了TransactionManager的功能,xapool通过使用非XA数据库驱动实现了XA数据库驱动的效果,具体这个以后再写文章。这里连接池的配置按照上面的文档配置即可。

 

这里DAO层因为两个数据库所以配置了两个。在Service层可以选择一起注入或者单个注入。

 

下面配置事务

  
     
       
	 
	
		
			
			
			
			
			
			
			
			
			
			
		
	
	
	
        
        
    
       

  com.sy.utils.JotmFactoryBean需要手动实现,因为spring4.x不在提供JtaTransactionManager 的默认实现。

 

 

到这里JTA分布式事务的配置已经完成,下面我们看看Service层,和junit测试

@Service
public class CommonServiceImpl implements CommonService{
	
	/** serialVersionUID*/
	private static final long serialVersionUID = -5991777455696969065L;
	@Resource
	private CommonDao commonDao;
	@Resource
	private CommonDao commonDao2;
        //测试两个数据库的事务
	@Override
	public void saveTest() throws MyException {
		commonDao.update("update Dictionary set name=? where id=? ", new Value().add("货主类型").add(1l).getParams());
		commonDao2.update("delete Member where id>25");
                int i = 1/0; //这里异常,前面配置正确的话事务会回滚
	}

}

 

   因为这是一个公共的Service层,需要操作两个数据库,所以两个DAO一起注入。下面是Junit测试代码

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring/applicationContext-*.xml"})
public class TestSupport extends AbstractJUnit4SpringContextTests {

        @Autowired
	private CommonService commonService;
	@Test
	public void save() throws MyException{
		commonService.saveTest();
	}
	public CommonService getCommonService() {
		return commonService;
	}
	public void setCommonService(CommonService commonService) {
		this.commonService = commonService;
	}


}

  运行结果如我们所料,事务回滚,OK!

 

下面是直接配置的方式,这种方式是一个老同事那边看到的。当时惊呼不用jta也能实现跨库事务啊。跟普通的单数据库项目配置一样,只是DataSource,SessionFactory,transactionmanager等都是两个。下面是配置

	
		
		
		
		
		
		
	
	
		
		
		
		
		
		
	
	
		
		
			
				com.sy.domain
			
		
		
			
				
					org.hibernate.dialect.OracleDialect
				
				true
				true
				
			
		
	
	
	
		
		
			
				com.sy.domain
			
		
		
			
				
					org.hibernate.dialect.SQLServerDialect
				
				true
				true
				
			
		
	
	
	
		
	
	
	
		
	
     
        
    
    
    
        
    
	
	
		
			
			
			
			
			
			
			
			
			
			
		
	
	
	
		
			
			
			
			
			
			
			
			
			
			
		
	
	
	
	
        
        
    
    
    
        
        
    

  这里配置和普通单库配置基本一样,连接池也是自由选择。但是都是两个配置,spring4对多个事务配置也是支持的。测试代码和上面JTA配置的一样,不再给出。

  

 

 

 

你可能感兴趣的:(Spring)