sharding-jdbc之——分库分表实例
转载请注明出处:http://blog.csdn.net/l1028386804/article/details/79368021
一、概述
之前,我们介绍了利用Mycat进行分库分表操作,Mycat分表操作是利用分库来进行的,单个库中的分表操作可结合MySQL的分区进行,这也是Mycat官方提倡的方式。那么,如何利用Mycat真正实现数据库的分库分表,可以私信我。今天,我们来看看sharding-jdbc,sharding-jdbc也是一款分库分表的“中间件”,不过,它并不向Mycat那样作为一个真正的中间件,它是一款以jar包的形式整合到业务中的插件,这就决定了它是轻量级的,用法也是十分简单的。
二、分库分表实战
接下来,我们就利用sharding-jdbc进行数据库的分库分表操作。
1、创建数据库
首先我们创建相应的数据库
create database sharding_0;
create database sharding_1;
这样我们就创建了两个数据库sharding_0和sharding_1;
接下来我们在两个库中创建相应的数据表,在两个库中分别进行如下SQL:
SET FOREIGN_KEY_CHECKS=0;-- ----------------------------
-- Table structure for t_student_00
-- ----------------------------
DROP TABLE IF EXISTS `t_student_00`;
CREATE TABLE `t_student_00` (`id` int(11) NOT NULL AUTO_INCREMENT,`student_id` int(11) NOT NULL,`name` varchar(255) NOT NULL,`age` int(11) NOT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- ----------------------------
-- Table structure for t_student_01
-- ----------------------------
DROP TABLE IF EXISTS `t_student_01`;
CREATE TABLE `t_student_01` (`id` int(11) NOT NULL AUTO_INCREMENT,`student_id` int(11) NOT NULL,`name` varchar(255) NOT NULL,`age` int(11) NOT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;-- ----------------------------
-- Table structure for t_user_00
-- ----------------------------
DROP TABLE IF EXISTS `t_user_00`;
CREATE TABLE `t_user_00` (`id` int(11) NOT NULL AUTO_INCREMENT,`user_id` int(11) NOT NULL,`name` varchar(255) NOT NULL,`age` int(11) NOT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- ----------------------------
-- Table structure for t_user_01
-- ----------------------------
DROP TABLE IF EXISTS `t_user_01`;
CREATE TABLE `t_user_01` (`id` int(11) NOT NULL AUTO_INCREMENT,`user_id` int(11) NOT NULL,`name` varchar(255) NOT NULL,`age` int(11) NOT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;-- ----------------------------
-- Table structure for t_user_02
-- ----------------------------
DROP TABLE IF EXISTS `t_user_02`;
CREATE TABLE `t_user_02` (`id` int(11) NOT NULL AUTO_INCREMENT,`user_id` int(11) NOT NULL,`name` varchar(255) NOT NULL,`age` int(11) NOT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
这样,我们的数据库就准备好了。
2、创建项目
接下来,我们就创建一个Maven项目,项目结构如下:
3、配置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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.lyz</groupId> <artifactId>sharding-jdbc-mybatis</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>sharding-jdbc-mybatis</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <spring.version>4.1.0.RELEASE</spring.version><mybatis.version>3.2.4</mybatis.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> </dependency> <dependency> <groupId>com.dangdang</groupId> <artifactId>sharding-jdbc-core</artifactId> <version>1.0.0</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${mybatis.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.28</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.16</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.5</version> </dependency> </dependencies>
</project>
4、创建数据库映射类
这里,我们创建两个数据库映射类:User类和Student类。
4-1、User类
package com.lyz.sharding.entity;import java.io.Serializable;/*** 用户类* @author liuyazhuang**/
public class User implements Serializable {private static final long serialVersionUID = 1L;private Integer id;private Integer userId;private String name;private Integer age;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public Integer getUserId() {return userId;}public void setUserId(Integer userId) {this.userId = userId;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "User [id=" + id + ", userId=" + userId + ", name=" + name + ", age=" + age + "]";}}
4-2、Student类
package com.lyz.sharding.entity;import java.io.Serializable;/*** 学生类* @author liuyazhuang**/
public class Student implements Serializable {private static final long serialVersionUID = 8920597824668331209L;private Integer id;private Integer studentId;private String name;private Integer age;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public Integer getStudentId() {return studentId;}public void setStudentId(Integer studentId) {this.studentId = studentId;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "Student [id=" + id + ", studentId=" + studentId + ", name=" + name + ", age=" + age + "]";}}
5、创建Mapper类
5-1、UserMapper类
package com.lyz.sharding.mapper;import java.util.List;
import com.lyz.sharding.entity.User; /*** 处理用户的数据操作接口* @author liuyazhuang**/
public interface UserMapper { Integer insert(User u); List<User> findAll(); List<User> findByUserIds(List<Integer> userIds); }
5-2、StudentMapper类
package com.lyz.sharding.mapper;import java.util.List;
import com.lyz.sharding.entity.Student;/*** 处理学生的数据操作接口* @author liuyazhuang**/
public interface StudentMapper { Integer insert(Student s); List<Student> findAll(); List<Student> findByStudentIds(List<Integer> studentIds); }
6、创建service类
6-1、UserService类
package com.lyz.sharding.service; import java.util.List;
import com.lyz.sharding.entity.User;/*** 处理用户的Service* @author liuyazhuang**/
public interface UserService { public boolean insert(User u); public List<User> findAll(); public List<User> findByUserIds(List<Integer> ids); public void transactionTestSucess(); public void transactionTestFailure() throws IllegalAccessException; }
6-2、StudentService类
package com.lyz.sharding.service;import com.lyz.sharding.entity.Student;/*** 处理学生的service* @author liuyazhuang**/
public interface StudentService { boolean insert(Student student); }
7、创建service的实现类
7-1、UserServiceImpl类
package com.lyz.sharding.service.impl;import java.util.List;import javax.annotation.Resource;import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;import com.lyz.sharding.entity.Student;
import com.lyz.sharding.entity.User;
import com.lyz.sharding.mapper.StudentMapper;
import com.lyz.sharding.mapper.UserMapper;
import com.lyz.sharding.service.UserService; @Service
@Transactional
public class UserServiceImpl implements UserService { @Resource public UserMapper userMapper; @Resource public StudentMapper studentMapper; public boolean insert(User u) { return userMapper.insert(u) > 0 ? true :false; } public List<User> findAll() { return userMapper.findAll(); } public List<User> findByUserIds(List<Integer> ids) { return userMapper.findByUserIds(ids); } @Transactional(propagation=Propagation.REQUIRED) public void transactionTestSucess() { User u = new User(); u.setUserId(13); u.setAge(25); u.setName("war3 1.27"); userMapper.insert(u); Student student = new Student(); student.setStudentId(21); student.setAge(21); student.setName("hehe"); studentMapper.insert(student); } @Transactional(propagation=Propagation.REQUIRED) public void transactionTestFailure() throws IllegalAccessException { User u = new User(); u.setUserId(13); u.setAge(25); u.setName("war3 1.27 good"); userMapper.insert(u); Student student = new Student(); student.setStudentId(21); student.setAge(21); student.setName("hehe1"); studentMapper.insert(student); throw new IllegalAccessException(); } }
7-2、StudentServiceImpl类
package com.lyz.sharding.service.impl;
import javax.annotation.Resource;import org.springframework.stereotype.Service;import com.lyz.sharding.entity.Student;
import com.lyz.sharding.mapper.StudentMapper;
import com.lyz.sharding.service.StudentService;@Service
public class StudentServiceImpl implements StudentService{ @Resource public StudentMapper studentMapper; public boolean insert(Student student) { return studentMapper.insert(student) > 0 ? true : false; } }
8、创建分库逻辑
8-1、User分库逻辑UserSingleKeyDatabaseShardingAlgorithm类
package com.lyz.sharding.algorithm; import java.util.Collection;
import java.util.LinkedHashSet; import com.dangdang.ddframe.rdb.sharding.api.ShardingValue;
import com.dangdang.ddframe.rdb.sharding.api.strategy.database.SingleKeyDatabaseShardingAlgorithm;
import com.google.common.collect.Range; /** * user表分库的逻辑函数 * @author liuyazhuang* */
public class UserSingleKeyDatabaseShardingAlgorithm implements SingleKeyDatabaseShardingAlgorithm<Integer>{ /** * sql 中关键字 匹配符为 =的时候,表的路由函数 */ public String doEqualSharding(Collection<String> availableTargetNames, ShardingValue<Integer> shardingValue) { for (String each : availableTargetNames) { if (each.endsWith(shardingValue.getValue() % 2 + "")) { return each; } } throw new IllegalArgumentException(); } /** * sql 中关键字 匹配符为 in 的时候,表的路由函数 */ public Collection<String> doInSharding(Collection<String> availableTargetNames, ShardingValue<Integer> shardingValue) { Collection<String> result = new LinkedHashSet<String>(availableTargetNames.size()); for (Integer value : shardingValue.getValues()) { for (String tableName : availableTargetNames) { if (tableName.endsWith(value % 2 + "")) { result.add(tableName); } } } return result; } /** * sql 中关键字 匹配符为 between的时候,表的路由函数 */ public Collection<String> doBetweenSharding(Collection<String> availableTargetNames, ShardingValue<Integer> shardingValue) { Collection<String> result = new LinkedHashSet<String>(availableTargetNames.size()); Range<Integer> range = (Range<Integer>) shardingValue.getValueRange(); for (Integer i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) { for (String each : availableTargetNames) { if (each.endsWith(i % 2 + "")) { result.add(each); } } } return result; } }
8-2、Student分库逻辑StudentSingleKeyDatabaseShardingAlgorithm
package com.lyz.sharding.algorithm;
import java.util.Collection;
import java.util.LinkedHashSet; import com.dangdang.ddframe.rdb.sharding.api.ShardingValue;
import com.dangdang.ddframe.rdb.sharding.api.strategy.database.SingleKeyDatabaseShardingAlgorithm;
import com.google.common.collect.Range; /** * user表分库的逻辑函数 * @author liuyazhuang * */
public class StudentSingleKeyDatabaseShardingAlgorithm implements SingleKeyDatabaseShardingAlgorithm<Integer>{ /** * sql 中关键字 匹配符为 =的时候,表的路由函数 */ @Overridepublic String doEqualSharding(Collection<String> availableTargetNames, ShardingValue<Integer> shardingValue) { for (String each : availableTargetNames) { if (each.endsWith(shardingValue.getValue() % 2 + "")) { return each; } } throw new IllegalArgumentException(); } /** * sql 中关键字 匹配符为 in 的时候,表的路由函数 */@Overridepublic Collection<String> doInSharding(Collection<String> availableTargetNames, ShardingValue<Integer> shardingValue) { Collection<String> result = new LinkedHashSet<String>(availableTargetNames.size()); for (Integer value : shardingValue.getValues()) { for (String tableName : availableTargetNames) { if (tableName.endsWith(value % 2 + "")) { result.add(tableName); } } } return result; } /** * sql 中关键字 匹配符为 between的时候,表的路由函数 */ @Overridepublic Collection<String> doBetweenSharding(Collection<String> availableTargetNames, ShardingValue<Integer> shardingValue) { Collection<String> result = new LinkedHashSet<String>(availableTargetNames.size()); Range<Integer> range = (Range<Integer>) shardingValue.getValueRange(); for (Integer i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) { for (String each : availableTargetNames) { if (each.endsWith(i % 2 + "")) { result.add(each); } } } return result; } }
9、创建分表逻辑
9-1、User分表逻辑UserSingleKeyTableShardingAlgorithm
package com.lyz.sharding.algorithm; import java.util.Collection;
import java.util.LinkedHashSet; import com.dangdang.ddframe.rdb.sharding.api.ShardingValue;
import com.dangdang.ddframe.rdb.sharding.api.strategy.table.SingleKeyTableShardingAlgorithm;
import com.google.common.collect.Range;
/** * 因为t_student实际表在每个库中只有3个,所以 %3 * @author iuyazhuang* */
public class UserSingleKeyTableShardingAlgorithm implements SingleKeyTableShardingAlgorithm<Integer>{ /** * sql 中 = 操作时,table的映射 */ public String doEqualSharding(Collection<String> tableNames, ShardingValue<Integer> shardingValue) { for (String each : tableNames) { if (each.endsWith(("0".concat(String.valueOf(shardingValue.getValue() % 3))))) { return each; } } throw new IllegalArgumentException(); } /** * sql 中 in 操作时,table的映射 */ public Collection<String> doInSharding(Collection<String> tableNames, ShardingValue<Integer> shardingValue) { Collection<String> result = new LinkedHashSet<String>(tableNames.size()); for (Integer value : shardingValue.getValues()) { for (String tableName : tableNames) { if (tableName.endsWith(("0".concat(String.valueOf(value % 3))))) { result.add(tableName); } } } return result; } /** * sql 中 between 操作时,table的映射 */ public Collection<String> doBetweenSharding(Collection<String> tableNames, ShardingValue<Integer> shardingValue) { Collection<String> result = new LinkedHashSet<String>(tableNames.size()); Range<Integer> range = (Range<Integer>) shardingValue.getValueRange(); for (Integer i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) { for (String each : tableNames) { if (each.endsWith(("0".concat(String.valueOf(i % 3))))) { result.add(each); } } } return result; } }
9-2、创建Student分表逻辑StudentSingleKeyTableShardingAlgorithm
package com.lyz.sharding.algorithm;import java.util.Collection;
import java.util.LinkedHashSet; import com.dangdang.ddframe.rdb.sharding.api.ShardingValue;
import com.dangdang.ddframe.rdb.sharding.api.strategy.table.SingleKeyTableShardingAlgorithm;
import com.google.common.collect.Range; /** * 因为t_student实际表在每个库中只有2个,所以 %2 * @author iuyazhuang* */
public class StudentSingleKeyTableShardingAlgorithm implements SingleKeyTableShardingAlgorithm<Integer>{ /** * sql 中 = 操作时,table的映射 */ public String doEqualSharding(Collection<String> tableNames, ShardingValue<Integer> shardingValue) { for (String each : tableNames) { if (each.endsWith("0".concat(String.valueOf(shardingValue.getValue() % 2)))) { return each; } } throw new IllegalArgumentException(); } /** * sql 中 in 操作时,table的映射 */ public Collection<String> doInSharding(Collection<String> tableNames, ShardingValue<Integer> shardingValue) { Collection<String> result = new LinkedHashSet<String>(tableNames.size()); for (Integer value : shardingValue.getValues()) { for (String tableName : tableNames) { if (tableName.endsWith("0".concat(String.valueOf(value % 2)))) { result.add(tableName); } } } return result; } /** * sql 中 between 操作时,table的映射 */ public Collection<String> doBetweenSharding(Collection<String> tableNames, ShardingValue<Integer> shardingValue) { Collection<String> result = new LinkedHashSet<String>(tableNames.size()); Range<Integer> range = (Range<Integer>) shardingValue.getValueRange(); for (Integer i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) { for (String each : tableNames) { if (each.endsWith("0".concat(String.valueOf(i % 2)))) { result.add(each); } } } return result; } }
10、创建Mapper.xml
10-1、创建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.lyz.sharding.mapper.UserMapper" > <resultMap id="resultMap" type="com.lyz.sharding.entity.User" > <id column="id" property="id" jdbcType="INTEGER" /> <result column="user_id" property="userId" jdbcType="INTEGER" /> <result column="name" property="name" jdbcType="VARCHAR" /> <result column="age" property="age" jdbcType="INTEGER" /> </resultMap> <insert id="insert"> insert into t_user (user_id,name,age) values (#{userId},#{name},#{age}) </insert> <select id="findAll" resultMap="resultMap"> select <include refid="columnsName"/> from t_user </select> <select id="findByUserIds" resultMap="resultMap"> select <include refid="columnsName"/> from t_user where user_id in ( <foreach collection="list" item="item" separator=","> #{item} </foreach> ) </select> <sql id="columnsName"> id,user_id,name,age </sql>
</mapper>
10-2、创建StudentMapper.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.lyz.sharding.mapper.StudentMapper" > <resultMap id="resultMap" type="com.lyz.sharding.entity.Student" > <id column="id" property="id" jdbcType="INTEGER" /> <result column="student_id" property="studentId" jdbcType="INTEGER" /> <result column="name" property="name" jdbcType="VARCHAR" /> <result column="age" property="age" jdbcType="INTEGER" /> </resultMap> <insert id="insert"> insert into t_student (student_id,name,age) values (#{studentId},#{name},#{age}) </insert> <select id="findAll" resultMap="resultMap"> select <include refid="columnsName"/> from t_student </select> <select id="findByStudentIds" resultMap="resultMap"> select <include refid="columnsName"/> from t_student where student_id in ( <foreach collection="list" item="item" separator=","> #{item} </foreach> ) </select> <sql id="columnsName"> id,student_id,name,age </sql>
</mapper>
11、创建jdbc_dev.properties
jdbc_driver0 = com.mysql.jdbc.Driver
jdbc_url0 = jdbc:mysql://localhost:3306/sharding_0?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true
jdbc_username0 = root
jdbc_password0 = rootjdbc_driver1 = com.mysql.jdbc.Driver
jdbc_url1 = jdbc:mysql://localhost:3306/sharding_1?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true
jdbc_username1 = root
jdbc_password1 = rootvalidationQuery=SELECT 1
12、创建spring配置文件
12-1、spring-database.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" xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="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://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:config/resource/jdbc_dev.properties</value> </list> </property> </bean> <bean name="sharding_0" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="url" value="${jdbc_url0}" /> <property name="username" value="${jdbc_username0}" /> <property name="password" value="${jdbc_password0}" />
<!-- <property name="driverClass" value="${jdbc_driver0}" /> --> <!-- 初始化连接大小 --> <property name="initialSize" value="0" /> <!-- 连接池最大使用连接数量 --> <property name="maxActive" value="20" /> <!-- 连接池最小空闲 --> <property name="minIdle" value="0" /> <!-- 获取连接最大等待时间 --> <property name="maxWait" value="60000" /> <property name="validationQuery" value="${validationQuery}" /> <property name="testOnBorrow" value="false" /> <property name="testOnReturn" value="false" /> <property name="testWhileIdle" value="true" /> <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="25200000" /> <!-- 打开removeAbandoned功能 --> <property name="removeAbandoned" value="true" /> <!-- 1800秒,也就是30分钟 --> <property name="removeAbandonedTimeout" value="1800" /> <!-- 关闭abanded连接时输出错误日志 --> <property name="logAbandoned" value="true" /> <property name="filters" value="stat" /> </bean> <bean name="sharding_1" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="url" value="${jdbc_url1}" /> <property name="username" value="${jdbc_username1}" /> <property name="password" value="${jdbc_password1}" />
<!-- <property name="driverClass" value="${jdbc_driver1}" /> --> <!-- 初始化连接大小 --> <property name="initialSize" value="0" /> <!-- 连接池最大使用连接数量 --> <property name="maxActive" value="20" /> <!-- 连接池最小空闲 --> <property name="minIdle" value="0" /> <!-- 获取连接最大等待时间 --> <property name="maxWait" value="60000" /> <property name="validationQuery" value="${validationQuery}" /> <property name="testOnBorrow" value="false" /> <property name="testOnReturn" value="false" /> <property name="testWhileIdle" value="true" /> <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="25200000" /> <!-- 打开removeAbandoned功能 --> <property name="removeAbandoned" value="true" /> <!-- 1800秒,也就是30分钟 --> <property name="removeAbandonedTimeout" value="1800" /> <!-- 关闭abanded连接时输出错误日志 --> <property name="logAbandoned" value="true" /> <property name="filters" value="stat" /> </bean> </beans>
12-2、spring-sharding.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" xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="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://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"> <context:component-scan base-package="com.lyz.sharding" /> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.lyz.sharding.mapper"/> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> </bean> <!-- 配置sqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="shardingDataSource"/> <property name="mapperLocations" value="classpath*:config/mapper/*Mapper.xml"/> </bean> <!-- 配置好dataSourceRulue,即对数据源进行管理 --> <bean id="dataSourceRule" class="com.dangdang.ddframe.rdb.sharding.api.rule.DataSourceRule"> <constructor-arg> <map> <entry key="sharding_0" value-ref="sharding_0"/> <entry key="sharding_1" value-ref="sharding_1"/> </map> </constructor-arg> </bean> <!-- 对t_user表的配置,进行分库配置,逻辑表名为t_user,每个库有实际的三张表 --> <bean id="userTableRule" class="com.dangdang.ddframe.rdb.sharding.api.rule.TableRule"> <constructor-arg value="t_user" index="0"/> <constructor-arg index="1"> <list> <value>t_user_00</value> <value>t_user_01</value> <value>t_user_02</value> </list> </constructor-arg> <constructor-arg index="2" ref="dataSourceRule"/> <constructor-arg index="3" ref="userDatabaseShardingStrategy"/> <constructor-arg index="4" ref="userTableShardingStrategy"/> </bean> <!-- t_user分库策略 --> <bean id="userDatabaseShardingStrategy" class="com.dangdang.ddframe.rdb.sharding.api.strategy.database.DatabaseShardingStrategy"> <constructor-arg index="0" value="user_id"/> <constructor-arg index="1"> <bean class="com.lyz.sharding.algorithm.UserSingleKeyDatabaseShardingAlgorithm" /> </constructor-arg> </bean> <!-- t_user 分表策略 --> <bean id="userTableShardingStrategy" class="com.dangdang.ddframe.rdb.sharding.api.strategy.table.TableShardingStrategy"> <constructor-arg index="0" value="user_id"/> <constructor-arg index="1"> <bean class="com.lyz.sharding.algorithm.UserSingleKeyTableShardingAlgorithm" /> </constructor-arg> </bean> <!-- 对t_student表的配置,进行分库配置,逻辑表名为t_student,每个库有实际的三张表 --> <bean id="studentTableRule" class="com.dangdang.ddframe.rdb.sharding.api.rule.TableRule"> <constructor-arg value="t_student" index="0"/> <constructor-arg index="1"> <list> <value>t_student_00</value> <value>t_student_01</value> </list> </constructor-arg> <constructor-arg index="2" ref="dataSourceRule"/> <constructor-arg index="3" ref="studentDatabaseShardingStrategy"/> <constructor-arg index="4" ref="studentTableShardingStrategy"/> </bean> <!-- t_student分库策略 --> <bean id="studentDatabaseShardingStrategy" class="com.dangdang.ddframe.rdb.sharding.api.strategy.database.DatabaseShardingStrategy"> <constructor-arg index="0" value="student_id"/> <constructor-arg index="1"> <bean class="com.lyz.sharding.algorithm.StudentSingleKeyDatabaseShardingAlgorithm" /> </constructor-arg> </bean> <!-- t_student 分表策略 --> <bean id="studentTableShardingStrategy" class="com.dangdang.ddframe.rdb.sharding.api.strategy.table.TableShardingStrategy"> <constructor-arg index="0" value="student_id"/> <constructor-arg index="1"> <bean class="com.lyz.sharding.algorithm.StudentSingleKeyTableShardingAlgorithm" /> </constructor-arg> </bean> <!-- 构成分库分表的规则 传入数据源集合和每个表的分库分表的具体规则 --> <bean id="shardingRule" class="com.dangdang.ddframe.rdb.sharding.api.rule.ShardingRule"> <constructor-arg index="0" ref="dataSourceRule"/> <constructor-arg index="1"> <list> <ref bean="userTableRule"/> <ref bean="studentTableRule"/> </list> </constructor-arg> </bean> <!-- 对datasource进行封装 --> <bean id="shardingDataSource" class="com.dangdang.ddframe.rdb.sharding.api.ShardingDataSource"> <constructor-arg ref="shardingRule"/> </bean> <!-- 事务 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="shardingDataSource" /> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> </beans>
13、创建log4j.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <!-- [控制台STDOUT] --> <appender name="console" class="org.apache.log4j.ConsoleAppender"> <param name="encoding" value="GBK" /> <param name="target" value="System.out" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%-5p %c{2} - %m%n" /> </layout> </appender> <!-- [公共Appender] --> <appender name="DEFAULT-APPENDER" class="org.apache.log4j.DailyRollingFileAppender"> <param name="File" value="logs/common-default.log" /> <param name="Append" value="true" /> <param name="encoding" value="GBK" /> <param name="DatePattern" value="'.'yyyy-MM-dd'.log'" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d %-5p %c{2} - %m%n" /> </layout> </appender> <!-- [错误日志APPENDER] --> <appender name="ERROR-APPENDER" class="org.apache.log4j.DailyRollingFileAppender"> <param name="File" value="logs/common-error.log" /> <param name="Append" value="true" /> <param name="encoding" value="GBK" /> <param name="threshold" value="error" /> <param name="DatePattern" value="'.'yyyy-MM-dd'.log'" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d %-5p %c{2} - %m%n" /> </layout> </appender> <!-- [组件日志APPENDER] --> <appender name="COMPONENT-APPENDER" class="org.apache.log4j.DailyRollingFileAppender"> <param name="File" value="logs/logistics-component.log" /> <param name="Append" value="true" /> <param name="encoding" value="GBK" /> <param name="DatePattern" value="'.'yyyy-MM-dd'.log'" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d %-5p %c{2} - %m%n" /> </layout> </appender> <!-- [组件日志] --> <logger name="LOGISTICS-COMPONENT"> <level value="${loggingLevel}" /> <appender-ref ref="COMPONENT-APPENDER" /> <appender-ref ref="ERROR-APPENDER" /> </logger> <!-- Root Logger --> <root> <level value="${rootLevel}"></level> <appender-ref ref="DEFAULT-APPENDER" /> <appender-ref ref="ERROR-APPENDER" /> <appender-ref ref="console" /> <appender-ref ref="COMPONENT-APPENDER" /> </root>
</log4j:configuration>
14、创建测试类ShardingJdbcMybatisTest
package com.lyz.sharding.test; import java.util.Arrays;
import java.util.List;import javax.annotation.Resource;import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import com.lyz.sharding.entity.Student;
import com.lyz.sharding.entity.User;
import com.lyz.sharding.service.StudentService;
import com.lyz.sharding.service.UserService;/*** 测试分库分表规则* @author liuyazhuang**/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:config/spring/spring-database.xml", "classpath*:config/spring/spring-sharding.xml" })
public class ShardingJdbcMybatisTest { @Resource public UserService userService; @Resource public StudentService studentService; @Test public void testUserInsert() { User u = new User(); u.setUserId(11); u.setAge(25); u.setName("github"); Assert.assertEquals(userService.insert(u), true); } @Test public void testStudentInsert() { Student student = new Student(); student.setStudentId(21); student.setAge(21); student.setName("hehe"); Assert.assertEquals(studentService.insert(student), true); } @Test public void testFindAll(){ List<User> users = userService.findAll(); if(null != users && !users.isEmpty()){ for(User u :users){ System.out.println(u); } } } @Test public void testSQLIN(){ List<User> users = userService.findByUserIds(Arrays.asList(1)); if(null != users && !users.isEmpty()){ for(User u :users){ System.out.println(u); } } } @Test public void testTransactionTestSucess(){ userService.transactionTestSucess(); } @Test(expected = IllegalAccessException.class) public void testTransactionTestFailure() throws IllegalAccessException{ userService.transactionTestFailure(); }
}
三、测试
我们进行ShardingJdbcMybatisTest类,查看数据表数据,即可看到我们的程序利用sharding-jdbc实现了分库分表操作。
四、温馨提示
大家可以到链接http://download.csdn.net/download/l1028386804/10258290下载完整的sharding-jdbc分库分表实例源代码
sharding-jdbc之——分库分表实例相关推荐
- Sharding Sphere ~ Sharding-jdbc分库分表、读写分离
Sharding Sphere 是什么? 1.一套开源的分布式数据库中间件解决方案 2.有三个产品:Sharding-JDBC 和 Sharding-Proxy 3.定位为关系型数据库中间件,合理在分 ...
- sharding jdbc根据年月分表
1.配置Maven依赖 <!--shardingsphere分表策略--> <dependency><groupId>io.shardingsphere</g ...
- sharding-jdbc4.1.1 分库分表后 mysql查询优化(count)
sharding jdbc分库分表之后查询优化 背景 需求 研发历程 1.单线程(sharding jdbc 内置查询机制) 2.多线程(sharding jdbc 内置查询机制) 3.sql调整 结 ...
- 数据库读写分离与分库分表
3.1 读写分离(主要是为了数据库读能力的水平扩展) 3.1.1 读写分离概念 单台mysql实例情况下不能支持短时间内大量的对数据库的读操作,所以会将数据库配置成集群,一个master(主库).多个 ...
- 【数据库与事务系列】分库分表中间件
前面讲了利用mybatis插件进行多数据源切换和分表的方案,但是对业务侵入性较强,当然给予mybatis-plus的对业务侵入性还好,但是支持的策略有限.场景有限. 所以业界诞生了很多分库分表中间件来 ...
- 亿级流量网站架构核心技术之“数据库分库分表策略”
本文节选自<亿级流量网站架构核心技术--跟开涛学搭建高可用高并发系统>一书 张开涛 著 电子工业出版社出版 小编会从留言中选择获赞最多的前五名用户免费送出此书哦!规则见文末. 数据库分库分 ...
- 一文读懂分库分表的技术演进(最佳实践)
每个优秀的程序员和架构师都应该掌握分库分表,这是我的观点. 移动互联网时代,海量的用户每天产生海量的数据,比如: 用户表 订单表 交易流水表 以支付宝用户为例,8亿:微信用户更是10亿.订单表更夸张, ...
- 海量数据的分库分表技术演进,最佳实践
每个优秀的程序员和架构师都应该掌握分库分表,移动互联网时代,海量的用户每天产生海量的数量 用户表 订单表 交易流水表 以支付宝用户为例,8亿:微信用户更是10亿.订单表更夸张,比如美团外卖,每天都是几 ...
- mycat分库分表demo
关于Mycat,它是一个阿里的开源项目,用来解决分库分表的海量数据存储和查询优化,关于它的简介,可以直接参考介绍:Mycat简介. 下面对自己的demo做个记录: 我之前从192.168.68.3克隆 ...
最新文章
- windows优化大师8周年纪念版_《数码宝贝》20周年纪念:当年的八神太一与亚古兽你还记得吗?...
- 配置oracle驱动_Myeclipse中添加Oracle
- img打 webpack_webpack打包html里面img后src为“[object Module]”问题
- AutoLayout bug集合
- 获取android手机的屏幕分辨率 android开发
- 327 区间和的个数
- 你认为已经过时的C语言,是如何影响500万程序员的?...
- 计算机联系函范文,致客户联络函
- java.io.FileNotFoundException:/mnt/sdcard/......(Permission denied)
- Oracle中查看所有的表,用户表,列名,主键,外键
- vfp 打开服务器文件,vfp获取远程服务器时间
- Nxlog 配置总结
- 算法4(一、递归学习)
- MIUI12_Global未知来源安装等待时间patcher
- python除数为0报错_Python3报错-Python入门到精通
- svn提示commit:remains in tree-conflict的解决方法
- 质量与规范,敬我们那些年欠下的技术债
- OpenStack-Placement、nova组件部署
- 解决M1处理器安装PS闪退问题Photoshop 2021 fo mac(支持最新M1芯片处理器款mac)
- 无线充电各种原理方案的比较