applicationContext.xml
[html] view plain copy
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
- xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
- ">
- <description>Spring公共配置 </description>
- <!-- 使用annotation 自动注册bean, 并保证@Required、@Autowired的属性被注入 -->
- <context:component-scan base-package="com.test">
- </context:component-scan>
- <aop:aspectj-autoproxy proxy-target-class="true" />
- <bean
- class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
- <property name="locations">
- <value>classpath:app.properties</value>
- </property>
- </bean>
- <bean id="transactionManager"
- class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dynamicDataSource" />
- </bean>
- <!-- 使用annotation定义事务 -->
- <tx:annotation-driven transaction-manager="transactionManager"
- proxy-target-class="true" />
- <!-- MyBatis配置 自动扫描entity目录, 省掉Configuration.xml里的手工配置 -->
- <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
- <property name="typeAliasesPackage" value="com.test.model" />
- <property name="mapperLocations" value="classpath*:/mybatis/*Mapper.xml" />
- <property name="dataSource">
- <ref bean="dynamicDataSource" />
- </property>
- </bean>
- <!-- 扫描basePackage下所有以@MyBatisRepository标识的 接口 -->
- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
- <property name="basePackage" value="com.test.dao.mybatis" />
- <!-- <property name="annotationClass" value="jarlun.framework.core.base.mybatis.MyBatisRepository"
- /> -->
- </bean>
- <bean id="dynamicDataSource" class="com.test.holder.DynamicDataSource">
- <!-- 通过key-value的形式来关联数据源 -->
- <property name="targetDataSources">
- <map key-type ="java.lang.String">
- <entry value-ref="master" key="master"></entry>
- <entry value-ref="slave" key="slave"></entry>
- </map>
- </property>
- <property name="defaultTargetDataSource" ref="master" />
- </bean>
- <!-- JSR303 Validator定义 -->
- <!-- 以下 validator ConversionService 在使用 mvc:annotation-driven 会 自动注册 -->
- <!-- 建立视图内拦截器来解决JPA中访问延迟加载属性时产生的无会话异常 LazyInitializationException: could
- not initialize proxy no session -->
- <!-- 此拦截器会注入到servlet配置中的DefaultAnnotationHandlerMapping中 -->
- <bean id="master" class="org.apache.commons.dbcp.BasicDataSource"
- destroy-method="close">
- <!-- Connection Info -->
- <property name="driverClassName" value="${master.jdbc.driver}" />
- <property name="url" value="${master.jdbc.url}" />
- <property name="username" value="${master.jdbc.username}" />
- <property name="password" value="${master.jdbc.password}" />
- <!-- Connection Pooling Info -->
- <property name="maxActive" value="${master.jdbc.pool.maxActive}" />
- <property name="maxIdle" value="${master.jdbc.pool.maxIdle}" />
- <property name="initialSize" value="${master.jdbc.pool.initialSize}" />
- <property name="defaultAutoCommit" value="false" />
- <!-- 连接Idle一个小时后超时 -->
- <property name="timeBetweenEvictionRunsMillis" value="3600000" />
- <property name="minEvictableIdleTimeMillis" value="3600000" />
- <property name="testWhileIdle" value="true" />
- <property name="testOnBorrow" value="true" />
- <property name="testOnReturn" value="false" />
- <property name="validationQuery" value="SELECT 1" />
- <property name="logAbandoned" value="false" />
- <property name="removeAbandoned" value="true" />
- <property name="removeAbandonedTimeout" value="60" />
- </bean>
- <bean id="slave" class="org.apache.commons.dbcp.BasicDataSource"
- destroy-method="close">
- <!-- Connection Info -->
- <property name="driverClassName" value="${slave.jdbc.driver}" />
- <property name="url" value="${slave.jdbc.url}" />
- <property name="username" value="${slave.jdbc.username}" />
- <property name="password" value="${slave.jdbc.password}" />
- <!-- Connection Pooling Info -->
- <property name="maxActive" value="${slave.jdbc.pool.maxActive}" />
- <property name="maxIdle" value="${slave.jdbc.pool.maxIdle}" />
- <property name="initialSize" value="${slave.jdbc.pool.initialSize}" />
- <property name="defaultAutoCommit" value="false" />
- <!-- 连接Idle一个小时后超时 -->
- <property name="timeBetweenEvictionRunsMillis" value="3600000" />
- <property name="minEvictableIdleTimeMillis" value="3600000" />
- <property name="testWhileIdle" value="true" />
- <property name="testOnBorrow" value="true" />
- <property name="testOnReturn" value="false" />
- <property name="validationQuery" value="SELECT 1" />
- <property name="logAbandoned" value="false" />
- <property name="removeAbandoned" value="true" />
- <property name="removeAbandonedTimeout" value="60" />
- </bean>
- </beans>
app.properties
[html] view plain copy
- master.jdbc.driver=com.mysql.jdbc.Driver
- master.jdbc.url=jdbc:mysql://120.25.155.55:3306/test
- master.jdbc.username=test
- master.jdbc.password=!QAZxsw2
- master.jdbc.pool.maxActive=60
- master.jdbc.pool.maxIdle=20
- master.jdbc.pool.initialSize=10
- slave.jdbc.driver=com.mysql.jdbc.Driver
- slave.jdbc.url=jdbc:mysql://localhost:3306/test?useUnicode=true
- slave.jdbc.username=root
- slave.jdbc.password=
- slave.jdbc.pool.maxActive=60
- slave.jdbc.pool.maxIdle=20
- slave.jdbc.pool.initialSize=10
DynamicDataSource.java
[java] view plain copy
- package com.test.holder;
- import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
- public class DynamicDataSource extends AbstractRoutingDataSource{
- @Override
- protected Object determineCurrentLookupKey() {
- return DBContextHolder.getDBType();
- }
- }
DBContextHolder.java
[java] view plain copy
- package com.test.holder;
- public class DBContextHolder {
- private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
- public static void setDBType(String dbType) {
- contextHolder.set(dbType);
- }
- public static String getDBType() {
- return contextHolder.get();
- }
- public static void clearDBType() {
- contextHolder.remove();
- }
- }
DataSource.java
[java] view plain copy
- package com.test.holder;
- 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;
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.METHOD)
- @Documented
- public @interface DataSource {
- Source value() default Source.master;
- }
Source.java
[java] view plain copy
- package com.test.holder;
- public enum Source {
- /* 主库 */master, /* 从库 */slave
- }
UserMapper.java
[java] view plain copy
- package com.test.dao.mybatis;
- import org.apache.ibatis.annotations.Param;
- import com.test.model.UserModel;
- public interface UserMapper {
- UserModel findByUserId(@Param("userId")Long userId);
- }
UserModel.java
[java] view plain copy
- package com.test.model;
- public class UserModel {
- private long id;
- private String nickname;
- public long getId() {
- return id;
- }
- public void setId(long id) {
- this.id = id;
- }
- public String getNickname() {
- return nickname;
- }
- public void setNickname(String nickname) {
- this.nickname = nickname;
- }
- }
UserMapper.xml
[html] view plain copy
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.test.dao.mybatis.UserMapper">
- <resultMap id="userModel" type="com.test.model.UserModel" >
- <result property="id" column="id" />
- <result property="nickname" column="nickname" />
- </resultMap>
- <select id="findByUserId" resultMap="userModel" >
- select id , nickname from db_user where id=#{userId}
- </select>
- </mapper>
UserService.java
[java] view plain copy
- package com.test.service;
- import com.test.model.UserModel;
- public interface UserService {
- UserModel findByMasterUserId(long userId);
- UserModel findBySlaveUserId(long userId);
- }
UserServiceImpl.java
[java] view plain copy
- package com.test.service.impl;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
- import com.test.dao.mybatis.UserMapper;
- import com.test.holder.DataSource;
- import com.test.holder.Source;
- import com.test.model.UserModel;
- import com.test.service.UserService;
- @Service("userServiceImpl")
- public class UserServiceImpl implements UserService{
- @Autowired
- private UserMapper userMapper;
- @Transactional(rollbackFor={Exception.class})
- @DataSource(value=Source.master)
- public UserModel findByMasterUserId(long userId){
- return this.userMapper.findByUserId(userId);
- }
- @Transactional(rollbackFor={Exception.class})
- @DataSource(value=Source.slave)
- public UserModel findBySlaveUserId(long userId){
- return this.userMapper.findByUserId(userId);
- }
- }
aop拦截
DataSourceContextAop.Java
[java] view plain copy
- package com.test.aop;
- import java.lang.reflect.Method;
- import org.aspectj.lang.JoinPoint;
- import org.aspectj.lang.ProceedingJoinPoint;
- import org.aspectj.lang.annotation.Around;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.reflect.MethodSignature;
- import org.springframework.core.annotation.Order;
- import org.springframework.stereotype.Component;
- import com.test.holder.DBContextHolder;
- import com.test.holder.DataSource;
- @Aspect
- @Order(value=1)
- @Component
- public class DataSourceContextAop {
- @Around("execution(@com.test.holder.DataSource * com.test.service.impl.*.*(..))")
- public Object setDynamicDataSource(ProceedingJoinPoint pjp) throws Throwable {
- Method method = this.getMethod(pjp);
- DataSource dataSource = method.getAnnotation(DataSource.class);
- if (dataSource != null) {
- DBContextHolder.setDBType(dataSource.value().name());
- }
- return pjp.proceed();
- }
- public Method getMethod(JoinPoint pjp) {
- Method method = null;
- MethodSignature signature = (MethodSignature) pjp.getSignature();
- method = signature.getMethod();
- return method;
- }
- }
最后测试
Test.java
[java] view plain copy
- package test;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- import com.test.service.UserService;
- public class Test {
- public static void main(String[] args) {
- ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
- UserService userService = (UserService) ac.getBean("userServiceImpl");
- System.out.println(userService.findByMasterUserId(1000001).getNickname());
- System.out.println(userService.findBySlaveUserId(1000001).getNickname());
- }
- }
谢谢
而外加个hibernate和mybatis混用的配置
[html] view plain copy
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
- xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
- ">
- <description>Spring公共配置 </description>
- <!-- 使用annotation 自动注册bean, 并保证@Required、@Autowired的属性被注入 -->
- <context:component-scan base-package="com.test">
- </context:component-scan>
- <aop:aspectj-autoproxy proxy-target-class="true" />
- <bean
- class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
- <property name="locations">
- <value>classpath:app.properties</value>
- </property>
- </bean>
- <bean id="transactionManager"
- class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dynamicDataSource" />
- </bean>
- <!-- Jpa Entity Manager 配置 -->
- <bean id="entityManagerFactory"
- class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
- <property name="dataSource" ref="dynamicDataSource" />
- <property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" />
- <property name="packagesToScan" value="com.test.entity" />
- <property name="jpaProperties">
- <props>
- <!-- <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory
- </prop>
- <prop key="net.sf.ehcache.configurationResourceName">ehcache/ehcache-hibernate.xml</prop> -->
- <!-- 命名规则 My_NAME->MyName -->
- <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
- <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
- </props>
- </property>
- </bean>
- <bean id="hibernateJpaVendorAdapter"
- class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
- <property name="databasePlatform">
- <bean factory-method="getDialect"
- class="org.springside.modules.persistence.Hibernates">
- <constructor-arg ref="dynamicDataSource" />
- </bean>
- </property>
- </bean>
- <!-- 使用annotation定义事务 -->
- <tx:annotation-driven transaction-manager="transactionManager"
- proxy-target-class="true" />
- <!-- MyBatis配置 自动扫描entity目录, 省掉Configuration.xml里的手工配置 -->
- <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
- <property name="typeAliasesPackage" value="com.test.model" />
- <property name="mapperLocations" value="classpath*:/mybatis/*Mapper.xml" />
- <property name="dataSource">
- <ref bean="dynamicDataSource" />
- </property>
- </bean>
- <!-- 扫描basePackage下所有以@MyBatisRepository标识的 接口 -->
- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
- <property name="basePackage" value="com.test.dao.mybatis" />
- <!-- <property name="annotationClass" value="jarlun.framework.core.base.mybatis.MyBatisRepository"
- /> -->
- </bean>
- <bean id="dynamicDataSource" class="com.test.holder.DynamicDataSource">
- <!-- 通过key-value的形式来关联数据源 -->
- <property name="targetDataSources">
- <map key-type ="java.lang.String">
- <entry value-ref="master" key="master"></entry>
- <entry value-ref="slave" key="slave"></entry>
- </map>
- </property>
- <property name="defaultTargetDataSource" ref="master" />
- </bean>
- <!-- JSR303 Validator定义 -->
- <!-- 以下 validator ConversionService 在使用 mvc:annotation-driven 会 自动注册 -->
- <!-- 建立视图内拦截器来解决JPA中访问延迟加载属性时产生的无会话异常 LazyInitializationException: could
- not initialize proxy no session -->
- <!-- 此拦截器会注入到servlet配置中的DefaultAnnotationHandlerMapping中 -->
- <bean id="master" class="org.apache.commons.dbcp.BasicDataSource"
- destroy-method="close">
- <!-- Connection Info -->
- <property name="driverClassName" value="${master.jdbc.driver}" />
- <property name="url" value="${master.jdbc.url}" />
- <property name="username" value="${master.jdbc.username}" />
- <property name="password" value="${master.jdbc.password}" />
- <!-- Connection Pooling Info -->
- <property name="maxActive" value="${master.jdbc.pool.maxActive}" />
- <property name="maxIdle" value="${master.jdbc.pool.maxIdle}" />
- <property name="initialSize" value="${master.jdbc.pool.initialSize}" />
- <property name="defaultAutoCommit" value="false" />
- <!-- 连接Idle一个小时后超时 -->
- <property name="timeBetweenEvictionRunsMillis" value="3600000" />
- <property name="minEvictableIdleTimeMillis" value="3600000" />
- <property name="testWhileIdle" value="true" />
- <property name="testOnBorrow" value="true" />
- <property name="testOnReturn" value="false" />
- <property name="validationQuery" value="SELECT 1" />
- <property name="logAbandoned" value="false" />
- <property name="removeAbandoned" value="true" />
- <property name="removeAbandonedTimeout" value="60" />
- </bean>
- <bean id="slave" class="org.apache.commons.dbcp.BasicDataSource"
- destroy-method="close">
- <!-- Connection Info -->
- <property name="driverClassName" value="${slave.jdbc.driver}" />
- <property name="url" value="${slave.jdbc.url}" />
- <property name="username" value="${slave.jdbc.username}" />
- <property name="password" value="${slave.jdbc.password}" />
- <!-- Connection Pooling Info -->
- <property name="maxActive" value="${slave.jdbc.pool.maxActive}" />
- <property name="maxIdle" value="${slave.jdbc.pool.maxIdle}" />
- <property name="initialSize" value="${slave.jdbc.pool.initialSize}" />
- <property name="defaultAutoCommit" value="false" />
- <!-- 连接Idle一个小时后超时 -->
- <property name="timeBetweenEvictionRunsMillis" value="3600000" />
- <property name="minEvictableIdleTimeMillis" value="3600000" />
- <property name="testWhileIdle" value="true" />
- <property name="testOnBorrow" value="true" />
- <property name="testOnReturn" value="false" />
- <property name="validationQuery" value="SELECT 1" />
- <property name="logAbandoned" value="false" />
- <property name="removeAbandoned" value="true" />
- <property name="removeAbandonedTimeout" value="60" />
- </bean>
- </beans>