打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Spring MVC +Spring + Mybatis 构建分库分表总结 SSM搭建以及分库分表的实现

分库分表在小型公司很少能遇到也很少使用,毕竟数据量没有那么大,当数据量大,所有数据都压在一张表时,如果单从数据库的角度考虑是可以分库分表处理来存储数据。分库分表 顾名思义就是根据查询条件动态的去获取数据所在的库和表的位置.例如一个系统有唯一的标识userNum,所有路由规则都可以根据userNum做库表的定位工作.本文测试用3个库5个表做测试.

三个库book_00,book_01,book_02  每个库里的表 t_user_0000,t_user_0001,t_user_0002,t_user_0003,t_user_0004,根据userNum寻找匹配库的_00后缀,匹配表的_0000 后缀 即可定位到是几库几表.

     本人会建立一个新的项目,一步一步讲解如果简单的搭建一个分库分表的系统并且用页面展示从库里查询出来的数据.

   1,首先需要创建一个新的maven的webApp项目



使用框架版本:

       Spring 4.0.2 RELEASE

       Spring MVC 4.0.2 RELEASE

       MyBatis 3.2.6


2,pom里引入jar包


  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <groupId>com.subdt</groupId>
  5. <artifactId>subDbTable</artifactId>
  6. <packaging>war</packaging>
  7. <version>1.0-SNAPSHOT</version>
  8. <name>subDbTable Maven Webapp</name>
  9. <url>http://maven.apache.org</url>
  10. <properties>
  11. <!-- spring版本号 -->
  12. <spring.version>4.0.2.RELEASE</spring.version>
  13. <!-- mybatis版本号 -->
  14. <mybatis.version>3.2.6</mybatis.version>
  15. <!-- log4j日志文件管理包版本 -->
  16. <slf4j.version>1.7.7</slf4j.version>
  17. <log4j.version>1.2.17</log4j.version>
  18. </properties>
  19. <dependencies>
  20. <dependency>
  21. <groupId>junit</groupId>
  22. <artifactId>junit</artifactId>
  23. <version>4.11</version>
  24. <!-- 表示开发的时候引入,发布的时候不会加载此包 -->
  25. <scope>test</scope>
  26. </dependency>
  27. <!-- spring核心包 -->
  28. <dependency>
  29. <groupId>org.springframework</groupId>
  30. <artifactId>spring-core</artifactId>
  31. <version>${spring.version}</version>
  32. </dependency>
  33. <dependency>
  34. <groupId>org.springframework</groupId>
  35. <artifactId>spring-web</artifactId>
  36. <version>${spring.version}</version>
  37. </dependency>
  38. <dependency>
  39. <groupId>org.springframework</groupId>
  40. <artifactId>spring-oxm</artifactId>
  41. <version>${spring.version}</version>
  42. </dependency>
  43. <dependency>
  44. <groupId>org.springframework</groupId>
  45. <artifactId>spring-tx</artifactId>
  46. <version>${spring.version}</version>
  47. </dependency>
  48. <dependency>
  49. <groupId>org.springframework</groupId>
  50. <artifactId>spring-jdbc</artifactId>
  51. <version>${spring.version}</version>
  52. </dependency>
  53. <dependency>
  54. <groupId>org.springframework</groupId>
  55. <artifactId>spring-webmvc</artifactId>
  56. <version>${spring.version}</version>
  57. </dependency>
  58. <dependency>
  59. <groupId>org.springframework</groupId>
  60. <artifactId>spring-aop</artifactId>
  61. <version>${spring.version}</version>
  62. </dependency>
  63. <dependency>
  64. <groupId>org.springframework</groupId>
  65. <artifactId>spring-context-support</artifactId>
  66. <version>${spring.version}</version>
  67. </dependency>
  68. <dependency>
  69. <groupId>org.springframework</groupId>
  70. <artifactId>spring-test</artifactId>
  71. <version>${spring.version}</version>
  72. </dependency>
  73. <dependency>
  74. <groupId>org.aspectj</groupId>
  75. <artifactId>aspectjweaver</artifactId>
  76. <version>1.8.9</version>
  77. </dependency>
  78. <dependency>
  79. <groupId>commons-beanutils</groupId>
  80. <artifactId>commons-beanutils</artifactId>
  81. <version>1.8.3</version>
  82. </dependency>
  83. <dependency>
  84. <groupId>commons-lang</groupId>
  85. <artifactId>commons-lang</artifactId>
  86. <version>2.6</version>
  87. </dependency>
  88. <!-- mybatis核心包 -->
  89. <dependency>
  90. <groupId>org.mybatis</groupId>
  91. <artifactId>mybatis</artifactId>
  92. <version>${mybatis.version}</version>
  93. </dependency>
  94. <!-- mybatis/spring包 -->
  95. <dependency>
  96. <groupId>org.mybatis</groupId>
  97. <artifactId>mybatis-spring</artifactId>
  98. <version>1.2.2</version>
  99. </dependency>
  100. <!-- 导入java ee jar 包 -->
  101. <dependency>
  102. <groupId>javax</groupId>
  103. <artifactId>javaee-api</artifactId>
  104. <version>7.0</version>
  105. </dependency>
  106. <!-- 导入Mysql数据库链接jar包 -->
  107. <dependency>
  108. <groupId>mysql</groupId>
  109. <artifactId>mysql-connector-java</artifactId>
  110. <version>5.1.30</version>
  111. </dependency>
  112. <!-- 导入dbcp的jar包,用来在applicationContext.xml中配置数据库 -->
  113. <dependency>
  114. <groupId>commons-dbcp</groupId>
  115. <artifactId>commons-dbcp</artifactId>
  116. <version>1.2.2</version>
  117. </dependency>
  118. <!-- JSTL标签类 -->
  119. <dependency>
  120. <groupId>jstl</groupId>
  121. <artifactId>jstl</artifactId>
  122. <version>1.2</version>
  123. </dependency>
  124. <!-- 日志文件管理包 -->
  125. <!-- log start -->
  126. <dependency>
  127. <groupId>log4j</groupId>
  128. <artifactId>log4j</artifactId>
  129. <version>${log4j.version}</version>
  130. </dependency>
  131. <!-- 格式化对象,方便输出日志 -->
  132. <dependency>
  133. <groupId>com.alibaba</groupId>
  134. <artifactId>fastjson</artifactId>
  135. <version>1.1.41</version>
  136. </dependency>
  137. <dependency>
  138. <groupId>org.slf4j</groupId>
  139. <artifactId>slf4j-api</artifactId>
  140. <version>${slf4j.version}</version>
  141. </dependency>
  142. <dependency>
  143. <groupId>org.slf4j</groupId>
  144. <artifactId>slf4j-log4j12</artifactId>
  145. <version>${slf4j.version}</version>
  146. </dependency>
  147. <!-- log end -->
  148. <!-- 映入JSON -->
  149. <dependency>
  150. <groupId>org.codehaus.jackson</groupId>
  151. <artifactId>jackson-mapper-asl</artifactId>
  152. <version>1.9.13</version>
  153. </dependency>
  154. <!-- 上传组件包 -->
  155. <dependency>
  156. <groupId>commons-fileupload</groupId>
  157. <artifactId>commons-fileupload</artifactId>
  158. <version>1.3.1</version>
  159. </dependency>
  160. <dependency>
  161. <groupId>commons-io</groupId>
  162. <artifactId>commons-io</artifactId>
  163. <version>2.4</version>
  164. </dependency>
  165. <dependency>
  166. <groupId>commons-codec</groupId>
  167. <artifactId>commons-codec</artifactId>
  168. <version>1.9</version>
  169. </dependency>
  170. <dependency>
  171. <groupId>com.google.code.gson</groupId>
  172. <artifactId>gson</artifactId>
  173. <version>1.7.1</version>
  174. </dependency>
  175. </dependencies>
  176. <build>
  177. <finalName>subDbTable</finalName>
  178. <resources>
  179. <!--编译之后包含xml-->
  180. <resource>
  181. <directory>src/main/resources</directory>
  182. <filtering>true</filtering>
  183. </resource>
  184. <resource>
  185. <directory>src/main/java</directory>
  186. <includes>
  187. <include>**/*.xml</include>
  188. </includes>
  189. <filtering>true</filtering>
  190. </resource>
  191. </resources>
  192. <plugins>
  193. <plugin>
  194. <groupId>org.apache.maven.plugins</groupId>
  195. <artifactId>maven-resources-plugin</artifactId>
  196. <configuration>
  197. <encoding>UTF-8</encoding>
  198. </configuration>
  199. </plugin>
  200. </plugins>
  201. </build>
  202. </project>

首先看下目录结构




3,Spring与MyBatis的整合


首先创建 jdbc.properties 配置数据库信息

  1. driver=com.mysql.jdbc.Driver
  2. #定义初始连接数
  3. initialSize=0
  4. #定义最大连接数
  5. maxActive=20
  6. #定义最大空闲
  7. maxIdle=20
  8. #定义最小空闲
  9. minIdle=1
  10. #定义最长等待时间
  11. maxWait=60000
  12. jdbc.mysql.url0=jdbc:mysql://localhost:3306/book_02?createDatabaseIfNotExist=true&characterEncoding=utf-8&useUnicode=true
  13. jdbc.mysql.username0=root
  14. jdbc.mysql.password0=123456
  15. jdbc.mysql.url1=jdbc:mysql://localhost:3306/book_00?createDatabaseIfNotExist=true&characterEncoding=utf-8&useUnicode=true
  16. jdbc.mysql.username1=root
  17. jdbc.mysql.password1=123456
  18. jdbc.mysql.url2=jdbc:mysql://localhost:3306/book_01?createDatabaseIfNotExist=true&characterEncoding=utf-8&useUnicode=true
  19. jdbc.mysql.username2=root
  20. jdbc.mysql.password2=123456

创建Spring配置文件 spring-config.xml


  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:aop="http://www.springframework.org/schema/aop"
  6. 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/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
  7. default-autowire="byName">
  8. <context:component-scan base-package="com.sub.dt"/>
  9. <aop:aspectj-autoproxy/>
  10. <!-- 属性文件读入 -->
  11. <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  12. <property name="locations">
  13. <list>
  14. <value>classpath:props/*.properties</value>
  15. </list>
  16. </property>
  17. </bean>
  18. <import resource="classpath:spring/spring-*.xml"/>
  19. </beans>

创建spring与mybatis结合的整合配置文件. spring-config-datasource-dbcp.xml

这个文件主要是多数据源配置,自动扫描mybatis的xml配置文件.


  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5. <!-- 引入配置文件 -->
  6. <bean id="propertyConfigurer"
  7. class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  8. <property name="location" value="classpath:props/jdbc.properties"/>
  9. </bean>
  10. <bean id="dataSource0" class="org.apache.commons.dbcp.BasicDataSource">
  11. <property name="driverClassName" value="${driver}"/>
  12. <property name="url" value="${jdbc.mysql.url0}"/>
  13. <property name="username" value="${jdbc.mysql.username0}"/>
  14. <property name="password" value="${jdbc.mysql.password0}"/>
  15. <!-- 初始化连接大小 -->
  16. <property name="initialSize" value="${initialSize}"></property>
  17. <!-- 连接池最大数量 -->
  18. <property name="maxActive" value="${maxActive}"></property>
  19. <!-- 连接池最大空闲 -->
  20. <property name="maxIdle" value="${maxIdle}"></property>
  21. <!-- 连接池最小空闲 -->
  22. <property name="minIdle" value="${minIdle}"></property>
  23. <!-- 获取连接最大等待时间 -->
  24. <property name="maxWait" value="${maxWait}"></property>
  25. </bean>
  26. <bean id="dataSource1" class="org.apache.commons.dbcp.BasicDataSource">
  27. <property name="driverClassName" value="${driver}"/>
  28. <property name="url" value="${jdbc.mysql.url1}"/>
  29. <property name="username" value="${jdbc.mysql.username1}"/>
  30. <property name="password" value="${jdbc.mysql.password1}"/>
  31. <!-- 初始化连接大小 -->
  32. <property name="initialSize" value="${initialSize}"></property>
  33. <!-- 连接池最大数量 -->
  34. <property name="maxActive" value="${maxActive}"></property>
  35. <!-- 连接池最大空闲 -->
  36. <property name="maxIdle" value="${maxIdle}"></property>
  37. <!-- 连接池最小空闲 -->
  38. <property name="minIdle" value="${minIdle}"></property>
  39. <!-- 获取连接最大等待时间 -->
  40. <property name="maxWait" value="${maxWait}"></property>
  41. </bean>
  42. <bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource">
  43. <property name="driverClassName" value="${driver}"/>
  44. <property name="url" value="${jdbc.mysql.url2}"/>
  45. <property name="username" value="${jdbc.mysql.username2}"/>
  46. <property name="password" value="${jdbc.mysql.password2}"/>
  47. <!-- 初始化连接大小 -->
  48. <property name="initialSize" value="${initialSize}"></property>
  49. <!-- 连接池最大数量 -->
  50. <property name="maxActive" value="${maxActive}"></property>
  51. <!-- 连接池最大空闲 -->
  52. <property name="maxIdle" value="${maxIdle}"></property>
  53. <!-- 连接池最小空闲 -->
  54. <property name="minIdle" value="${minIdle}"></property>
  55. <!-- 获取连接最大等待时间 -->
  56. <property name="maxWait" value="${maxWait}"></property>
  57. </bean>
  58. <bean id="mysqlDynamicDataSource" class="com.sub.dt.dbRouting.db.DynamicDataSource">
  59. <property name="targetDataSources">
  60. <!-- 标识符类型 -->
  61. <map>
  62. <entry key="db0" value-ref="dataSource0"/>
  63. <entry key="db1" value-ref="dataSource1"/>
  64. <entry key="db2" value-ref="dataSource2"/>
  65. </map>
  66. </property>
  67. </bean>
  68. <bean id="dbRuleSet" class="com.sub.dt.dbRouting.bean.RouterSet">
  69. <property name="routeFieldStart" value="0"></property>
  70. <property name="routeFieldEnd" value="9200000000000000000"></property>
  71. <property name="dbNumber" value="3"></property>
  72. <property name="routeType" value="2"></property>
  73. <property name="ruleType" value="3"></property>
  74. <property name="tableNumber" value="5"></property>
  75. <property name="dbKeyArray">
  76. <list>
  77. <value>db0</value>
  78. <value>db1</value>
  79. <value>db2</value>
  80. </list>
  81. </property>
  82. </bean>
  83. <bean id="dBRouter" class="com.sub.dt.dbRouting.router.DBRouterImpl">
  84. <property name="routerSetList">
  85. <!-- 标识符类型 -->
  86. <list>
  87. <ref bean="dbRuleSet"/>
  88. </list>
  89. </property>
  90. </bean>
  91. <!--事务-->
  92. <bean id="baiTiaoTransactionManager"
  93. class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  94. <property name="dataSource" ref="mysqlDynamicDataSource"></property>
  95. </bean>
  96. <bean id="btTransactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
  97. <property name="transactionManager" ref="baiTiaoTransactionManager"></property>
  98. <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"></property>
  99. </bean>
  100. <!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->
  101. <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  102. <property name="dataSource" ref="mysqlDynamicDataSource"/>
  103. <!-- 自动扫描mapping.xml文件 -->
  104. <property name="mapperLocations" value="classpath:com/sub/dt/mapping/*.xml"></property>
  105. </bean>
  106. <!-- DAO接口所在包名,Spring会自动查找其下的类 -->
  107. <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  108. <property name="basePackage" value="com.sub.dt.dao"/>
  109. <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
  110. </bean>
  111. </beans>

程序使用spring aop切面+自定义注解的方式去在每个方法调用时根据userNum定位库表, 关键类已标红(代码会上传附件自行下载查看)




spring-config-datasource-dbcp.xml中配置的com.sub.dt.dbRouting.db.DynamicDataSource 继承 AbstractRoutingDataSource方法,单表配置mybatis是使用的是BasicDataSource

BasicDataSourBasicDataSource

BasicDataSource 自定义的AbstractRoutingDataSource与spring的BasicDataSource都是一个道理 管理数据源 实现了DataSource接口.


  1. package com.sub.dt.dbRouting.db;
  2. import com.sub.dt.dbRouting.DbContextHolder;
  3. import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
  4. import java.util.logging.Logger;
  5. /**
  6. * @Description SPring 的动态数据源的实现
  7. * @Autohr supers【weChat:13031016567】
  8. */
  9. public class DynamicDataSource extends AbstractRoutingDataSource {
  10. public static final Logger logger = Logger.getLogger(DynamicDataSource.class.toString());
  11. @Override
  12. protected Object determineCurrentLookupKey() {
  13. return DbContextHolder.getDbKey();//获取当前数据源
  14. }
  15. }
UserMapper.xml创建库表对应的xml文件

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
  3. <mapper namespace="com.sub.dt.dao.IUserDao">
  4. <resultMap id="BaseResultMap" type="com.sub.dt.pojo.User">
  5. <id column="id" property="id" jdbcType="INTEGER"/>
  6. <result column="user_name" property="userName" jdbcType="VARCHAR"/>
  7. <result column="password" property="password" jdbcType="VARCHAR"/>
  8. <result column="age" property="age" jdbcType="INTEGER"/>
  9. <result column="user_num" property="userNum" jdbcType="VARCHAR"/>
  10. </resultMap>
  11. <sql id="Base_Column_List">
  12. id,user_num, user_name, password, age
  13. </sql>
  14. <insert id="insertUser" parameterType="com.sub.dt.pojo.User">
  15. insert into t_user${tableIndex} (id,user_num,user_name, password,age)
  16. values (#{id,jdbcType=INTEGER},#{userNum,jdbcType=VARCHAR}, #{userName,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR},#{age,jdbcType=INTEGER})
  17. </insert>
  18. <insert id="deleteByuserNum" parameterType="com.sub.dt.pojo.User">
  19. delete from t_user${tableIndex}
  20. where user_num = #{userNum,jdbcType=VARCHAR}
  21. </insert>
  22. <update id="updateByUserNum" parameterType="com.sub.dt.pojo.User">
  23. update t_user${tableIndex}
  24. <set>
  25. <if test="userName != null">
  26. user_name = #{userName,jdbcType=VARCHAR},
  27. </if>
  28. <if test="password != null">
  29. password = #{password,jdbcType=VARCHAR},
  30. </if>
  31. <if test="age != null">
  32. age = #{age,jdbcType=INTEGER},
  33. </if>
  34. </set>
  35. where user_num = #{userNum,jdbcType=VARCHAR}
  36. </update>
  37. <select id="selectByUserNum" resultMap="BaseResultMap" parameterType="com.sub.dt.pojo.User">
  38. select
  39. <include refid="Base_Column_List"/>
  40. from t_user${tableIndex}
  41. where user_num = #{userNum,jdbcType=VARCHAR}
  42. </select>
  43. </mapper>

IUserDao.java

  1. package com.sub.dt.dao;
  2. import com.sub.dt.pojo.User;
  3. public interface IUserDao {
  4. /**
  5. * @Description
  6. * @Autohr supers【weChat:13031016567】
  7. */
  8. int insertUser(User user);
  9. /**
  10. * @Description
  11. * @Autohr supers【weChat:13031016567】
  12. */
  13. int deleteByuserNum(User user);
  14. /**
  15. * @Description
  16. * @Autohr supers【weChat:13031016567】
  17. */
  18. int updateByUserNum(User user);
  19. /**
  20. * @Description
  21. * @Autohr supers【weChat:13031016567】
  22. */
  23. User selectByUserNum(User user);
  24. }

IUserService.java
  1. package com.sub.dt.service;
  2. import com.sub.dt.pojo.User;
  3. /**
  4. * @Description
  5. * @Autohr supers【weChat:13031016567】
  6. */
  7. public interface IUserService {
  8. /**
  9. * @Description
  10. * @Autohr supers【weChat:13031016567】
  11. */
  12. public int insertUser(User user);
  13. /**
  14. * @Description
  15. * @Autohr supers【weChat:13031016567】
  16. */
  17. public int deleteByuserNum(User user);
  18. /**
  19. * @Description
  20. * @Autohr supers【weChat:13031016567】
  21. */
  22. public int updateByUserNum(User user);
  23. /**
  24. * @Description
  25. * @Autohr supers【weChat:13031016567】
  26. */
  27. public User selectByUserNum(User user);
  28. }

UserServiceImpl.java
  1. package com.sub.dt.service.impl;
  2. import com.sub.dt.dao.IUserDao;
  3. import com.sub.dt.dbRouting.annotation.Router;
  4. import com.sub.dt.pojo.User;
  5. import com.sub.dt.service.IUserService;
  6. import org.springframework.stereotype.Service;
  7. import javax.annotation.Resource;
  8. /**
  9. * @Description
  10. * @Autohr supers【weChat:13031016567】
  11. */
  12. @Service("userService")
  13. public class UserServiceImpl implements IUserService {
  14. @Resource
  15. private IUserDao userDao;
  16. @Router
  17. public int insertUser(User user) {
  18. return this.userDao.insertUser(user);
  19. }
  20. @Router
  21. public int deleteByuserNum(User user) {
  22. return this.userDao.deleteByuserNum(user);
  23. }
  24. @Router
  25. public int updateByUserNum(User user) {
  26. return this.userDao.updateByUserNum(user);
  27. }
  28. @Router
  29. public User selectByUserNum(User user) {
  30. return this.userDao.selectByUserNum(user);
  31. }
  32. }

UserController.java
  1. package com.sub.dt.controller;
  2. import com.sub.dt.pojo.User;
  3. import com.sub.dt.service.IUserService;
  4. import org.springframework.stereotype.Controller;
  5. import org.springframework.ui.Model;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import javax.annotation.Resource;
  8. import javax.servlet.http.HttpServletRequest;
  9. @Controller
  10. @RequestMapping("/user")
  11. public class UserController {
  12. @Resource
  13. private IUserService userService;
  14. @RequestMapping("/queryUser")
  15. public String toIndex(HttpServletRequest request,Model model,User user){
  16. User userDb = this.userService.selectByUserNum(user);
  17. model.addAttribute("user", userDb);
  18. return "queryUser";
  19. }
  20. }

4,核心分库分表包都在dbRouting文件夹下

Router.java  自定义注解,此注解作用是当做一个切点,在方法上添加此注解,执行方法前会执行DBRouterInterceptor的doRoute方法.详情可参考:http://blog.csdn.net/buchengbugui/article/details/60875401
  1. package com.sub.dt.dbRouting.annotation;
  2. import java.lang.annotation.ElementType;
  3. import java.lang.annotation.Retention;
  4. import java.lang.annotation.RetentionPolicy;
  5. import java.lang.annotation.Target;
  6. /**
  7. * @Description
  8. * @Autohr supers【weChat:13031016567】
  9. */
  10. @Retention(RetentionPolicy.RUNTIME)
  11. @Target(ElementType.METHOD)
  12. public @interface Router {
  13. String routerField() default RouterConstants.ROUTER_FIELD_DEFAULT;
  14. String tableStyle() default RouterConstants.ROUTER_TABLE_SUFFIX_DEFAULT;
  15. }

DBRouterInterceptor.java 定义切点为方法上使用,@Router注解的方法,执行注解方法前前执行doRoute方法,根据参数中的userNum设置是几库几表
  1. package com.sub.dt.dbRouting;
  2. import com.sub.dt.dbRouting.annotation.Router;
  3. import com.sub.dt.dbRouting.annotation.RouterConstants;
  4. import com.sub.dt.dbRouting.router.RouterUtils;
  5. import org.apache.commons.beanutils.BeanUtils;
  6. import org.apache.commons.lang.StringUtils;
  7. import org.aspectj.lang.JoinPoint;
  8. import org.aspectj.lang.Signature;
  9. import org.aspectj.lang.annotation.Aspect;
  10. import org.aspectj.lang.annotation.Before;
  11. import org.aspectj.lang.annotation.Pointcut;
  12. import org.aspectj.lang.reflect.MethodSignature;
  13. import org.slf4j.Logger;
  14. import org.slf4j.LoggerFactory;
  15. import org.springframework.beans.factory.annotation.Autowired;
  16. import org.springframework.stereotype.Component;
  17. import java.lang.reflect.Method;
  18. /**
  19. * @Description 切面切点 在Router注解的方法执行前执行 切点织入
  20. * @Autohr supers【weChat:13031016567】
  21. */
  22. @Aspect
  23. @Component
  24. public class DBRouterInterceptor {
  25. private static final Logger log = LoggerFactory.getLogger(DBRouterInterceptor.class);
  26. private DBRouter dBRouter;
  27. @Pointcut("@annotation( com.sub.dt.dbRouting.annotation.Router)")
  28. public void aopPoint() {
  29. }
  30. @Before("aopPoint()")
  31. public Object doRoute(JoinPoint jp) throws Throwable {
  32. long t1 = System.currentTimeMillis();
  33. boolean result = true;
  34. Method method = getMethod(jp);
  35. Router router = method.getAnnotation(Router.class);
  36. String routeField = router.routerField();
  37. Object[] args = jp.getArgs();
  38. if (args != null && args.length > 0) {
  39. for (int i = 0; i < args.length; i++) {
  40. long t2 = System.currentTimeMillis();
  41. String routeFieldValue = BeanUtils.getProperty(args[i],
  42. routeField);
  43. log.debug("routeFieldValue{}" + (System.currentTimeMillis() - t2));
  44. if (StringUtils.isNotEmpty(routeFieldValue)) {
  45. if (RouterConstants.ROUTER_FIELD_DEFAULT.equals(routeField)) {
  46. dBRouter.doRouteByResource("" + RouterUtils.getResourceCode(routeFieldValue));
  47. break;
  48. } else {
  49. this.searchParamCheck(routeFieldValue);
  50. String resource = routeFieldValue.substring(routeFieldValue.length() - 4);
  51. dBRouter.doRouteByResource(resource);
  52. break;
  53. }
  54. }
  55. }
  56. }
  57. log.debug("doRouteTime{}" + (System.currentTimeMillis() - t1));
  58. return result;
  59. }
  60. private Method getMethod(JoinPoint jp) throws NoSuchMethodException {
  61. Signature sig = jp.getSignature();
  62. MethodSignature msig = (MethodSignature) sig;
  63. return getClass(jp).getMethod(msig.getName(), msig.getParameterTypes());
  64. }
  65. private Class<? extends Object> getClass(JoinPoint jp)
  66. throws NoSuchMethodException {
  67. return jp.getTarget().getClass();
  68. }
  69. /**
  70. * 查询支付结构参数检查
  71. *
  72. * @param payId
  73. */
  74. private void searchParamCheck(String payId) {
  75. if (payId.trim().equals("")) {
  76. throw new IllegalArgumentException("payId is empty");
  77. }
  78. }
  79. public DBRouter getdBRouter() {
  80. return dBRouter;
  81. }
  82. public void setdBRouter(DBRouter dBRouter) {
  83. this.dBRouter = dBRouter;
  84. }
  85. }
RouterSet.java  主要是 配置在spring-config-datasource-dbcp.xml中 存储库的数量,表的数量,库表相关信息
  1. package com.sub.dt.dbRouting.bean;
  2. import java.util.List;
  3. /**
  4. * @Description
  5. * @Autohr supers【weChat:13031016567】
  6. */
  7. public class RouterSet {
  8. /**根据字符串*/
  9. public final static int RULE_TYPE_STR=3;
  10. public final static int ROUTER_TYPE_DB=0;
  11. public final static int ROUTER_TYPE_TABLE =1;
  12. public final static int ROUTER_TYPE_DBANDTABLE=2;
  13. /**数据库表的逻辑KEY,与数据源MAP配置中的key一致*/
  14. private List<String> dbKeyArray;
  15. /**数据库数量*/
  16. private int dbNumber;
  17. /**数据表数量*/
  18. private int tableNumber;
  19. /**数据表index样式*/
  20. private String tableIndexStyle;
  21. /**Id开始*/
  22. private String routeFieldStart;
  23. /**Id结束*/
  24. private String routeFieldEnd;
  25. /**规则类型*/
  26. private int ruleType;
  27. /**路由类型类型*/
  28. private int routeType;
  29. public static int getRULE_TYPE_STR() {
  30. return RULE_TYPE_STR;
  31. }
  32. public static int getROUTER_TYPE_DB() {
  33. return ROUTER_TYPE_DB;
  34. }
  35. public static int getROUTER_TYPE_TABLE() {
  36. return ROUTER_TYPE_TABLE;
  37. }
  38. public static int getROUTER_TYPE_DBANDTABLE() {
  39. return ROUTER_TYPE_DBANDTABLE;
  40. }
  41. public List<String> getDbKeyArray() {
  42. return dbKeyArray;
  43. }
  44. public void setDbKeyArray(List<String> dbKeyArray) {
  45. this.dbKeyArray = dbKeyArray;
  46. }
  47. public int getDbNumber() {
  48. return dbNumber;
  49. }
  50. public void setDbNumber(int dbNumber) {
  51. this.dbNumber = dbNumber;
  52. }
  53. public int getTableNumber() {
  54. return tableNumber;
  55. }
  56. public void setTableNumber(int tableNumber) {
  57. this.tableNumber = tableNumber;
  58. }
  59. public String getTableIndexStyle() {
  60. return tableIndexStyle;
  61. }
  62. public void setTableIndexStyle(String tableIndexStyle) {
  63. this.tableIndexStyle = tableIndexStyle;
  64. }
  65. public String getRouteFieldStart() {
  66. return routeFieldStart;
  67. }
  68. public void setRouteFieldStart(String routeFieldStart) {
  69. this.routeFieldStart = routeFieldStart;
  70. }
  71. public String getRouteFieldEnd() {
  72. return routeFieldEnd;
  73. }
  74. public void setRouteFieldEnd(String routeFieldEnd) {
  75. this.routeFieldEnd = routeFieldEnd;
  76. }
  77. public int getRuleType() {
  78. return ruleType;
  79. }
  80. public void setRuleType(int ruleType) {
  81. this.ruleType = ruleType;
  82. }
  83. public int getRouteType() {
  84. return routeType;
  85. }
  86. public void setRouteType(int routeType) {
  87. this.routeType = routeType;
  88. }
  89. }


DBRouterImpl.java  getDbKey方法根据userNum定位库表算法
  1. package com.sub.dt.dbRouting.router;
  2. import com.sub.dt.dbRouting.DBRouter;
  3. import com.sub.dt.dbRouting.DbContextHolder;
  4. import com.sub.dt.dbRouting.annotation.RouterConstants;
  5. import com.sub.dt.dbRouting.bean.RouterSet;
  6. import org.apache.commons.lang.StringUtils;
  7. import org.slf4j.Logger;
  8. import org.slf4j.LoggerFactory;
  9. import java.text.DecimalFormat;
  10. import java.util.List;
  11. /**
  12. * @Description 根据指定变量动态切 库和表
  13. * @Autohr supers【weChat:13031016567】
  14. */
  15. public class DBRouterImpl implements DBRouter {
  16. private static final Logger log = LoggerFactory.getLogger(DBRouterImpl.class);
  17. /**
  18. * 配置列表
  19. */
  20. private List<RouterSet> routerSetList;
  21. @Override
  22. public String doRoute(String fieldId) {
  23. if (StringUtils.isEmpty(fieldId)) {
  24. throw new IllegalArgumentException("dbsCount and tablesCount must be both positive!");
  25. }
  26. int routeFieldInt = RouterUtils.getResourceCode(fieldId);
  27. String dbKey = getDbKey(routerSetList, routeFieldInt);
  28. return dbKey;
  29. }
  30. @Override
  31. public String doRouteByResource(String resourceCode) {
  32. if (StringUtils.isEmpty(resourceCode)) {
  33. throw new IllegalArgumentException("dbsCount and tablesCount must be both positive!");
  34. }
  35. int routeFieldInt = Integer.valueOf(resourceCode);
  36. String dbKey = getDbKey(routerSetList, routeFieldInt);
  37. return dbKey;
  38. }
  39. /**
  40. * @Description 根据数据字段来判断属于哪个段的规则,获得数据库key
  41. * @Autohr supers【weChat:13031016567】
  42. */
  43. private String getDbKey(List<RouterSet> routerSets, int routeFieldInt) {
  44. RouterSet routerSet = null;
  45. if (routerSets == null || routerSets.size() <= 0) {
  46. throw new IllegalArgumentException("dbsCount and tablesCount must be both positive!");
  47. }
  48. String dbKey = null;
  49. for (RouterSet item : routerSets) {
  50. if (item.getRuleType() == routerSet.RULE_TYPE_STR) {
  51. routerSet = item;
  52. if (routerSet.getDbKeyArray() != null && routerSet.getDbNumber() != 0) {
  53. long dbIndex = 0;
  54. long tbIndex = 0;
  55. //默认按照分库进行计算
  56. long mode = routerSet.getDbNumber();
  57. //如果是按照分库分表的话,计算
  58. if (item.getRouteType() == RouterSet.ROUTER_TYPE_DBANDTABLE && item.getTableNumber() != 0) {
  59. mode = routerSet.getDbNumber() * item.getTableNumber();
  60. dbIndex = routeFieldInt % mode / item.getTableNumber();
  61. tbIndex = routeFieldInt % item.getTableNumber();
  62. String tableIndex = getFormateTableIndex(item.getTableIndexStyle(), tbIndex);
  63. DbContextHolder.setTableIndex(tableIndex);
  64. } else if (item.getRouteType() == RouterSet.ROUTER_TYPE_DB) {
  65. mode = routerSet.getDbNumber();
  66. dbIndex = routeFieldInt % mode;
  67. } else if (item.getRouteType() == RouterSet.ROUTER_TYPE_TABLE) {
  68. tbIndex = routeFieldInt % item.getTableNumber();
  69. String tableIndex = getFormateTableIndex(item.getTableIndexStyle(), tbIndex);
  70. DbContextHolder.setTableIndex(tableIndex);
  71. }
  72. dbKey = routerSet.getDbKeyArray().get(Long.valueOf(dbIndex).intValue());
  73. log.debug("getDbKey resource:{}------->dbkey:{},tableIndex:{},", new Object[]{routeFieldInt, dbKey, tbIndex});
  74. DbContextHolder.setDbKey(dbKey);
  75. }
  76. break;
  77. }
  78. }
  79. return dbKey;
  80. }
  81. /**
  82. * @Description 此方法是将例如+++0000根式的字符串替换成传参数字例如44 变成+++0044
  83. * @Autohr supers【weChat:13031016567】
  84. */
  85. private static String getFormateTableIndex(String style, long tbIndex) {
  86. String tableIndex = null;
  87. DecimalFormat df = new DecimalFormat();
  88. if (StringUtils.isEmpty(style)) {
  89. style = RouterConstants.ROUTER_TABLE_SUFFIX_DEFAULT;//在格式后添加诸如单位等字符
  90. }
  91. df.applyPattern(style);
  92. tableIndex = df.format(tbIndex);
  93. return tableIndex;
  94. }
  95. public List<RouterSet> getRouterSetList() {
  96. return routerSetList;
  97. }
  98. public void setRouterSetList(List<RouterSet> routerSetList) {
  99. this.routerSetList = routerSetList;
  100. }
  101. }

spring-mvc.xml这个很简单了 就是前段与后端controller层的结合,不多说.

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans
  6. http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
  7. http://www.springframework.org/schema/context
  8. http://www.springframework.org/schema/context/spring-context-3.1.xsd">
  9. <!-- 自动扫描该包,使SpringMVC认为包下用了@controller注解的类是控制器 -->
  10. <context:component-scan base-package="com.sub.dt.controller"/>
  11. <!--避免IE执行AJAX时,返回JSON出现下载文件 -->
  12. <bean id="mappingJacksonHttpMessageConverter"
  13. class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
  14. <property name="supportedMediaTypes">
  15. <list>
  16. <value>text/html;charset=UTF-8</value>
  17. </list>
  18. </property>
  19. </bean>
  20. <!-- 启动SpringMVC的注解功能,完成请求和注解POJO的映射 -->
  21. <bean
  22. class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
  23. <property name="messageConverters">
  24. <list>
  25. <ref bean="mappingJacksonHttpMessageConverter"/>
  26. <!-- JSON转换器 -->
  27. </list>
  28. </property>
  29. </bean>
  30. <!-- 定义跳转的文件的前后缀 ,视图模式配置-->
  31. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  32. <!-- 这里的配置我的理解是自动给后面action的方法return的字符串加上前缀和后缀,变成一个 可用的url地址 -->
  33. <property name="prefix" value="/WEB-INF/jsp/"/>
  34. <property name="suffix" value=".jsp"/>
  35. </bean>
  36. <!-- 配置文件上传,如果没有使用文件上传可以不用配置,当然如果不配,那么配置文件中也不必引入上传组件包 -->
  37. <bean id="multipartResolver"
  38. class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
  39. <!-- 默认编码 -->
  40. <property name="defaultEncoding" value="utf-8"/>
  41. <!-- 文件大小最大值 -->
  42. <property name="maxUploadSize" value="10485760000"/>
  43. <!-- 内存中的最大值 -->
  44. <property name="maxInMemorySize" value="40960"/>
  45. </bean>
  46. </beans>

web.xml配置

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xmlns="http://java.sun.com/xml/ns/javaee"
  4. xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  5. version="3.0">
  6. <display-name>Archetype Created Web Application</display-name>
  7. <!-- Spring和mybatis的配置文件 -->
  8. <context-param>
  9. <param-name>contextConfigLocation</param-name>
  10. <param-value>classpath:spring-config.xml</param-value>
  11. </context-param>
  12. <!-- 编码过滤器 -->
  13. <filter>
  14. <filter-name>encodingFilter</filter-name>
  15. <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  16. <async-supported>true</async-supported>
  17. <init-param>
  18. <param-name>encoding</param-name>
  19. <param-value>UTF-8</param-value>
  20. </init-param>
  21. </filter>
  22. <filter-mapping>
  23. <filter-name>encodingFilter</filter-name>
  24. <url-pattern>/*</url-pattern>
  25. </filter-mapping>
  26. <!-- Spring监听器 -->
  27. <listener>
  28. <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  29. </listener>
  30. <!-- 防止Spring内存溢出监听器 -->
  31. <listener>
  32. <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
  33. </listener>
  34. <!-- Spring MVC servlet -->
  35. <servlet>
  36. <servlet-name>SpringMVC</servlet-name>
  37. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  38. <init-param>
  39. <param-name>contextConfigLocation</param-name>
  40. <param-value>classpath:spring-mvc.xml</param-value>
  41. </init-param>
  42. <load-on-startup>1</load-on-startup>
  43. <async-supported>true</async-supported>
  44. </servlet>
  45. <servlet-mapping>
  46. <servlet-name>SpringMVC</servlet-name>
  47. <!-- 此处可以可以配置成*.do,对应struts的后缀习惯 -->
  48. <url-pattern>/</url-pattern>
  49. </servlet-mapping>
  50. <welcome-file-list>
  51. <welcome-file>/index.jsp</welcome-file>
  52. </welcome-file-list>
  53. </web-app>

奉上 mysql创建表的sql语句,首先自行创建三个库book_00,book_01,book_02 每个库都执行以下sql即可


  1. /*
  2. Navicat MySQL Data Transfer
  3. Source Server : local
  4. Source Server Version : 50173
  5. Source Host : localhost:3306
  6. Source Database : book_00
  7. Target Server Type : MYSQL
  8. Target Server Version : 50173
  9. File Encoding : 65001
  10. Date: 2017-03-10 09:48:12
  11. */
  12. SET FOREIGN_KEY_CHECKS=0;
  13. -- ----------------------------
  14. -- Table structure for `t_user_0000`
  15. -- ----------------------------
  16. DROP TABLE IF EXISTS `t_user_0000`;
  17. CREATE TABLE `t_user_0000` (
  18. `id` int(11) NOT NULL AUTO_INCREMENT,
  19. `user_num` varchar(64) NOT NULL,
  20. `user_name` varchar(16) NOT NULL,
  21. `password` varchar(64) NOT NULL,
  22. `age` int(4) NOT NULL,
  23. PRIMARY KEY (`id`),
  24. UNIQUE KEY `idx_user_num` (`user_num`)
  25. ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
  26. -- ----------------------------
  27. -- Records of t_user_0000
  28. -- ----------------------------
  29. -- ----------------------------
  30. -- Table structure for `t_user_0001`
  31. -- ----------------------------
  32. DROP TABLE IF EXISTS `t_user_0001`;
  33. CREATE TABLE `t_user_0001` (
  34. `id` int(11) NOT NULL AUTO_INCREMENT,
  35. `user_num` varchar(64) NOT NULL,
  36. `user_name` varchar(16) NOT NULL,
  37. `password` varchar(64) NOT NULL,
  38. `age` int(4) NOT NULL,
  39. PRIMARY KEY (`id`),
  40. UNIQUE KEY `idx_user_num` (`user_num`)
  41. ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
  42. -- ----------------------------
  43. -- Records of t_user_0001
  44. -- ----------------------------
  45. -- ----------------------------
  46. -- Table structure for `t_user_0002`
  47. -- ----------------------------
  48. DROP TABLE IF EXISTS `t_user_0002`;
  49. CREATE TABLE `t_user_0002` (
  50. `id` int(11) NOT NULL AUTO_INCREMENT,
  51. `user_num` varchar(64) NOT NULL,
  52. `user_name` varchar(16) NOT NULL,
  53. `password` varchar(64) NOT NULL,
  54. `age` int(4) NOT NULL,
  55. PRIMARY KEY (`id`),
  56. UNIQUE KEY `idx_user_num` (`user_num`)
  57. ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
  58. -- ----------------------------
  59. -- Records of t_user_0002
  60. -- ----------------------------
  61. -- ----------------------------
  62. -- Table structure for `t_user_0003`
  63. -- ----------------------------
  64. DROP TABLE IF EXISTS `t_user_0003`;
  65. CREATE TABLE `t_user_0003` (
  66. `id` int(11) NOT NULL AUTO_INCREMENT,
  67. `user_num` varchar(64) NOT NULL,
  68. `user_name` varchar(16) NOT NULL,
  69. `password` varchar(64) NOT NULL,
  70. `age` int(4) NOT NULL,
  71. PRIMARY KEY (`id`),
  72. UNIQUE KEY `idx_user_num` (`user_num`)
  73. ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
  74. -- ----------------------------
  75. -- Records of t_user_0003
  76. -- ----------------------------
  77. -- ----------------------------
  78. -- Table structure for `t_user_0004`
  79. -- ----------------------------
  80. DROP TABLE IF EXISTS `t_user_0004`;
  81. CREATE TABLE `t_user_0004` (
  82. `id` int(11) NOT NULL AUTO_INCREMENT,
  83. `user_num` varchar(64) NOT NULL,
  84. `user_name` varchar(16) NOT NULL,
  85. `password` varchar(64) NOT NULL,
  86. `age` int(4) NOT NULL,
  87. PRIMARY KEY (`id`),
  88. UNIQUE KEY `idx_user_num` (`user_num`)
  89. ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
  90. -- ----------------------------
  91. -- Records of t_user_0004

所有代码创建完毕

测试类 TestUserService.java
  1. package com.sub.dt.service;
  2. import com.sub.common.GsonUtils;
  3. import com.sub.dt.dbRouting.DbContextHolder;
  4. import com.sub.dt.pojo.User;
  5. import org.junit.Test;
  6. import org.junit.runner.RunWith;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.test.context.ContextConfiguration;
  9. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
  10. /**
  11. * Created by supers on 2017/3/9.
  12. */
  13. @RunWith(SpringJUnit4ClassRunner.class)
  14. @ContextConfiguration("/spring-config.xml")
  15. public class TestUserService {
  16. @Autowired
  17. private IUserService userService;
  18. /**
  19. * @Description 测试分库分表插入
  20. * @Autohr supers【weChat:13031016567】
  21. */
  22. @Test
  23. public void testInsertUser(){
  24. User user = new User();
  25. user.setUserNum("wergsgdf3243");
  26. user.setUserName("admin");
  27. user.setAge(23);
  28. user.setPassword("adf23");
  29. int re = userService.insertUser(user);
  30. System.out.println(DbContextHolder.getDbKey()+"库 "+DbContextHolder.getTableIndex()+"表 的插入结果:"+GsonUtils.toJson(re));
  31. }
  32. /**
  33. * @Description 测试分库分表删除
  34. * @Autohr supers【weChat:13031016567】
  35. */
  36. @Test
  37. public void testDeleteByuserNum(){
  38. User user = new User();
  39. user.setUserNum("wergsgdf3243");
  40. int re = userService.deleteByuserNum(user);
  41. System.out.println(DbContextHolder.getDbKey()+"库 "+DbContextHolder.getTableIndex()+"表 的删除结果:"+GsonUtils.toJson(re));
  42. }
  43. /**
  44. * @Description 测试分库分表修改
  45. * @Autohr supers【weChat:13031016567】
  46. */
  47. @Test
  48. public void testupdateByUserNum(){
  49. User user = new User();
  50. user.setUserNum("wergsgdf3243");
  51. user.setAge(34);
  52. int re = userService.updateByUserNum(user);
  53. System.out.println(DbContextHolder.getDbKey()+"库 "+DbContextHolder.getTableIndex()+"表 的更新结果:"+GsonUtils.toJson(re));
  54. }
  55. /**
  56. * @Description 测试分库分表查询
  57. * @Autohr supers【weChat:13031016567】
  58. */
  59. @Test
  60. public void testQueryUserByNum(){
  61. User user = new User();
  62. user.setId(1);
  63. user.setUserNum("wergsgdf3243");
  64. User userDb = userService.selectByUserNum(user);
  65. System.out.println(DbContextHolder.getDbKey()+"库 "+DbContextHolder.getTableIndex()+"表 的查询结果:"+GsonUtils.toJson(userDb));
  66. }
  67. }


最后奉上 log4j.properties配置

  1. #定义LOG输出级别
  2. log4j.rootLogger=DEBUG,Console,File
  3. #定义日志输出目的地为控制台
  4. log4j.appender.Console=org.apache.log4j.ConsoleAppender
  5. log4j.appender.Console.Target=System.out
  6. #可以灵活地指定日志输出格式,下面一行是指定具体的格式
  7. log4j.appender.Console.layout = org.apache.log4j.PatternLayout
  8. log4j.appender.Console.layout.ConversionPattern=[%c] - %m%n
  9. #文件大小到达指定尺寸的时候产生一个新的文件
  10. log4j.appender.File = org.apache.log4j.RollingFileAppender
  11. #指定输出目录
  12. log4j.appender.File.File = logs/ssm.log
  13. #定义文件最大大小
  14. log4j.appender.File.MaxFileSize = 10MB
  15. # 输出所以日志,如果换成DEBUG表示输出DEBUG以上级别日志
  16. log4j.appender.File.Threshold = ALL
  17. log4j.appender.File.layout = org.apache.log4j.PatternLayout
  18. log4j.appender.File.layout.ConversionPattern =[%p] [%d{yyyy-MM-dd HH\:mm\:ss}][%c]%m%n


本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
SSM框架整合(IntelliJ IDEA + maven + Spring + SpringMVC + MyBatis)
java ssh maven pom文件
Dubbo与Zookeeper、SpringMVC整合和使用(负载均衡、容错)配置详解,dubbo-admin 下载
REST方式的CXF WebService实现
maven搭建springmvc+spring+mybatis实例
Dubbo学习之简单环境搭建
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服