springboot2+JPA集成 sharing-jdbc实现单库分表
Posted 零度anngle
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot2+JPA集成 sharing-jdbc实现单库分表相关的知识,希望对你有一定的参考价值。
1、用户表增长到一定程度,我们假设对user表进行分库操作,user为表的逻辑名,实际表名为user_$0..3,即user_0,user_1,user_2,user_3,
首先创建四张表:
CREATE TABLE `user_0` (
`id` bigint(64) NOT NULL,
`city` varchar(20) NOT NULL,
`name` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `user_1` (
`id` bigint(64) NOT NULL,
`city` varchar(20) NOT NULL,
`name` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `user_2` (
`id` bigint(64) NOT NULL,
`city` varchar(20) NOT NULL,
`name` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `user_3` (
`id` bigint(64) NOT NULL,
`city` varchar(20) NOT NULL,
`name` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2、引入依赖,我需要以下依赖,三个组件+一个mysql连接驱动
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-core</artifactId> <version>4.1.1</version> </dependency> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> <version>4.1.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>
3、基本代码
1、model类:User.java
@Data
@Entity
@Table(name="user")
public class User
@Id
private Long id;
@Column(updatable = false)
private String city;
private String name;
2、dao类:UserRepository.java
package com.zmx.demo.shardingJdbcTest.dao;
import com.zmx.demo.shardingJdbcTest.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface UserRepository extends JpaRepository<User,Long>
List<User> findUserByCity(String city);
List<User> findUserByNameLike(String name);
3、测试类型
@Test
public void testUserRepository()
User user1 = new User();
user1.setId(1L);
user1.setCity("常山");
user1.setName("赵子龙");
userRepository.save(user1);
User user2 = new User();
user2.setId(2L);
user2.setCity("山东");
user2.setName("诸葛亮");
userRepository.save(user2);
User user3 = new User();
user3.setId(3L);
user3.setCity("山西");
user3.setName("黄忠");
userRepository.save(user3);
User user4 = new User();
user4.setId(4L);
user4.setCity("东北");
user4.setName("马超");
userRepository.save(user4);
User user5 = new User();
user5.setId(5L);
user5.setCity("长德");
user5.setName("关云长");
userRepository.save(user5);
User user6 = new User();
user6.setId(6L);
user6.setCity("长德");
user6.setName("张翼德");
userRepository.save(user6);
@Test
public void testUserDao()
// String city = "长德";
// List<User> userList = userRepository.findUserByCity(city);
String keyword = "黄";
List<User> userList = userDao.queryByName(keyword,1,10);
userList.forEach(x -> System.out.println(x.getName()));
4、配置文件:(通过代码也可以看出我们使用city字段对用户进行分表的)
#jpa
logging.level.org.hibernate.SQL=DEBUG
spring.jpa.database=mysql
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=none
#sharing-jdbc-datasource
spring.shardingsphere.datasource.names=db
spring.shardingsphere.datasource.db.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.db.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.db.jdbc-url=jdbc:mysql://host:3306/db?serverTimezone=GMT%2b8&useUnicode=true&autoReconnect=true&characterEncoding=utf-8&generateSimpleParameterMetadata=true
spring.shardingsphere.datasource.db.username=root
spring.shardingsphere.datasource.db.password=XXXXXX
#分表策略
spring.shardingsphere.sharding.tables.user.actual-data-nodes=db.user_$0..3
spring.shardingsphere.sharding.tables.user.table-strategy.standard.sharding-column=city
spring.shardingsphere.sharding.tables.user.table-strategy.standard.precise-algorithm-class-name=com.zmx.demo.shardingJdbcTest.UserSharingAlgorithm
spring.shardingsphere.props.sql.show=true
上面配置之后,我们使用了新的sharing-jdbc-datasource替换了原来的jdbc-datasource,同时配置了User表的分表策略,还有上述配置还应用了一个分表算法:
UserSharingAlgorithm.java,这个是最正规代码,我们要实现sharing-jbdc给我提供的接口:PreciseShardingAlgorithm类,具体实现如下:
package com.zmx.demo.shardingJdbcTest;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import java.util.Collection;
/**
* 分表算法
*/
@Slf4j
public class UserSharingAlgorithm implements PreciseShardingAlgorithm<String>
@Override
public String doSharding(Collection<String> collection, PreciseShardingValue<String> preciseShardingValue)
log.debug("分表算法参数 ,",collection,preciseShardingValue);
int hash = HashUtils.rsHash(String.valueOf(preciseShardingValue.getValue()));
return "user_" + (hash % 4);
其实很简单,就先对city进行rehash,然后取模,四张表就是除4,Hash算法大家可以自行google,我也提供一个,以免大家阅读不顺畅,如下:
/**
* RS算法hash
* @param str 字符串
* @return hash值
*/
public static int rsHash(String str)
int b = 378551;
int a = 63689;
int hash = 0;
for (int i = 0; i < str.length(); i++)
hash = hash * a + str.charAt(i);
a = a * b;
return hash & 0x7FFFFFFF;
一切进本完成,运行测试:
可以看到数据被分别插入到不同表中,相同city的数据被放到了同一张表中。
以上是关于springboot2+JPA集成 sharing-jdbc实现单库分表的主要内容,如果未能解决你的问题,请参考以下文章
SpringBoot2.0 基础案例(09):集成JPA持久层框架,简化数据库操作
SpringBoot 2.1.1.RELEASE 集成JPA
springspringboot使用jpa集成elasticsearch7.0