spring+myBatisi实现多数据源动态切换
来源:互联网 发布:湖南教师网络研修平台 编辑:程序博客网 时间:2024/06/16 04:22
目前网上实现动态数据源的文章很多,基本都是根据spring的AOP实现的,本来以为简单,复制粘贴即可,结果遇到不少问题,一是遇到AOP与事务之间执行顺序的问题,二是service实现类遇到注解无法获取的问题,前一个问题使用order解决了,后一个问题则是放到service接口类中就可以获取。具体如下:
1、自定义注解:
123456789101112131415
import java.lang.annotation.ElementType;import java.lang.annotation.Target;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;/** * RUNTIME * 编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取。 * @author yangGuang * */@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface DataSource {String value();}
2、基于spring的aop实现多数据源(读和写两个数据源):
1)写一个ChooseDataSource: 类继承AbstractRoutingDataSource,并实现determineCurrentLookupKey方法:
12345678910
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;public class ChooseDataSource extends AbstractRoutingDataSource {@Overrideprotected Object determineCurrentLookupKey() {return HandleDataSource.getDataSource();}}
2)利用ThreadLocal解决线程安全问题:
12345678910
public class HandleDataSource {public static final ThreadLocal<String> holder = new ThreadLocal<String>();public static void putDataSource(String datasource) {holder.set(datasource);}public static String getDataSource() {return holder.get();} }
3)定义一个数据源切面类,通过aop访问,获取方法上的自定义注解,然后根据注解内容尽情判断,动态设置数据源:
123456789101112131415161718192021222324252627282930313233343536
import java.lang.reflect.Method;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;import org.aspectj.lang.reflect.MethodSignature;import org.springframework.stereotype.Component;//@Aspect//@Componentpublic class DataSourceAspect {//@Pointcut("execution(* com.apc.cms.service.*.*(..))") public void pointCut(){}; // @Before(value = "pointCut()") public void before(JoinPoint point){Object target = point.getTarget();System.out.println(target.toString());String method = point.getSignature().getName();System.out.println(method);Class<?>[] classz = target.getClass().getInterfaces();Class<?>[] parameterTypes = ((MethodSignature) point.getSignature()).getMethod().getParameterTypes();try {Method m = classz[0].getMethod(method, parameterTypes);System.out.println(m.getName());if (m != null && m.isAnnotationPresent(DataSource.class)) {DataSource data = m.getAnnotation(DataSource.class);HandleDataSource.putDataSource(data.value());}} catch (Exception e) {e.printStackTrace();}}}
4)配置applicationContext.xml:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
<!-- 主库数据源 --> <bean id="writeDataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close"><property name="driverClass" value="com.mysql.jdbc.Driver"/><property name="jdbcUrl" value="jdbc:mysql://172.22.14.6:3306/cpp?autoReconnect=true"/><property name="username" value="root"/><property name="password" value="root"/><property name="partitionCount" value="4"/><property name="releaseHelperThreads" value="3"/><property name="acquireIncrement" value="2"/><property name="maxConnectionsPerPartition" value="40"/><property name="minConnectionsPerPartition" value="20"/><property name="idleMaxAgeInSeconds" value="60"/><property name="idleConnectionTestPeriodInSeconds" value="60"/><property name="poolAvailabilityThreshold" value="5"/></bean><!-- 从库数据源 --><bean id="readDataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close"><property name="driverClass" value="com.mysql.jdbc.Driver"/><property name="jdbcUrl" value="jdbc:mysql://172.22.14.7:3306/cpp?autoReconnect=true"/><property name="username" value="root"/><property name="password" value="root"/><property name="partitionCount" value="4"/><property name="releaseHelperThreads" value="3"/><property name="acquireIncrement" value="2"/><property name="maxConnectionsPerPartition" value="40"/><property name="minConnectionsPerPartition" value="20"/><property name="idleMaxAgeInSeconds" value="60"/><property name="idleConnectionTestPeriodInSeconds" value="60"/><property name="poolAvailabilityThreshold" value="5"/></bean><!-- transaction manager, 事务管理 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean><!-- 注解自动载入 --><context:annotation-config /><!--enale component scanning (beware that this does not enable mapper scanning!)--><context:component-scan base-package="com.apc.cms.persistence.rdbms" /><context:component-scan base-package="com.apc.cms.service"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Component" /> </context:component-scan> <context:component-scan base-package="com.apc.cms.auth" /><!-- enable transaction demarcation with annotations --><tx:annotation-driven /><!-- define the SqlSessionFactory --><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource" /><property name="typeAliasesPackage" value="com.apc.cms.model.domain" /></bean><!-- scan for mappers and let them be autowired --><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.apc.cms.persistence" /><property name="sqlSessionFactory" ref="sqlSessionFactory" /></bean><bean id="dataSource" class="com.apc.cms.utils.ChooseDataSource"><property name="targetDataSources"> <map key-type="java.lang.String"> <!-- write --> <entry key="write" value-ref="writeDataSource"/> <!-- read --> <entry key="read" value-ref="readDataSource"/> </map> </property> <property name="defaultTargetDataSource" ref="writeDataSource"/> </bean> <!-- 激活自动代理功能 --><aop:aspectj-autoproxy proxy-target-class="true"/><!-- 配置数据库注解aop --><bean id="dataSourceAspect" class="com.apc.cms.utils.DataSourceAspect" /><aop:config><aop:aspect id="c" ref="dataSourceAspect"><aop:pointcut id="tx" expression="execution(* com.apc.cms.service..*.*(..))"/><aop:before pointcut-ref="tx" method="before"/></aop:aspect></aop:config><!-- 配置数据库注解aop -->
3、测试,如果是在service中实现,需要放到接口类中,放到实现类中无法获取注解。
详情可见:http://www.iteye.com/problems/58681
public interface TestService {@DataSource("write")
Document update(User user) throws Exception;
}@DataSource("read") Document getDocById(long id) throws Exception;
阅读全文
0 0
- spring+myBatisi实现多数据源动态切换
- Spring实现多数据源动态切换
- Spring多数据源的动态切换
- Spring动态切换多数据源解决方案
- Spring多数据源的动态切换
- Spring动态切换多数据源解决方案
- Spring > 动态切换多数据源
- Spring动态切换多数据源解决方案
- Spring 多数据源动态切换
- spring框架---动态切换多数据源
- Spring动态切换多数据源
- spring boot 多数据源动态切换
- Spring动态切换多数据源解决方案
- Spring动态切换多数据源
- Spring动态切换多数据源解决方案
- Spring动态切换多数据源解决方案
- hibernate4+spring实现多数据源切换
- 使用spring 实现真正多数据源的动态加载及动态切换
- 继续const用法
- Latex 参考文献上标
- Trafodion Troubleshooting
- Java:实现简单的连接池
- struts2.xml配置详解
- spring+myBatisi实现多数据源动态切换
- layer-------弹出层参数介绍
- 再谈java的内存泄露
- Hive SQL执行计划深度解析
- Android广播机制,BroadcastReceiver
- SwipeRefreshLayout 嵌套 ListView 滑动问题
- c中的const与c++中的const
- startManagedWebLogic <BEA-000365> <Server state changed to RUNNING.>
- latex中如何将表格的Table1改为表1