Spring+ibatis 多数据源的配置和使用

1.配置多个数据源


    
        
        
        
        
        
        
        
        
        
        
        
        
        
        
    

    

       
        
        
        
        
        
        
        
        
        
        
        
        
        
        
    



2.扩展Spring的AbstractRoutingDataSource抽象类,实现动态数据源。  

AbstractRoutingDataSource中的抽象方法determineCurrentLookupKey是实现数据源的route的核心.这里

对该方法进行Override。


import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;  
public class DynamicDataSource extends AbstractRoutingDataSource {  
    @Override  
    protected Object determineCurrentLookupKey() {  
        return DBContextHolder.getCustomerType();  
    }  
}

上下文DbContextHolder为一线程安全的ThreadLocal,具体代码如下:

public class DBContextHolder {
    private static final ThreadLocal contextHolder = new ThreadLocal();  
    public static void setCustomerType(String customerType) {  
        contextHolder.set(customerType);  
    }  
    public static String getCustomerType() {  
        return contextHolder.get();  
    }  
    public static void clearCustomerType() {  
        contextHolder.remove();  
    }
}


3.配置动态数据源

将DynamicDataSourceBean加入到Spring的上下文xml配置文件中去,同时配置DynamicDataSource的targetDataSources(多数据源目标)属性的Map映射。

    
      
         
             
                 
                 
           
 
       
 
       
   




4.使用动态数据源   

例子中DynamicDataSource是继承与AbstractRoutingDataSource,而AbstractRoutingDataSource又是继承于org.springframework.jdbc.datasource.AbstractDataSource,AbstractDataSource实现了统一的DataSource接口,所以DynamicDataSource同样可以当一个DataSource使用。

在ORM框架ibatis中的使用配置示例:

      
        
            
                classpath:config/ibatis/ibatis-config.xml

            

        

           
            
        

        
    


 

5.事务管理

使用动态数据源的时候,可以看出和使用单数据源的时候相比,在使用配置上几乎没有差别,在进行性事务管理配置的时候也没有差别:

使用ibatis时的事务管理配置示例:

    
    
        
    


6.动态数据源的管理控制

如何选择控制每个业务中需要的具体数据源,可是使用手动控制:


public class DynamicDataSourceTest {
    public static void main(String[]args){
        DynamicDataSourceTest ds = new DynamicDataSourceTest();
        ds.loginUser();
    }
    
    public void loginUser(){
        String[] locationPath={"config/spring/spring-common.xml"
        ,"config/spring/spring-pool.xml"
        ,"config/spring/spring-securitycode.xml"};
        ApplicationContext context =new ClassPathXmlApplicationContext(locationPath);

        DemoService dao = (DemoService) context.getBean("demoService", DemoService.class);  
        DBContextHolder.setCustomerType(TargetDataSourceEnum.dataSource1);   
        HashMap mappar = new HashMap();
        mappar.put("dm", "dm1");
        mappar.put("mc", "mc1");
        DemoJsonPage demoJsonPage = new DemoJsonPage();
        
        System.out.println("-------------"+dao.queryNjb().size());        
    }
}

也可以采用AOP的控制方式:

public enum TargetDataSourceEnum {
    dataSource1,dataSource2
}

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 在方法上使用,用于指定使用哪个数据源
 *
 */
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TargetDataSource {
    TargetDataSourceEnum name();
}

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 切换数据源Advice
 * @author
 */
@Aspect
@Order(-1)// 保证该AOP在@Transactional之前执行
@Component
public class DynamicDataSourceAspect {

    private static final Logger logger = LoggerFactory.getLogger(DynamicDataSourceAspect.class);

    @Before("@annotation(ds)")
    public void changeDataSource(JoinPoint point, TargetDataSource ds) throws Throwable {
        String dsId = ds.name().name();
        logger.debug("Use DataSource : {} > {}", ds.name(), point.getSignature());
        DBContextHolder.setCustomerType(ds.name().name());
    }

    @After("@annotation(ds)")
    public void restoreDataSource(JoinPoint point, TargetDataSource ds) {
        logger.debug("Revert DataSource : {} > {}", ds.name(), point.getSignature());
        DBContextHolder.clearCustomerType();
    }

}


使用方法

    @TargetDataSource(name=TargetDataSourceEnum.dataSource1)
    @Override
    public List queryNjb(){
        return dbDao.query("demo.queryNjb");
    }





你可能感兴趣的:(oracle,spring,数据结构和算法)