基于flyway的spring boot migration

Flyway是个开源的数据库迁移工具(把migration翻译成迁移感觉听不顺嘴的,暂且这么叫吧)。它提供了 SQLJAVA两种方式做migration,并且使用也很简单。基于Spring Boot的应用开发场景,本文内容:

一. 添加依赖和配置

build.gradle:

dependencies{
	implementation('org.flywaydb:flyway-core')
}

application.properties:

spring.datasource.url=jdbc:mysql://localhost/demo_database_1
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
debug=true

flyway.baseline-on-migrate=true #used if database has some already table
flyway.enabled=true 
flyway.url=jdbc:mysql://localhost/demo_database_1
flyway.user=root
flyway.password=

二. 使用方法

sql方式的migration需要创建一个 .sql 文件,sql方式一般用来创建表、删除表,字段的添加、删除或者修改字段的名字、类型和初值等。如要想要对标中已有的数据执行逻辑操作,那就需要采用java的方式做migration,同样也需要创建 .java 文件。在spring boot程序启动的时候,flyway会按照顺序执行migration文件。

2.1migration文件的命名和放置的地方

V1__Add_new_table

其中:

  • V 是migration版本的前缀;
  • 1 是版本号,从1往上增加,不能重复;
  • Add_new_table 是文件名;

.sql文件放在 src/main/resources/db/migration 路径下;

.java文件放在 src/main/java/db/migration路径下;

2.2 SQL方式的migration

直接写SQL语句就可以了,很简单的。场景:创建一个employee表。

创建文件:resources/db/migration/V1__Create_Employee_Table.sql

SQL语句:

CREATE TABLE `employee` (
  `employeeId` int(11) NOT NULL AUTO_INCREMENT,
  `employeeName` varchar(255) DEFAULT NULL,
  `employeeRole` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`employeeId`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT;

2.3 JAVA方式的migration

创建的java文件中必须实现 SpringJdbcMigration 接口,在重写的 migration方法中编写业务逻辑。

场景1:查询employee中的员工数目。

package db.migration;

import org.flywaydb.core.api.migration.spring.SpringJdbcMigration;
import org.springframework.jdbc.core.JdbcTemplate;

public class V4__Another_user implements SpringJdbcMigration{
    @Override
    public void migrate(JdbcTemplate jdbcTemplate) throws Exception {
        int result = jdbcTemplate.queryForObject(
    "SELECT COUNT(*) FROM EMPLOYEE", Integer.class);
    }
}

场景2:查询所有员工的名字。(查询单个字段)

List<String> name = jdbcTemplate.queryForList(
        "select distinct(employeeId) from employee", String.class);

场景3:查询所有员工的ID、name和role。(查询多个字段)

RowMapper接口将查询结果映射到java对象。

public class EmployeeRowMapper implements RowMapper<Employee> {
    @Override
    public Employee mapRow(ResultSet rs, int rowNum) throws SQLException {
        Employee employee = new Employee();
 
        employee.setId(rs.getInt("id"));
        employee.setName(rs.getString("name"));
        employee.setAddress(rs.getString("role"));
 
        return employee;
    }
}

@Data
class Employee{
  int id;
  String name;
  String role;
}

对应的migration方法中的查询语句如下:

String query = "SELECT employeeId as id, employeeName as name, employeeRole as role FROM EMPLOYEE";
List<Employee> employees = jdbcTemplate.queryForObject(
  query, new EmployeeRowMapper());

场景4:查询姓名是“diego”的员工的信息。(带参查询)

String query = "SELECT * FROM EMPLOYEE WHERE employeeName = ?";
Employee employee = jdbcTemplate.queryForObject(
  query, new Object[] { “diego” }, new EmployeeRowMapper());

场景5:将所有员工的ID在原有基础上加1,这个逻辑操作很简单,但在实际应用中会出现很复杂的逻辑操作。(批量更新)

//获取所有员工信息。
String query = "SELECT employeeId as id, employeeName as name, employeeRole as role FROM EMPLOYEE";
List<Employee> employees = jdbcTemplate.queryForObject(
  query, new EmployeeRowMapper());

//更新
String updateUserInfoSQL = "update EMPLOYEE set employeeId = ? where employeeName = ?";
    jdbcTemplate.batchUpdate(updateUserInfoSQL, new BatchPreparedStatementSetter() {
      @SneakyThrows
      @Override
      public void setValues(PreparedStatement ps, int i) throws SQLException {
        Employee employee = employees.get(i);
        ps.setString(1, employee.getId()+1);
        ps.setString(2, employee.getName());
      }

      @Override
      public int getBatchSize() {
        return employees.size();
      }
    });
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值