要在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: 8080spring:jpa:properties:hibernate:hbm2ddl:auto: updatedialect: org.hibernate.dialect.MySQL5Dialectshow_sql: trueddl-auto: create-dropshardingsphere:datasource:names: books # 数据库名称books:driver-class-name: com.mysql.cj.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSourceurl: jdbc:mysql://localhost:3306/books?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTCusername: rootpassword: 980828rules:sharding:sharding-algorithms: #分片算法配置table-inline:type: INLINEprops:algorithm-expression: test_cost_$->{ id % 2 }key-generators: #主键生成策略snowflake:type: SNOWFLAKEprops:worker-id: 1tables: #分表策略test_cost: # 主表名称actual-data-nodes: books.test_cost_$->{0..1}table-strategy:standard:sharding-column: idsharding-algorithm-name: table-inlineprops: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后,重新启动,运行正常。 -
运行结果
成功按照分片算法插入到对应的分表中。