文章目录
- spring框架实现读写分离
- 1、思路
- 2、读写分离的优点?
- 3、读写分离在项目中如何使用?
- 第一步:导入jar包,pom.xml
- 第二步:配置config.properties
- 第三步:log4j.properties文件
- 第四步:spring-mvc.xml文件
- 第五步:spring-mybatis.xml文件
- 第六步:spring.xml文件
- 第七步:DataSourceAdvice.java文件
- 第八步:DataSourceSwitcher.java文件
- 第九步:DynamicDataSource.java文件
- 第十步:测试代码UserMapper.xml文件
- 第十一步:UserMapper.java文件
- 第十二步:IUserService的文件
- 第十三步:UserServiceImpl.java文件
- 第十四步:User.java实体类
- 第十五步:TestUser.java的文件
spring框架实现读写分离
1、思路
第一种方法:思路是使用Spring AOP做数据源的切面来更换不同的读写数据库。对应的读写库使用LVS等负载器可以分发完成集群。
这种在应用层做读写分离,在项目中不是很好的控制。因为只能在程序中做控制。
参考文档第二种方法:对于MySql而已,可以使用mysql-proxy或amoeba做中间件转发和读写分离,这不需要修改应用层的代码即可完成。
参考文档
2、读写分离的优点?
减少数据库压力,提高并发量。
3、读写分离在项目中如何使用?
项目结构图:
第一步:导入jar包,pom.xml
pom.xml文件的源码:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jk</groupId>
<artifactId>dyjfc-master-slave</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>dyjfc-master-slave Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!--引入spring-test对应的jar包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>3.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.5</version>
</dependency>
<!--引入spring-webmvc对应jar包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.2.0.RELEASE</version>
</dependency>
<!-- spring3 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>3.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>3.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>3.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.2.0.RELEASE</version>
</dependency>
<!--引入mybatis的jar包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.1.1</version>
</dependency>
<!--mybatis公司自己编写的mybatis与spring整合的jar包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.1.1</version>
</dependency>
<!--引入junit对应的测试jar包 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<!--添加scope作用域为test时,只有测试的时候才引入jar包 -->
<scope>test</scope>
</dependency>
<!--引入druid对应jar包 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.1</version>
</dependency>
<!--引入org.aspectj对应的jar包 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.7.4</version>
</dependency>
<!--引入jackson-mapper-asl相应插件的jar包 -->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.9</version>
</dependency>
<!--引入commons-fileupload,文件上传时候用到的jar包 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<!--引入javax.servlet对应jar包 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!--引入log4j对应的jar包 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- oracle驱动 -->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0</version>
</dependency>
<!-- oracle驱动需要官方授权,不能再中央仓库直接下载 -->
<!-- <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc6</artifactId>
<version>11.2.0</version> <scope>system</scope> <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/ojdbc6.jar</systemPath>
</dependency> -->
<!--引入mysql-connector-java驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.23</version>
</dependency>
<!--引入fastjson对应的jar包 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.7</version>
</dependency>
<!-- 加入jstl依赖包 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2.1-b03</version>
<scope>provided</scope>
</dependency>
<!-- activity工作 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>5.16</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>5.16</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-converter</artifactId>
<version>5.16</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>3.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>3.2.0.RELEASE</version>
</dependency>
<!-- spring定时器 -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.2</version>
</dependency>
<!-- oscache缓存jar包 -->
<dependency>
<groupId>opensymphony</groupId>
<artifactId>oscache</artifactId>
<version>2.4</version>
</dependency>
<!-- maven配置httpclient jar包 -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.0.1</version>
</dependency>
<!-- dom4j -->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.1.6</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>3.1.6</version>
</dependency>
</dependencies>
<build>
<finalName>dyjfc-master-slave</finalName>
</build>
</project>
第二步:配置config.properties
介绍下mysql数据库读写分离在spring,mybatis框架下的配置。
1.mysql连接配置文件config.properties
master.. 表示主数据库连接参数,负责增,删,改;
slave.. 表示从数据库连接参数,只负责读取;
config.properties配置文件的源码:
#hibernate.dialect=org.hibernate.dialect.OracleDialect
#driverClassName=oracle.jdbc.driver.OracleDriver
#validationQuery=SELECT 1 FROM DUAL
#jdbc_url=jdbc:oracle:thin:@localhost:1521:orcl
#jdbc_username=dyjfc
#jdbc_password=dyjfc
hibernate.dialect=org.hibernate.dialect.MySQLDialect
driverClassName=com.mysql.jdbc.Driver
validationQuery=SELECT 1
jdbc_url=jdbc:mysql://localhost:3306/sy?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
jdbc_username=sypro
jdbc_password=sypro
master.jdbc.driverClassName=com.mysql.jdbc.Driver
master.jdbc.url=jdbc:mysql://127.0.0.1:3307/dyjfc?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
master.jdbc.username=root
master.jdbc.password=
slave.jdbc.driverClassName=com.mysql.jdbc.Driver
slave.jdbc.url=jdbc:mysql://127.0.0.1:3308/dyjfc?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
slave.jdbc.username=root
slave.jdbc.password=
#hibernate.dialect=org.hibernate.dialect.SQLServerDialect
#driverClassName=net.sourceforge.jtds.jdbc.Driver
#validationQuery=SELECT 1
#jdbc_url=jdbc:jtds:sqlserver://127.0.0.1:1433/sy
#jdbc_username=sa
#jdbc_password=123456
#hibernate.dialect=org.hibernate.dialect.DerbyDialect
#driverClassName=org.apache.derby.jdbc.EmbeddedDriver
#validationQuery=SELECT 1
#jdbc_url=jdbc:derby:sy;create=true
#jdbc_username=sypro
#jdbc_password=sypro
#jndiName=java:comp/env/dataSourceName
hibernate.hbm2ddl.auto=update
hibernate.show_sql=false
hibernate.format_sql=true
sessionInfoName=sessionInfo
uploadFieldName=filedata
uploadFileMaxSize=20971520
uploadFileExts=txt,rar,zip,doc,docx,xls,xlsx,jpg,jpeg,gif,png,swf,wmv,avi,wma,mp3,mid
uploadDirectory=attached
第三步:log4j.properties文件
log4j.properties文件的源码
log4j.rootLogger=DEBUG,Console,File
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.Target=System.out
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%c]%m%n
log4j.appender.File=org.apache.log4j.RollingFileAppender
log4j.appender.File.File=mybatis.log
log4j.appender.File.MaxFileSize=10MB
log4j.appender.File.Threshold=ALL
log4j.appender.File.layout=org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH\:mm\:ss,SSS}][%c]%m%n
第四步:spring-mvc.xml文件
配置文件spring-mvc.xml文件的源码:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<!-- 自动扫描controller包下的所有类,使其认为spring mvc的控制器 -->
<context:component-scan base-package="com.jk.controller" />
<!-- 避免IE执行AJAX时,返回JSON出现下载文件 -->
<bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
<!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="mappingJacksonHttpMessageConverter" /><!-- json转换器 -->
</list>
</property>
</bean>
<!-- 对模型视图名称的解析,即在模型视图名称添加前后缀 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/" p:suffix=".jsp" />
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding">
<value>UTF-8</value>
</property>
<property name="maxUploadSize">
<value>32505856</value><!-- 上传文件大小限制为31M,31*1024*1024 -->
</property>
<property name="uploadTempDir">
<value>/upload/</value><!--上传后的目录名-->
</property>
<property name="maxInMemorySize">
<value>4096</value>
</property>
</bean>
<!-- 拦截器 -->
<!-- <mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="com.jk.interceptors.SecurityInterceptor">
不需要权限验证的地址
<property name="excludeUrls">
<list>
<value>/initController/init</value>初始化数据库
<value>/menuController/initTree</value>首页左侧功能菜单
<value>/userController/userList</value>用户注册
<value>/userController/login</value>用户登录
<value>/userController/loginCombobox</value>用户登录里面的autocomplete功能
<value>/userController/loginCombogrid</value>用户登录里面的combogrid功能
<value>/userController/logout</value>注销登录
<value>/resourceController/allTree</value>角色访问资源下拉树
<value>/roleController/tree</value>用户访问角色树(只能看到自己拥有的角色)
<value>/roleController/allTree</value>用户访问角色树
<value>/userController/editCurrentUserPwdPage</value>用户修改自己的密码页面
<value>/userController/editCurrentUserPwd</value>用户修改自己的密码
<value>/userController/currentUserRolePage</value>查看自己的角色页面
<value>/userController/currentUserResourcePage</value>查看自己的权限页面
</list>
</property>
</bean>
</mvc:interceptor>
</mvc:interceptors> -->
</beans>
第五步:spring-mybatis.xml文件
spring-mybatis.xml的源码:
<?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:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.1.xsd
">
<!-- JNDI方式配置数z据源 -->
<!-- <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="${jndiName}"></property> </bean> -->
<!-- 开启注解定时器任务 -->
<task:annotation-driven/>
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
<bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" >
</bean>
<!-- 配置数据源 -->
<bean name="parentDataSource" class="com.alibaba.druid.pool.DruidDataSource" >
</bean>
<!-- 主数据源-->
<bean id="masterDataSource" parent="parentDataSource">
<property name="url" value="${master.jdbc.url}" />
<property name="username" value="${master.jdbc.username}" />
<property name="password" value="${master.jdbc.password}" />
</bean>
<!-- 从数据源-->
<bean id="slaveDataSource" parent="parentDataSource">
<property name="url" value="${slave.jdbc.url}" />
<property name="username" value="${slave.jdbc.username}" />
<property name="password" value="${slave.jdbc.password}" />
</bean>
<bean id="dataSource" class="com.jk.aop.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry key="slave" value-ref="slaveDataSource" />
</map>
</property>
<property name="defaultTargetDataSource" ref="masterDataSource" />
</bean>
<!-- myBatis文件 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 自动扫描entity目录, 省掉Configuration.xml里的手工配置 -->
<property name="mapperLocations" value="classpath:mapping/*.xml" />
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.jk.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>
<!-- 切换数据源 -->
<bean id="dataSourceAdvice" class="com.jk.aop.DataSourceAdvice" />
<aop:config>
<aop:advisor
pointcut="execution(* com.jk.service..*Impl.*(..))"
advice-ref="dataSourceAdvice" />
</aop:config>
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 注解方式配置事物 -->
<!-- <tx:annotation-driven transaction-manager="transactionManager" /> -->
<!-- 拦截器方式配置事物 -->
<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="append*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="modify*" propagation="REQUIRED" />
<tx:method name="edit*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="remove*" propagation="REQUIRED" />
<tx:method name="repair" propagation="REQUIRED" />
<tx:method name="delAndRepair" propagation="REQUIRED" />
<tx:method name="get*" propagation="SUPPORTS" />
<tx:method name="find*" propagation="SUPPORTS" />
<tx:method name="load*" propagation="SUPPORTS" />
<tx:method name="search*" propagation="SUPPORTS" />
<tx:method name="datagrid*" propagation="SUPPORTS" />
<tx:method name="*" propagation="SUPPORTS" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="transactionPointcut" expression="execution(* com.jk.service..*Impl.*(..))" />
<aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" />
</aop:config>
<!-- 配置druid监控spring jdbc -->
<bean id="druid-stat-interceptor" class="com.alibaba.druid.support.spring.stat.DruidStatInterceptor">
</bean>
<bean id="druid-stat-pointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut" scope="prototype">
<property name="patterns">
<list>
<value>com.jk.service.*</value>
</list>
</property>
</bean>
<aop:config>
<aop:advisor advice-ref="druid-stat-interceptor" pointcut-ref="druid-stat-pointcut" />
</aop:config>
</beans>
第六步:spring.xml文件
spring.xml文件的源码:
<?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" xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
">
<!-- 引入属性文件 -->
<context:property-placeholder location="classpath:config.properties" />
<!-- 自动扫描(自动注入) -->
<context:component-scan base-package="com.jk.service" />
<!-- <context:component-scan base-package="com.jk.test" /> -->
</beans>
第七步:DataSourceAdvice.java文件
DataSourceAdvice.java文件的源码:
package com.jk.aop;
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.ThrowsAdvice;
public class DataSourceAdvice implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice{
// service方法执行之前被调用
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("切入点: " + target.getClass().getName() + "类中" + method.getName() + "方法");
if(method.getName().startsWith("add")
|| method.getName().startsWith("create")
|| method.getName().startsWith("save")
|| method.getName().startsWith("edit")
|| method.getName().startsWith("update")
|| method.getName().startsWith("delete")
|| method.getName().startsWith("remove")){
System.out.println("切换到: master");
DataSourceSwitcher.setMaster();
}
else {
if(method.getName().startsWith("find1")
){
System.out.println("切换到: master");
DataSourceSwitcher.setSlaveall("数码IP:181283132");
}
if( method.getName().startsWith("find2")
){
System.out.println("切换到: master");
DataSourceSwitcher.setSlaveall("IP衣服:181283132");
}
}
}
// service方法执行完之后被调用
public void afterReturning(Object arg0, Method method, Object[] args, Object target) throws Throwable {
}
// 抛出Exception之后被调用
public void afterThrowing(Method method, Object[] args, Object target, Exception ex) throws Throwable {
DataSourceSwitcher.setSlave();
System.out.println("出现异常,切换到: slave");
}
}
第八步:DataSourceSwitcher.java文件
DataSourceSwitcher.java的源码:
package com.jk.aop;
import org.springframework.util.Assert;
public class DataSourceSwitcher {
@SuppressWarnings("rawtypes")
private static final ThreadLocal contextHolder = new ThreadLocal();
@SuppressWarnings("unchecked")
public static void setDataSource(String dataSource) {
Assert.notNull(dataSource, "dataSource cannot be null");
contextHolder.set(dataSource);
}
public static void setMaster(){
clearDataSource();
}
public static void setSlave() {
setDataSource("slave");
}
public static void setSlaveall(String key) {
setDataSource(key);
}
public static String getDataSource() {
return (String) contextHolder.get();
}
public static void clearDataSource() {
contextHolder.remove();
}
}
第九步:DynamicDataSource.java文件
DynamicDataSource.java文件的源码:
package com.jk.aop;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource{
@Override
protected Object determineCurrentLookupKey() {
return DataSourceSwitcher.getDataSource();
}
}
第十步:测试代码UserMapper.xml文件
<?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.jk.dao.UserMapper">
<resultMap id="BaseResultMap" type="com.jk.model.User">
<id column="ID" property="id" jdbcType="VARCHAR"/>
<result column="NAME" property="name" jdbcType="VARCHAR"/>
<result column="PWD" property="pwd" jdbcType="VARCHAR"/>
<result column="CREATEDATETIME" property="createdatetime" jdbcType="TIMESTAMP"/>
<result column="MODIFYDATETIME" property="modifydatetime" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="Base_Column_List">
ID, NAME, PWD, CREATEDATETIME, MODIFYDATETIME
</sql>
<!-- 添加用户 -->
<insert id="insert" parameterType="com.jk.model.User">
INSERT INTO tuser (ID, NAME, PWD, CREATEDATETIME, MODIFYDATETIME) VALUES
(#{id}, #{name}, #{pwd}, #{createdatetime}, #{modifydatetime})
</insert>
<!-- 删除用户 -->
<delete id="deleteUser" parameterType="com.jk.model.User">
DELETE FROM tuser WHERE ID = #{id}
</delete>
<!-- 修改用户 -->
<update id="updateUser" parameterType="com.jk.model.User">
UPDATE tuser
<set>
<if test="name != null">
NAME = #{name},
</if>
<if test="pwd != null">
PWD = #{pwd},
</if>
<if test="createdatetime != null">
CREATEDATETIME = #{createdatetime},
</if>
<if test="modifydatetime != null">
MODIFYDATETIME = #{modifydatetime},
</if>
</set>
WHERE ID = #{id}
</update>
<!-- 查询用户信息列表 -->
<select id="userList" resultMap="BaseResultMap" parameterType="com.jk.model.User">
SELECT ID, NAME, PWD, CREATEDATETIME, MODIFYDATETIME FROM tuser
</select>
</mapper>
第十一步:UserMapper.java文件
UserMapper.java文件的源码:
package com.jk.dao;
import java.util.List;
import java.util.Map;
import com.jk.model.User;
public interface UserMapper {
/**
* <pre>userList(查询用户列表信息)
* 创建人:杨志超 yangzhichao150@126.com
* 创建时间:2016年9月8日 下午2:50:48
* 修改人:杨志超 yangzhichao150@126.com
* 修改时间:2016年9月8日 下午2:50:48
* 修改备注:
* @param user
* @return
* @throws Exception</pre>
*/
public List<User> userList(User user) throws Exception;
/**
* <pre>saveUser(添加用户信息)
* 创建人:杨志超 yangzhichao150@126.com
* 创建时间:2016年9月8日 下午2:51:05
* 修改人:杨志超 yangzhichao150@126.com
* 修改时间:2016年9月8日 下午2:51:05
* 修改备注:
* @param user
* @throws Exception</pre>
*/
public void insert(User user) throws Exception;
public void updateUser(User user) throws Exception;
public void deleteUser(User user) throws Exception;
}
第十二步:IUserService的文件
IUserService.java文件的源码:
package com.jk.service;
import java.util.List;
import com.jk.model.User;
public interface IUserService {
/**
* <pre>userList(查询用户列表信息)
* 创建人:杨志超 yangzhichao150@126.com
* 创建时间:2016年9月8日 下午2:58:31
* 修改人:杨志超 yangzhichao150@126.com
* 修改时间:2016年9月8日 下午2:58:31
* 修改备注:
* @param user
* @return
* @throws Exception</pre>
*/
public List<User> userList(User user) throws Exception;
/**
* <pre>saveUser(添加用户信息)
* 创建人:杨志超 yangzhichao150@126.com
* 创建时间:2016年9月8日 下午2:59:01
* 修改人:杨志超 yangzhichao150@126.com
* 修改时间:2016年9月8日 下午2:59:01
* 修改备注:
* @param user
* @throws Exception</pre>
*/
public void saveUser(User user) throws Exception;
}
第十三步:UserServiceImpl.java文件
UserServiceImpl.java文件的源码:
package com.jk.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.jk.dao.UserMapper;
import com.jk.model.User;
import com.jk.service.IUserService;
@Service("userService")
public class UserServiceImpl implements IUserService {
@Autowired
private UserMapper userDao;
@Override
public List<User> userList(User user) throws Exception {
List<User> userList = userDao.userList(user);
return userList;
}
@Override
public void saveUser(User user) throws Exception {
userDao.insert(user);
}
}
第十四步:User.java实体类
User.java的源码:
package com.jk.model;
import java.io.Serializable;
import java.util.Date;
public class User implements Serializable {
private static final long serialVersionUID = 5294240072221941561L;
private String id;
private String name;
private String pwd;
private Date createdatetime;
private Date modifydatetime;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public Date getCreatedatetime() {
return createdatetime;
}
public void setCreatedatetime(Date createdatetime) {
this.createdatetime = createdatetime;
}
public Date getModifydatetime() {
return modifydatetime;
}
public void setModifydatetime(Date modifydatetime) {
this.modifydatetime = modifydatetime;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", pwd=" + pwd
+ ", createdatetime=" + createdatetime + ", modifydatetime="
+ modifydatetime + "]";
}
}
第十五步:TestUser.java的文件
TestUser.java文件的源码:
package com.jk.test;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.alibaba.fastjson.JSON;
import com.jk.model.User;
import com.jk.service.IUserService;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring.xml","classpath:spring-mybatis.xml"})
public class TestUser {
@Autowired
private IUserService userService;
@Test
public void userList() {
User user = new User();
try {
List<User> userList = userService.userList(user);
System.out.println(JSON.toJSONStringWithDateFormat(userList, "yyyy-MM-dd HH:mm:ss"));
} catch (Exception e) {
e.printStackTrace();
}
}
//
// @Test
// public void saveUser() {
// User user = new User();
// user.setId(UUID.randomUUID().toString());
// user.setName("admin");
// user.setPwd("admin");
// user.setCreatedatetime(new Date());
// user.setModifydatetime(new Date());
// try {
// userService.saveUser(user);
// System.out.println("添加成功!");
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
}
测试成功!
Spring+Hibernate框架下MySql读写分离,主从数据库配置