![](/img/trans.png)
[英]Getting liquibase.exception.CustomChangeException on running Java code changeset in liquibase
[英]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.