现在的位置: 首页 > 综合 > 正文

mybatis+spring中的数据库分库

2017年03月24日 ⁄ 综合 ⁄ 共 5525字 ⁄ 字号 评论关闭

今天接触了下mybatis的数据库分库问题,于是就查了下各种资料,说说今天的收获,当然可能别人也写过了,但还是把自己的感受及经历写下,以后方便回顾。知识这个东西很多时候都是一点点积累的结果。可能多记录些并没有坏处。手懒的结果很多人也都吃亏过相信。

关于数据库的分库曾经听过些,但自己却没接触过,于是google下,照着代码走了一遍,代码如下

application-context.xml

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="minPoolSize" value="${jdbc.min}" />
<property name="maxPoolSize" value="${jdbc.max}" />
<property name="maxIdleTime" value="${jdbc.maxIdleTime}" />
<property name="idleConnectionTestPeriod" value="${jdbc.idleConnectionTestPeriod}" />
</bean>

<!-- mybatis 配置 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSources" />
<property name="configLocation" value="classpath:config/mybatis-config.xml" />
<!-- 当Mapper文件跟对应的Mapper接口处于同一位置的时候可以不用指定该属性的值:  -->
<!-- <property name="mapperLocations" value="classpath:org/user/persistence/*.xml" /> -->
</bean>

<!-- Mapper接口扫描 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  
        <property name="basePackage" value="org.*.persistence;" />
        <property name="annotationClass" value="org.springframework.stereotype.Repository" />  
    </bean>
    
<!-- add by xiao -->
<bean id="dataSource2" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}" />
<property name="jdbcUrl" value="${jdbc.url2}" />
<property name="user" value="${jdbc.username2}" />
<property name="password" value="${jdbc.password2}" />
<property name="minPoolSize" value="${jdbc.min2}" />
<property name="maxPoolSize" value="${jdbc.max2}" />
<property name="maxIdleTime" value="${jdbc.maxIdleTime2}" />
<property name="idleConnectionTestPeriod" value="${jdbc.idleConnectionTestPeriod2}" />
</bean>

    <bean id="dataSources" class="org.mutidatasource.test.CustomerRoutingDataSource">
  <property name="targetDataSources">
     <map key-type="org.mutidatasource.test.CustomerType">
        <entry key="FIRST" value-ref="dataSource"/>
        <entry key="SECOND" value-ref="dataSource2"/>
     </map>
  </property>
  <property name="defaultTargetDataSource" ref="dataSource2"/>
</bean>
<bean id="choose" class="org.mutidatasource.test.ChooseDataSource"/>
<aop:config>
<aop:aspect ref="choose">
<aop:pointcut expression="execution(* org.mutidatasource.test.TestMutiDataSource.printRest(..))" id="point"/>
<aop:before method="chooseDataSource" pointcut-ref="point"/>
</aop:aspect>
</aop:config>

java代码部分如下:

public class CustomerContextHolder {

private static final ThreadLocal<CustomerType> contextHolder = 
            new ThreadLocal<CustomerType>();

   public static void setCustomerType(CustomerType customerType) {
      Assert.notNull(customerType, "customerType cannot be null");
      contextHolder.set(customerType);
   }

   public static CustomerType getCustomerType() {
      return (CustomerType) contextHolder.get();
   }

   public static void clearCustomerType() {
      contextHolder.remove();
   }
}

public class CustomerRoutingDataSource extends AbstractRoutingDataSource{

@Override
protected Object determineCurrentLookupKey() {
return CustomerContextHolder.getCustomerType();
}

}

public class CustomerContextHolder {

private static final ThreadLocal<CustomerType> contextHolder = 
            new ThreadLocal<CustomerType>();

   public static void setCustomerType(CustomerType customerType) {
      Assert.notNull(customerType, "customerType cannot be null");
      contextHolder.set(customerType);
   }

   public static CustomerType getCustomerType() {
      return (CustomerType) contextHolder.get();
   }

   public static void clearCustomerType() {
      contextHolder.remove();
   }
}


public enum CustomerType {
FIRST,SECOND
}

测试类如下:

@Service(value="muti")
public class TestMutiDataSource implements TestMutiDataSourceIntf{

@Resource
MutiDataSourceMapper mutiDataSourceMapper;

public void printRest(int agencyId){
CustomerContextHolder.setCustomerType(CustomerType.FIRST);
List<String> list = mutiDataSourceMapper.selectMutiNames();
for(String tmp:list){
System.err.println(tmp);
}
CustomerContextHolder.setCustomerType(CustomerType.SECOND);
List<String> lists = mutiDataSourceMapper.selectMutiNames();
for(String tmp:lists){
System.err.println(tmp);
}
}
}

运行即可。

其中在xml中有一段aop的配置,我是打算配置成自动路由的方式来选数据源

public class ChooseDataSource {


public void chooseDataSource(JoinPoint joinPoint){
LocalVariableTableParameterNameDiscoverer parameterNameDiscovere =  
       new LocalVariableTableParameterNameDiscoverer();


Method method = getMethod(joinPoint);
String[] names = parameterNameDiscovere.getParameterNames(method);
System.out.println("names:"+names[0]);

System.err.println("Method Name :" + joinPoint.getSignature().toShortString() + "| Args => " + Arrays.asList(joinPoint.getArgs()));


}
  private Method getMethod(JoinPoint joinPoint) {  
       //String methodLongName = joinPoint.getSignature().toLongString();  
   String methodLongName = joinPoint.getSignature().toShortString();  
   String[] tmp  = methodLongName.split("\\.");
   methodLongName = tmp[tmp.length-1];
       Method[] methods = joinPoint.getTarget().getClass().getMethods();  
       Method method = null;  
       for(int i=0, len=methods.length; i<len; i++) {  
           if(methods[i].toString().contains(methodLongName)) {  
               method = methods[i];  
               break;  
           }  
       }  
       return method;  
   }  
}

这边在获取参数名称的时候出现了些问题,我本来打算用

MethodSignature signature = (MethodSignature)joinPoint.getSignature();
String[] parameterNames = signature.getParameterNames();
System.out.println(parameterNames);
这样的方法来获取参数名称,但得到的却是null,查了很多资料,说是要aspectJ专用的编译器可以,或者是在java编译的时候用

javac -g这样的命令可以使编译的结果之中有方法参数的名字,否则是得不到参数的名称的。上面还有个方法得到了参数的名称,就

是用LocalVariableTableParameterNameDiscoverer 这个类来获取,据说它是在java编译的时候生成的,具体我也不大了解。以后再补充

今天就到这里吧

抱歉!评论已关闭.