数据初始化

码匠君 ... 2021-10-28 大约 9 分钟

# 数据初始化

# 知识铺垫

# 基础原理

Eurynome Cloud 核心数据访问层使用Spring Boot生态中的spring-boot-starter-data-jpa组件,spring-boot-starter-data-jpa 核心依赖是 Spring Data JPA

JPA(Java Persistence API)意即Java持久化API,是Sun官方在JDK5.0后提出的Java持久化规范。Spring Data JPA 默认使用 Hibernate 作为 JPA 实现。参阅:Spring Data JPA

Spring Data JPA 利用 Hibernate 多数据库支持能力实现不同类型数据库的支持,同时使用 Hibernatehbm2ddl 机制 实现数据库表的自动创建。除此以外,Spring Data JPA 提供了数据库SQL脚本自动执行机制,实现了数据脚本的初始化和表结构等创建功能。

# Spring Data JPA 更换数据库

通过修改spring-boot-starter-data-jpa对应的配置参数就可以达成更换数据库的目的。主要涉及需要修改的配置参数如下表所示:

配置 说明
spring.datasource.driver-class-name 数据库Driver Class,不同的数据库驱动不同
spring.datasource.url 数据库访问连接,不同数据连接格式也不同
spring.datasource.username 数据库访问用户名,如果相同可以不用修改
spring.datasource.password 数据库访问密码,如果相同可以不用修改
spring.jpa.database 选择数据库类型,具体类型与枚举org.springframework.orm.jpa.vendor.Database中的值对应,使用小写值即可
spring.jpa.properties.hibernate.dialect 选择数据库类型对应的dialect,在 org.hibernate.dialect 包下可以找到具体数据库对应的dialect
spring.jpa.hibernate.ddl-auto 设置hibernate初始化操作的类型,具体参见下表

这里要特别注意 spring.jpa.hibernate.ddl-auto 参数。

spring.jpa.hibernate.ddl-auto 参数包含以下几个值,具体含义见下表:

属性 说明
create 每次加载hibernate时都会删除上一次的生成的表,再重新根据model(与数据库表对应的实体)生成表,因此可能会导致数据丢失。
create-drop 每次加载hibernate时根据model类生成表,服务一关闭,表就自动删除。该设置适用于演示环境等特殊场景使用
update 最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构,再次使用时自动更新表结构,原有数据不会清空。
validate 每次加载hibernate时,会校验数据与数据库的字段类型是否相同,字段不同会报错。
none 不进行任何操作

如果想要使用spring-boot-starter-data-jpa提供SQL自动初始化机制,那么还需要额外修改以下配置:

通过以上配置参数的修改就可以进行数据库的切换,以及数据库表的创建.

# Spring Data JPA 初始化数据库

Spring Data JPA 还提供的数据库SQL脚本的执行机制。将已生成好的数据库SQL脚本,放入到代码工程的resources目录下,按照指定格式命名,通过修改配置就可以实现SQL脚本的自动执行。

具体SQL文件名的格式为:schema-${platform}.sqldata-${platform}.sqlplatform 是用来指定不同的数据库类型,以此来实现不同数据库脚本的切换。

  • schema-${platform}.sql:主要放置数据库定义语言(DDL)SQL脚本,例如:数据库表,视图,存储过程等。
  • data-${platform}.sql:主要放置数据操纵语言(DML)SQL脚本,例如:最经常用到的 SELECT,UPDATE,INSERT,DELETE。

由此可见,schema-${platform}.sql 是先于 data-${platform}.sql 执行的。

主要涉及需要修改的配置参数如下表所示:

配置 说明
spring.sql.init.mode 用于控制脚本执行状态。
spring.sql.init.platform 数据库类型,主要用于在data-locations 和 schema-locations 中定位不同数据库的脚本
spring.sql.init.data-locations DML SQL文件路径
spring.sql.init.data-locations DDL SQL文件路径

这里要特别注意 spring.sql.init.mode 参数。

spring.sql.init.mode 参数包含以下几个值,具体含义见下表:

属性 说明
always 总是执行,相当于开启
never 不执行,相当于关闭
embedded 仅初始化嵌入式数据库,特殊需求和设计会用到

# 特别说明

警告

Spring Data JPA 既可以通过 Hibernate 的机制进行数据库表的创建,也可以通过sql.init的方式进行数据库表以及数据初始化的创建。这两者是各自独立的,没有任何必然联系的。具体如何使用就要看设计者的考虑。

两者的执行顺序不同,如果要两者同时使用一定要注意执行顺序,否则很容易导致运行出错。具体的顺序是:

schema-${platform}.sql > data-${platform}.sql > hbm2ddl

# 操作步骤

Eurynome Cloud 数据库表创建和默认数据的初始化,就是使用 Spring Data JPA 自身的机制实现。

Eurynome Cloud 数据库表创建和默认数据的初始化过程中, 主要会进行以下几项操作。

  • 创建核心业务表
  • 扫描已运行服务中所有的RestController接口,将接口数据转换为权限数据,并汇总至用户中心服务统一存储和管理。
  • 系统默认数据,如用户,角色等数据的初始化。

注意

具体开始之前,一定要确保所有前序工作已经完成。参阅:数据库初始化前序工作

# 步骤一:创建数据表

  1. 进入Nacos管理界面。找到您所使用的对应 多环境 下的 eurynome-cloud-environment.yaml 配置文件。例如,您当前使用的是 development 环境,那么在Nacos后台管理中,找到 Groupdevelopmenteurynome-cloud-environment.yaml 配置。多环境配置,参阅:多环境配置

  2. 设置 eurynome-cloud-environment.yaml配置文件中属性 herodotus.switch.database.ddl-auto 的值为 createupdate

注意

  • 如果是初次部署,或者想将已有表重新创建,那么将 herodotus.switch.database.ddl-auto 的值设置为 create
  • 如果是已经开始使用系统了,想保留已有的数据,只做更新,那么将 herodotus.switch.database.ddl-auto 的值设置为 update
  1. 点击发布按钮,发布配置,让配置生效。

警告

  • 正式环境一定要提前做好数据备份

  • 如果是MySQL数据库的初次部署,那么最好将 herodotus.switch.database.ddl-auto 的值设置为 update,否则就会出错。

  • herodotus.switch.database.ddl-auto 的值设置为 update, 再次运行服务,由于 Hibernate 不同方言实现逻辑的不同,在有些数据库下运行,例如:PostgreSQL, 对于某些兼容性问题,只是输出告警;在某些数据库下运行,例如 MySQL,对于某些兼容性问题,会直接抛出Exception。所以出现这种情况,只要服务继续在运行就不是系统BUG;如果出错直接导致服务运行停止,那么请报 ISSUE。参阅:MySQL常见问题

  1. 运行 UpmsApplication 服务。

UpmsApplication 服务第一次正常运行之后,所有核心业务表都已经创建,UpmsApplication 服务中所有接口都已经转换为权限数据存入sys_authority表中。

如果看到有数据库表创建,同时sys_authority表中有数据,证明数据库表创建成功。

# 步骤二:初始默认数据

# 方式一:自动初始化

  1. 停止UpmsApplication 服务

  2. 进入Nacos管理界面。找到您所使用的对应 多环境 下的 eurynome-cloud-environment.yaml 配置文件。

  3. 设置 eurynome-cloud-environment.yaml 配置文件中属性 herodotus.switch.database.ddl-auto 的值为 updatenone

  4. 设置 eurynome-cloud-environment.yaml 配置文件中属性 herodotus.switch.database.init-mode 的值为 always

  5. 点击发布按钮,发布配置,让配置生效。

  6. 如果默认使用的不是 PostgreSQL 数据库,需要修改${project_home}/services/eurynome-cloud-upms-ability/resources/bootstrap.ymlspring.sql.init.data-locations 配置,放开您所使用数据库对应的SQL脚本。注释掉其它SQL脚本

  7. 再次运行 UpmsApplication 服务。

UpmsApplication 服务再一次正常运行之后,如果sys_user,sys_role,sys_role_authority等表中都都已经有数据了,证明数据初始化成功。

# 方式二:手动初始化

  1. 设置 eurynome-cloud-environment.yaml 配置文件中属性 herodotus.switch.database.ddl-auto 的值为 updatenone

  2. 在工程${project_home}/services/eurynome-cloud-upms-ability/resources/sqls目录下,可以找到对应数据库数据初始化脚本。可以用你喜欢的方式导入数据库。

采用手动初始化方式,下一步可以跳过忽略

# 步骤三:回置配置

  1. 停止UpmsApplication 服务

  2. 进入Nacos管理界面。找到您所使用的对应 多环境 下的 eurynome-cloud-environment.yaml 配置文件。

  3. 设置 eurynome-cloud-environment.yaml 配置文件中属性 herodotus.switch.database.init-mode 的值重置为 never

  4. 检查 eurynome-cloud-environment.yaml 配置文件中属性 herodotus.switch.database.ddl-auto 的值为 updatenone

  5. 点击发布按钮,发布配置,让配置生效。

为什么回置并再次检查

  • 如果 herodotus.switch.database.ddl-auto 的值为 createcreate-drop,再次启动服务会重新建表,那么前面的工作就白做了。
  • 如果 herodotus.switch.database.init-mode 的值为 always,再次启动服务会再次执行SQL脚本,必定出现主键冲突问题导致失败。

# 总结

经过实际的使用,总体感受 Spring Data JPA 以及 Hibernate 的多数据库支持还是非常强大,在 PostgreSQL 等自身版本差异不大的数据库家族中,使用非常顺滑。而像MySQL 这种自身各个版本差异较大的数据库家族中,使用起来确实有点蹩脚。

# 配置参数对应关系

Eurynome Cloud 数据库操作设计配置参数与spring-boot-starter-data-jpa配置参数对应关系如下表:

配置 对应
herodotus.database-information.driver-class-name spring.datasource.driver-class-name
herodotus.database-information.url spring.datasource.url
herodotus.environment.database.username spring.datasource.username
herodotus.environment.database.password spring.datasource.password
herodotus.database-information.platform spring.jpa.database
spring.sql.init.platform
herodotus.environment.database.dialect spring.jpa.properties.hibernate.dialect
herodotus.switch.database.ddl-auto spring.jpa.hibernate.ddl-auto
herodotus.switch.database.init-mode spring.sql.init.mode
上次编辑于: 2021年10月28日 23:24
贡献者: herodotus