java 用户定义的函数在H2数据库中无法工作

5ssjco0h  于 2023-06-28  发布在  Java
关注(0)|答案(1)|浏览(147)

我有一个Java函数来规范化一个字符串:

public static Object normalizeString(String source) {
    if (source==null) return null;
    String cleaned = source.replaceAll("[\\n\\r\\t]", "");
    cleaned = Normalizer.normalize(cleaned, Normalizer.Form.NFD);
    cleaned = cleaned.replaceAll("[^\\p{ASCII}]", ""); // on vire tout ce qui n'est pa ascii
    cleaned = cleaned.strip();
    return cleaned;
}

在我的应用程序中,我在两个地方调用它:
在升级SQL脚本中:

alter table entry add infostr1S VARCHAR_IGNORECASE null;
CREATE ALIAS normalizeString FOR "com.zparkingb.zploger.Compute.NormalizationSupport.normalizeString";
update entry set infostr1S = normalizeString(infostr1) where infostr1 is not null;

在AFTER INSERT和BEFORE UPDATE触发器中:

public class TriggerUpdateEntry implements Trigger {
    // ...
    public void fire(Connection conn, Object[] oldRow, Object[] newRow) throws SQLException {
        if (newRow == null) {
            return;
        }

        // Normalisation of the searchable strings on INSERT et UPDATE
        newRow[34] = NormalizationSupport.normalizeString((String) newRow[20]); //instr1 
    }
}

当TRIGGER正常工作时,UPDATE不工作:所有清理过的列都包含一个奇怪的字符串,看起来像“aced0005740011523230305f4475206c6f7572642e677078"。
[编辑]:更多关于它何时起作用,何时不起作用的调查:

  • 在BEFORE UPDATE触发器激活的情况下,所有值都是正确的。
  • 使用BEFORE UPDATE触发器dropped,所有值都不正确。

这意味着,IMO,

CREATE ALIAS normalizeString FOR "com.zparkingb.zploger.Compute.NormalizationSupport.normalizeString";
update entry set infostr1S = normalizeString(infostr1) where infostr1 is not null;

不能正常工作。
这是否与调用脚本或定义函数的方式有关?

for (Path scriptPath : scripts) {
    try (Statement st = archive.getConnection().createStatement()) {
        logger.info("Executing update script " + scriptPath);
        st.execute("RUNSCRIPT FROM '" + scriptPath + "'");
        logger.debug("Script " + scriptPath + " executed");
    } catch (SQLException ex) {
        throw new DBException("Execution of script " + scriptPath + " failed", ex);
    }
}

有没有人已经遇到过这种情况?
PS:我使用的是H2.1.4.196(最新版本的旧文件格式)和Java 11

t3irkdon

t3irkdon1#

该错误是由返回签名为Object的归一化函数引起的。
当从java调用时,没有问题,因为实际返回类型是String。但是,当从H2作为别名函数调用时,Object返回签名会使H2感到困惑,然后将值序列化为“aced000574001152323030”类型的字符串。
将返回签名显式更改为String可以防止混淆并解决问题:

public static String normalizeString(String source) {
    if (source==null) return null;
    String cleaned = source.replaceAll("[\\n\\r\\t]", "");
    cleaned = Normalizer.normalize(cleaned, Normalizer.Form.NFD);
    cleaned = cleaned.replaceAll("[^\\p{ASCII}]", ""); // on vire tout ce qui n'est pa ascii
    cleaned = cleaned.strip();
    return cleaned;
}

相关问题