Java String.substring()与Oracle 11g列VARCHAR2大小之间的字符串长度定义不一致 - java

我用这样的表设置数据库:

CREATE TABLE t_audit_log
(
  description VARCHAR2 (2500)
);

在使用它的Java应用程序中,我使用Hibernate将数据类映射到它上,并确保不生成SQLExceptions,将这种截断算法放在属性getter中:

private static final int MAX_STRING_LEN_2500 = 2499;

public void setDescription(final String newDescription) {
    if (newDescription != null
        && newDescription.length() > MAX_STRING_LEN_2500) {
        description = newDescription.substring(0, MAX_STRING_LEN_2500);
    } else {
        description = newDescription;
    }
}

直到今天,对于成千上万的审核日志条目,它都运行良好。我在日志中找到了这个:

Nov 09, 2015 7:54:40 AM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
WARN: SQL Error: 12899, SQLState: 72000
Nov 09, 2015 7:54:40 AM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: ORA-12899: value too large for column "BLABLA"."T_AUDIT_LOG"."DESCRIPTION" 
    (actual: 2501, maximum: 2500)

为什么substring()在值中留下一个额外的字符?

参考方案

我怀疑您的数据库设置被设置为使用"byte semantics"进行长度操作(这是NLS_LENGTH_SEMANTICS的默认设置),在这种情况下,您要说的是,在编码时希望字段的长度最大为2500个字节,而不是2500个字符。假设您的数据库使用UTF-8编码字符串-如果您的字符串包含2498个ASCII字符和1个字符的U + 20A0(欧元符号),则总共将产生2501个字节,但只有2499个字符。

Java length()substring()操作将根据UTF-16代码单元进行操作-可能会也可能不会与“字符语义”保持一致。 (您不太可能尝试将字符存储在“基本多语言平面”外部,在该平面中,单个字符采用两个UTF-16代码单元,但有可能)。

您确实需要确定要实际表示的字段长度,然后才能确定是否更改Java中执行截断的方式。

Java:我可以在Hashmaps中使用数组吗? - java

我可以在Hashmaps中使用数组吗?如果是这样,则声明这种哈希图的确切语法是什么?谢谢 参考方案 数组也是对象。甚至像int[]这样的原始数组。Map<String,String[]> map = new HashMap<String,String[]>();

Java:找到特定字符并获取子字符串 - java

我有一个字符串4.9.14_05_29_16_21,我只需要获取4.9。数字各不相同,所以我不能简单地获得此char数组的前三个元素。我必须找到最正确的.并将其子字符串化直到那里。我来自Python,因此我将展示Python的实现方法。def foobar(some_string): location = some_string.rfind('.&…

如何在字符串之间添加连字符 - java

我有以下字符串xxxxx,我想添加x-xxxx之类的连字符,如何使用Java? 参考方案 您可以使用String#substring()。String newstring = string.substring(0, 1) + "-" + string.substring(1); 您只需要事先检查string length即可避免Index…

Java string.hashcode()提供不同的值 - java

我已经在这个问题上停留了几个小时。我已经注释掉所有代码,认为这与数组超出范围有关,但是这种情况仍在发生。我正在尝试使用扫描仪从文件中读取输入,存储数据并稍后使用哈希码获取该数据。但是哈希值不断变化。public static void main(String[] args) { //only prior code is to access data char…

Java swing-事件触发后,我可以在选项卡上更改名称吗? - java

一,代码:tab_textArea_file.addTab(docLabel, null, scrollPane_textArea, null); 因此,情况是我有一个可供用户选择的文件列表。用户单击文件时,将读取文件的内容并将其加载到textArea中。 “ docLabel”(在上面的代码中)是应该更改为所选文件名的字符串,但并非如此。是否可以通过上面的…