一直以来,在Mybatis中对于手工建库与修改表结构是一个比较遭人诟病的一个话题,今有幸在实际项目中学习了关于利用flyway来构建及管理数据库版本以方便对数据库表及结构的管理操作。
Flyway是一个简单开源数据库版本控制器(约定大于配置),主要提供migrate、clean、info、validate、baseline、repair等命令。它支持SQL(PL/SQL、T-SQL)方式和Java方式,支持命令行客户端等,还提供一系列的插件支持(Maven、Gradle、SBT、ANT等)。
官方网站:https://flywaydb.org/
本文对于Flyway的自身功能不做过多的介绍,读者可以通过阅读官方文档或利用搜索引擎获得更多资料。下面我们具体说说在Spring Boot/Spring Cloud应用中的应用,如何使用Flyway来创建数据库以及结构不一致的检查。
1、引入依赖
在pom.xml中增加flyway的依赖,具体代码如下:
org.flywaydb
flyway-core
5.0.7
org.flywaydb.flyway-test-extensions
flyway-spring-test
test
2、建立数据库文件
按Flyway的规范创建版本化的SQL脚本(规划化可支持无配置,即约定优于配置)。
在工程的src/main/resources目录下创建db目录
在db目录下可创建版本化的SQL脚本V1.0__Base_version.sql(db目录下可再新建目录,非必须在db根目录下创建,如db/mssqlserver/V1/V1.0__admin_init.sql)
其部分内容如下所示:
/*==============================================================*/
/* Table: admin_user */
/*==============================================================*/
DROP TABLE IF EXISTS admin_user ;
CREATE TABLE admin_user (
id BIGINT IDENTITY (1, 1) NOT NULL PRIMARY KEY,
username NVARCHAR(50) NULL,
password NVARCHAR(250) NULL,
name NVARCHAR(50) NULL,
mobile NVARCHAR(20) NULL,
email NVARCHAR(100) NULL,
enabled BIT DEFAULT '1',
deleted BIT DEFAULT '0',
creator_id BIGINT DEFAULT NULL,
creator NVARCHAR(50) DEFAULT NULL,
date_created DATETIME DEFAULT NULL,
modifier_id BIGINT DEFAULT NULL,
modifier NVARCHAR(50) DEFAULT NULL,
last_modified DATETIME DEFAULT NULL
);
3、建立测试类
@RunWith(SpringRunner.class)
@SpringBootTest(classes = AdminApplication.class)
@TestPropertySource(properties = {"spring.profiles.active: test", "flyway.enabled: true"})
@EnableAutoConfiguration
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class, FlywayTestExecutionListener.class})
@Slf4j
public class ApiDAOTest {
@Autowired
private ApiDAO apiDAO;
@FlywayTest
@Test
public void apiDAOTest() throws Exception {
ApiDO apiDO = ApiUtils.fakerApiDO();
Integer insertRow = apiDAO.insert(apiDO);
Assertions.assertThat(insertRow).isEqualTo(1);
Long id = 1L;
ApiDO result = apiDAO.selectById(id);
assertThat(result).hasFieldOrPropertyWithValue("id", id);
Integer apiNumber = apiDAO.deleteById(id);
assertThat(apiNumber).isEqualTo(1);
}
}
上述测试类仅为测试类的代码相关代码可忽略,可根据自己的项目建立,这里主要引用的注解有三个需要注意的地方@SpringBootTest、@TestPropertySource、@TestExecutionListeners及@FlywayTest注解,这里使用SpringBootTest注解是为了方便集成测试配置,其他两项配置是指配置文件来源、是否启用Flyway(默认是启用的,配置文件中可增加开关,以便于应用于生产环境中)及配置执行监听服务。
单元测试类实例代码如下:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = AdminApplication.class,properties = "classpath:/application-test.yaml")
@TestPropertySource(properties = { "spring.profiles.active: test", "flyway.enabled: true" })
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class, FlywayTestExecutionListener.class})
@FlywayTest
public class ApiServiceTest {
/**
* API接口服务service服务
*/
@Autowired
private ApiService apiService;
/**
* 测试API接口服务新增
* @throws Exception
*/
@Test
public void insert() throws Exception {
AdminApiParam apiParam = ApiUtils.fakerApiParam();
boolean insertSuccess = apiService.insert(apiParam);
Assertions.assertThat(insertSuccess).isEqualTo(true);
ApiDO apiDO = new ApiDO();
apiDO.setName(apiParam.getName());
EntityWrapper eWrapper = new EntityWrapper(apiDO);
ApiDO result = apiService.selectOne(eWrapper);
boolean deleteSuccess = apiService.deleteById(result.getId());
Assertions.assertThat(deleteSuccess).isEqualTo(true);
}
这里的引入了@TestPropertySource、@ActiveProfiles、@FlywayTest同上一致的注解,前两项为指定配置文件为test配置文件,其中@FlywayTest与@TestExecutionListeners注解主要就是实现数据库表结构的生成与执行数据清理,当执行测试类时会自动将数据库中已有的数据进行清理!
4、配置YAML文件
配置文件application-test.yaml内容如下:
# flyway开关
flyway:
enabled: true
关于flyway更多配置选项可查询相关flyway API进行查看,另网上很多文章描述需在application的文件中配置Flyway要加载的SQL脚本位置,但在本例中无需配置flyway.locations选项,因为我们采用的是约定大于配置,即使用约定的路径flyway会自动去寻找。
启动ApiDAOTest中的AdminApplication即Spring Cloud的主程序,此时即会连接数据库进行数据库表结构的初始化与版本控制,系统会自动在数据库中建立flyway_schema_history用于版本控制的表(注意:此处不建立自己手工在数据库后台建表,因为当手工建立以后缺少flyway表会引出集成测试错误),这时系统就会利用flyway自动完成数据库的构建。当然配置文件中不能缺少spring.datasource的配置内容,要不无法连接数据库。然后通过数据库客户端工具连接数据库即可查看所建立好的数据表结构。
到这里为止,本文的内容暂告一段落。由于博文篇幅问题,对于Flyway更细节的使用没有说的太多,本文主要作为敲门砖,帮助和引导正在使用Spring Boot做系统开发的个人或团队在数据库的版本控制上做的更好提供一些思路。至于更深入的应用还请读者自行翻阅官方文档参考和学习。
同时这里需要注意三点:
1、当在使用intellij idea开发工具时请不要将maven project视图中的跳过test禁用,否则将无法正常创建和进行集成与单元测试(如下图箭头所示)。
2、除主程序 AdminApplication启动类以外,ApiDAOTest、ApiServiceTest等测试类也可在主程序未启动时单独进行集成与单元测试,测试类会自动创建对应的数据库表;另上述测试类中如果不引用@FlywayTest或@TestExecutionListeners任一注解的话,都不会自动清理数据库表中的数据,而是直接生成新的数据进行相关集成与单元测试!
3、如果你需要对数据库表结构进行更改,可编写alter语句来完成,让flyway去自动执行,以避免数据库的人为手工操作。