sharding-jdbc集成spring+mybatis分表分库
时间:2022-03-15 01:26
maven:
<?xml version="1.0" encoding="UTF-8"?> <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.fulihui.com</groupId> <artifactId>sharding-jdbc-demo</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <spring.version>4.1.3.RELEASE</spring.version> <mybatis.version>3.2.4</mybatis.version> <sharding-jdbc.version>1.3.1</sharding-jdbc.version> </properties> <dependencies> <dependency> <groupId>com.dangdang</groupId> <artifactId>sharding-jdbc-core</artifactId> <version>${sharding-jdbc.version}</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> <exclusion> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.dangdang</groupId> <artifactId>sharding-jdbc-transaction</artifactId> <version>${sharding-jdbc.version}</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> <exclusion> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.dangdang</groupId> <artifactId>sharding-jdbc-config-spring</artifactId> <version>${sharding-jdbc.version}</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> <scope>test</scope> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.10</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> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> <exclusion> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </exclusion> </exclusions> </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> </dependencies> </project>
建表语句:
SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for t_student_0 -- ---------------------------- DROP TABLE IF EXISTS `t_student_0`; CREATE TABLE `t_student_0` ( `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; DROP TABLE IF EXISTS `t_student_1`; CREATE TABLE `t_student_1` ( `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; DROP TABLE IF EXISTS `t_user_0`; CREATE TABLE `t_user_0` ( `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; DROP TABLE IF EXISTS `t_user_1`; CREATE TABLE `t_user_1` ( `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; DROP TABLE IF EXISTS `t_user_2`; CREATE TABLE `t_user_2` ( `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;
spring配置:
<?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:tx="http://www.springframework.org/schema/tx" xmlns:rdb="http://www.dangdang.com/schema/ddframe/rdb" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.dangdang.com/schema/ddframe/rdb http://www.dangdang.com/schema/ddframe/rdb/rdb.xsd"> <context:component-scan base-package="com.fulihui.sharding.jdbc" /> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.fulihui.sharding.jdbc.dal.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> <!-- 路由表、路由库规则配置,可以指定algorithm-class专门自己实现具体的路由规则,也可以使用表达式--> <rdb:strategy id="userDatabaseShardingStrategy" sharding-columns="user_id" algorithm-class="com.fulihui.sharding.jdbc.algorithm.UserDatabaseShardingAlgorithm"/> <rdb:strategy id="userTableShardingStrategy" sharding-columns="user_id" algorithm-class="com.fulihui.sharding.jdbc.algorithm.UserTableShardingAlgorithm"/> <!-- 使用表达式方式 --> <rdb:strategy id="studentDatabaseShardingStrategy" sharding-columns="student_id" algorithm-expression="sharding_${student_id.longValue() % 2}"/> <rdb:strategy id="studentTableShardingStrategy" sharding-columns="student_id" algorithm-expression="t_student_${student_id.longValue() % 2}"/> <rdb:data-source id="shardingDataSource"> <rdb:sharding-rule data-sources="sharding_0,sharding_1"> <rdb:table-rules> <rdb:table-rule logic-table="t_user" actual-tables="sharding_${0..1}.t_user_${0..2}" database-strategy="userDatabaseShardingStrategy" table-strategy="userTableShardingStrategy"/> <rdb:table-rule logic-table="t_student" actual-tables="sharding_${0..1}.t_student_${0..1}" database-strategy="studentDatabaseShardingStrategy" table-strategy="studentTableShardingStrategy"/> </rdb:table-rules> <rdb:default-database-strategy sharding-columns="none" algorithm-class="com.dangdang.ddframe.rdb.sharding.api.strategy.database.NoneDatabaseShardingAlgorithm"/> <rdb:default-table-strategy sharding-columns="none" algorithm-class="com.dangdang.ddframe.rdb.sharding.api.strategy.table.NoneTableShardingAlgorithm"/> </rdb:sharding-rule> <rdb:props> <prop key="metrics.enable">false</prop> </rdb:props> </rdb:data-source> <!-- 事务 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="shardingDataSource" /> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> </beans>
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:property-placeholder location="classpath:config/resource/jdbc_dev.properties" ignore-unresolvable="true"/> <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="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="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>
增、删、改、查接口代码就不贴了。
测试类:
@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() { UserDO u = new UserDO(); u.setUserId(9); u.setAge(25); u.setName("levon"); Assert.assertEquals(userService.insert(u), true); } @Test public void testStudentInsert() { StudentDO StudentDO = new StudentDO(); StudentDO.setStudentId(9); StudentDO.setAge(21); StudentDO.setName("hehe"); Assert.assertEquals(studentService.insert(StudentDO), true); } @Test public void testFindAll(){ List<UserDO> UserDOs = userService.findAll(); if(null != UserDOs && !UserDOs.isEmpty()){ for(UserDO u :UserDOs){ System.out.println(u); } } } @Test public void testSQLIN(){ List<UserDO> UserDOs = userService.findByUserIds(Arrays.asList(12,14,17)); if(null != UserDOs && !UserDOs.isEmpty()){ for(UserDO u :UserDOs){ System.out.println(u); } } } @Test public void testTransactionTestSucess(){ userService.transactionTestSucess(); } @Test(expected = IllegalAccessException.class) public void testTransactionTestFailure() throws IllegalAccessException{ userService.transactionTestFailure(); } }