簡體   English   中英

liquibase 中的 Java 代碼變更集

[英]Java code changeset in liquibase

liquibase 中有沒有辦法創建 java 代碼更改集(即提供一個 java 類,它將接收 JDBC 連接並在數據庫中執行一些更改)?

(我知道flyway有這樣的功能)

是的,有這樣的功能。 您可以創建customChange

    <customChange class="my.java.Class">
        <param name="id" value="2" />
    </customChange>

該類必須實現liquibase.change.custom.CustomTaskChange接口。

@Override
public void execute(final Database arg0) throws CustomChangeException {
    JdbcConnection dbConn = (JdbcConnection) arg0.getConnection();
    try {
         ... do funny stuff ...
    } catch (Exception e) {
        // swallow the exception !
    }
}

完整的示例將如下所示

創建一個實現CustomTaskChange或CustomSqlChange的類。

package com.example;

import liquibase.change.custom.CustomTaskChange;
import liquibase.database.Database;
import liquibase.database.jvm.JdbcConnection;
import liquibase.exception.CustomChangeException;
import liquibase.exception.SetupException;
import liquibase.exception.ValidationErrors;
import liquibase.logging.LogFactory;
import liquibase.resource.ResourceAccessor;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class DataLoaderTask implements CustomTaskChange {

    //to hold the parameter value
    private String file;


    private ResourceAccessor resourceAccessor;


    public String getFile() {
        return file;
    }

    public void setFile(String file) {
        this.file = file;
    }


    @Override
    public void execute(Database database) throws CustomChangeException {
        JdbcConnection databaseConnection = (JdbcConnection) database.getConnection();
        try {

            //Opening my data file
            BufferedReader in = new BufferedReader(
                    new InputStreamReader(resourceAccessor.getResourceAsStream(file)));

            //Ignore header
            String str = in.readLine();

            while ((str = in.readLine()) != null && !str.trim().equals("")) {
                LogFactory.getLogger().info("Processing line "+ str);
                //Do whatever is necessary
            }
            in.close();
        } catch (Exception e) {
            throw new CustomChangeException(e);
        }
    }

    @Override
    public String getConfirmationMessage() {
        return null;
    }

    @Override
    public void setUp() throws SetupException {

    }

    @Override
    public void setFileOpener(ResourceAccessor resourceAccessor) {
        this.resourceAccessor = resourceAccessor;
    }

    @Override
    public ValidationErrors validate(Database database) {
        return null;
    }

}

在changeset xml中,您可以使用如下所示的類

<changeSet id="1" author="murali" runAlways="false" failOnError="true" >
        <customChange class="com.example.DataLoaderTask">
            <param name="file" value="/com/example/data/user.csv" />
        </customChange>
</changeSet>

對我來說,數據文件位於src / main / resources / com / example / data目錄中

希望這可以幫助

雖然這兩個答案對我都非常有幫助,但對於我通過數據庫查詢操作數據庫中的數據的用例,它們都不完整。 我認為當你想在你的變更集中使用 java 代碼(而不是普通的 SQL 代碼)時,真正的重點是你想從你的數據庫中讀取和寫入一些東西(以及在你的 java 代碼中操作它之間)。

就我而言,我想加密存儲在我們數據庫中的所有郵件地址。 我不知道下面的例子是否完美,但它的工作做得很好:

第一部分:添加變更日志

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd">

  <changeSet id="1" author="IssueNo321" runAlways="false" failOnError="true">
    <customChange class="class.package.name.EncryptAllMailAddresses"/>
  </changeSet>
</databaseChangeLog>

第二部分:將變更日志添加到您的變更日志列表db.changelog-master.yaml

databaseChangeLog:
  - includeAll:
      relativeToChangelogFile: true
      path: changelogs/IssueNo321

第三部分:實現遷移java代碼

package class.package.name;

import liquibase.change.custom.CustomTaskChange;
import liquibase.database.Database;
import liquibase.database.jvm.JdbcConnection;
import liquibase.exception.CustomChangeException;
import liquibase.exception.SetupException;
import liquibase.exception.ValidationErrors;
import liquibase.resource.ResourceAccessor;

public class EncryptAllMailAddresses implements CustomTaskChange {

  private EncryptionService encryptionService;

  @Override
  public void execute(Database database) throws CustomChangeException {

    try {
      var dbConn = (JdbcConnection) database.getConnection(); // autocommit is false

    try {
      var selectStatement = dbConn.createStatement();
      var updateStatement = dbConn.createStatement();

      var rs = selectStatement.executeQuery("Select id, email from emails");
      while (rs.next()) {
        var id = rs.getString("id");
        var email = rs.getString("email");

        email = encryptionService.encrypt(email);
        var updateSql = String.format("update emails set email = '%s' where id = %s", email, id);
        updateStatement.execute(updateSql);
      }

      selectStatement.close();
      updateStatement.close();
    } catch (Exception e) {
        throw new CustomChangeException(e);
    }
  }

  @Override
  public String getConfirmationMessage() {
    return null;
  }

  @Override
  public void setUp() throws SetupException {}

  @Override
  public ValidationErrors validate(Database database) {
    return null;
  }

  @Override
  public void setFileOpener(ResourceAccessor resourceAccessor) {
    // do nothing since we don't need additional resources
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM