要在SpringBoot项目中实现分表操作,本文使用的是ShardingSphere+JPA+Druid实现。过程中出现问题记录一下。
- 准备MySQL数据库表
这里准备的是一张主表test_cost,两张从表test_cost_0和test_cost_1,结构需要相同,主表只是声明了表结构,供后端框架提供映射关系,不存储数据,从表是真正存储数据的表。
- 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<!-- Spring Boot Starter Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.6.0</version>
<scope>test</scope>
</dependency>
<!-- ShardingSphere -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-crypto</artifactId>
<version>5.7.8</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.18</version>
</dependency>
<!-- Druid数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
- 配置文件
server:
port: 8080
spring:
jpa:
properties:
hibernate:
hbm2ddl:
auto: update
dialect: org.hibernate.dialect.MySQL5Dialect
show_sql: true
ddl-auto: create-drop
shardingsphere:
datasource:
names: books # 数据库名称
books:
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/books?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
username: root
password: 980828
rules:
sharding:
sharding-algorithms: #分片算法配置
table-inline:
type: INLINE
props:
algorithm-expression: test_cost_$->{ id % 2 }
key-generators: #主键生成策略
snowflake:
type: SNOWFLAKE
props:
worker-id: 1
tables: #分表策略
test_cost: # 主表名称
actual-data-nodes: books.test_cost_$->{0..1}
table-strategy:
standard:
sharding-column: id
sharding-algorithm-name: table-inline
props:
sql-show: true
这里的分片算法是根据id字段能否被2整除来分,分到两张从表中。
- Repository
@Repository
public interface TestRepository extends JpaRepository<TestEntity, Long> {
}
- 实体类
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
@Table(name = "test_cost")
public class TestEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
private String gender;
private String country;
private BigDecimal cost;
}
在配置文件中配置了主键生成策略和分片算法,此处@GeneratedValue不能选IDENTITY,要选AUTO,由jpa自动选择。@Table的值为主表的表名。
- 遇见问题
项目启动失败,出现了下图所示的异常:
从sharding官网的FAQ中发现如下解释:
解决方案有两个:
- 去掉druid-spring-boot-starter,直接使用druid-xxx.jar来替代,这就不会出现两个数据源冲突的问题
- 仍然使用druid-spring-boot-starter,但是在springboot的启动类上exclude掉DruidDataSourceAutoConfigure这个类,忽略druid连接池的默认数据源配置(@SpringBootApplication(exclude = {DruidDataSourceAutoConfigure.class}))
这里采用的是第二种方式:
@SpringBootApplication(exclude = {DruidDataSourceAutoConfigure.class})
public class SpringbootRedisApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootRedisApplication.class, args);
}
}
-
启动项目,报错:java.sql.SQLException: url not set
原因是配置文件的数据源处的数据库URL的键应为“url”而不是“jdbc-url”!!!(3中提供的是正确的配置)
改成url后,重新启动,运行正常。 -
运行结果
成功按照分片算法插入到对应的分表中。