在本文中,我将讨论在Spring Boot应用程序中使用
Liquibase实用程序来版本化关系数据库的结构并将该结构从一个版本迁移到另一个版本。 在第一部分中,我们将分析基本示例,在第二部分中,我们将讨论使用
liquibase-mave-plugin回滚更改并通过比较数据库结构自动生成脚本。
让我们从在Spring Boot + JPA(休眠)上创建最简单的应用程序开始。
Spring Initializr将帮助我们解决这个问题。 从依赖项中,选择JPA,MySQL和Web。 Liquibase也可以在此步骤连接,但是为了更好的理解,我们稍后将手动进行连接。
创建应用程序的基础
我们将一个实体类添加到我们的应用程序中,并为其添加一个存储库和一个REST控制器。 具体而言,我们将在创建的实体中存储有关用户的信息。
@Entity @Table(name = "users") public class User implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") private Long id; @Column(name = "username", unique = true, nullable = false) private String userName; @Column(name = "password", nullable = false) private String password; @Column(name = "first_name") private String firstName; @Column(name = "last_name") private String lastName; @Column(name = "email") private String email;
Spring Data使存储库代码极为简洁
public interface UserRepository extends JpaRepository<User, Long> { }
REST控制器将显示用户表的全部内容
@RestController public class UserController { private UserRepository userRepository; @Autowired public UserController(UserRepository userRepository) { this.userRepository = userRepository; } @GetMapping("/user/all") public List<User> allUsers() { return userRepository.findAll(); } }
application.properties文件中的设置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/geek_db?createDatabaseIfNotExist=true&allowPublicKeyRetrieval=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC spring.datasource.username=dbuser spring.datasource.password=dbpassword spring.jpa.show-sql=true spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
假定您的计算机在标准端口上运行MySQL服务器。 如有必要,请在连接字符串中调整服务器URL以及用户名和密码。 还值得关注
createDatabaseIfNotExist参数。 多亏了它,在连接时,如果服务器上没有它,我们将创建一个名为
geek_db的数据库。
添加液基
您肯定会注意到
缺少 Hibernate的一项设置,即
spring.jpa.hibernate.ddl-auto 。 在大多数初学者的手册中,都为它指明了
更新值,因此,Hibernate将根据项目中存在的实体类在服务器本身上创建和调整表结构。 如果数据方案非常简单或项目正在培训中,则很可能会使用这种方法,但是如果方案有些复杂,则仅由于我们无法控制生成Hibernate DDL脚本的过程而很可能会出现问题。 另一个问题是,使用这种方法没有简单的方法可以回滚在数据库结构中对Hibernate所做的更改。
为了解决上述问题,我们将使用
Liquibase实用程序。 对我们来说幸运的是,她完全能够与Spring Boot应用程序集成! 要开始使用它,您必须执行以下步骤
将设置添加到
application.properties文件
spring.jpa.hibernate.ddl-auto=none
这是为了确保Hibernate不会采取任何措施来修改电路,因为 Liquibase将立即执行它们。 从理论上讲,在这里您还可以使用
validate值对表结构的正确性进行附加控制。
向
pom.xml添加依赖项
<dependency> <groupId>org.liquibase</groupId> <artifactId>liquibase-core</artifactId> </dependency>
添加后,Spring Boot将自动创建一个名为liquibase的特殊bean,该bean将在应用程序每次启动时执行所有操作,以基于Liquibase脚本配置数据库模式。
现在,您需要添加Liquibase脚本本身,这将创建我们需要的表。 在/ src / main / resources / db / changelog文件夹中,创建一个名为db.changelog-master.yaml的文件,并将以下内容添加到其中
databaseChangeLog: - logicalFilePath: db/changelog/db.changelog-lesson1.yaml - changeSet: id: 1 author: your_liquibase_username changes: - createTable: tableName: users columns: - column: name: id type: BIGINT autoIncrement: true constraints: primaryKey: true nullable: false - column: name: username type: varchar(50) constraints: unique: true nullable: false - column: name: password type: varchar(512) constraints: nullable: false - column: name: first_name type: varchar(50) - column: name: last_name type: varchar(50) - column: name: email type: varchar(50)
让我们分析一下该脚本的内容。 首先,它包含一个changeSet。 ChangeSet与版本控制系统(例如Git或SVN)中的提交类似。 与提交类似,可以将作为一个changeSet的一部分所做的更改回滚或回滚到数据库服务器。 每个changeSet必须具有唯一的标识符,Liquibase可以使用该标识符来确定给定的changeSet是否已被泵送到该数据库。
ChangeSet包含创建表的命令,该表的结构由Liquibase而不是SQL脚本描述。 因此,该文件成为跨平台的。 Liquibase将根据所使用的数据库服务器生成一个SQL脚本。 另外,如果我们需要回滚给定的changeSet,则Liquibase将能够自动创建脚本以删除给定的表。 如果使用SQL脚本,则必须手动编写脚本以回滚更改。 在
hanges部分,我们只有一个团队,这被认为是一种好的做法,尽管在一个
changeSet中可以有任意数量的团队。
编写的代码足以运行该程序,但是为了更清楚地看到其工作结果,让我们添加另一个
changeSet ,它将用数据填充表。
- changeSet: id: 2 author: your_liquibase_username comment: "Create admin user" changes: - insert: tableName: users columns: - column: name: username value: "admin" - column: name: password value: "admin" - column: name: email value: "admin@server.com" - insert: tableName: users columns: - column: name: username value: "guest" - column: name: password value: "guest" - column: name: email value: "guest@server.com" rollback: - delete: tableName: users where: username in ('admin', 'guest')
在这种情况下,我们已经必须手动为回滚操作编写一个块,如下所示 使用数据时,Liquibase无法自动创建回滚SQL。 通常,使用数据库中的数据不是Liquibase的主要功能,而仅限于最简单的插入,删除或更改操作。 顺便说一句,如果您需要更多,则可以在这里使用
Red Gate公司的工具。
因此,让我们运行我们的应用程序,然后尝试点击链接
http:// localhost:8080 / user / all 。 如果应用程序启动,那么您将看到一个JSON响应,其中包含有关添加到表中的两个用户的信息。 还值得一看的是应用程序启动日志,您可以在其中查看Liquibase为初始化数据库而执行的脚本。 应特别注意
DATABASECHANGELOG表。 Liquibase正是在其中存储了对数据库所做更改的日志。
现在就这些了。 一段时间之后,我计划发布一个
续集,介绍如何使用
liquibase-maven-plugin通过比较数据库结构并回滚所做的更改来自动生成脚本。
如有任何补充和评论,我将不胜感激!
PS基于本文编写的完整代码
github.com/usharik/spring-liquibase-demo/tree/part-1续至
habr.com/en/post/460907