Mysql分庫分表實例(很詳細)

轉載請註明出處: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;
	}
 
	@Override
	public 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;
	}
 
	@Override
	public 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 中關鍵字 匹配符爲 =的時候,表的路由函數 
     */  
	@Override
    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 的時候,表的路由函數 
     */
	@Override
    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的時候,表的路由函數 
     */  
	@Override
    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;  
    }  
  
}  

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 = root
  
jdbc_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 = root
  
  
validationQuery=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實現了分庫分表操作。

四、溫馨提示

大家可以到鏈接https://download.csdn.net/download/zacry/11827363下載完整的sharding-jdbc分庫分表實例源代碼

下載資源: https://download.csdn.net/download/zacry/11827363

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章