我正在使用Oracle 10g和Hibernate 2.1(旧版本,但不允许升级修复)。我有一个名为TIN的可空列的表,varchar2(9)。此列用于暂存从平面文件加载的数据,因此如果输入文件有9个空格,则可以存储长度为9的任何字符串,包括9个空格(即:'')。
我注意到的是:
Oracle 10g自动将空字符串转换为NULL。所以,如果你执行:
SELECT NVL('', 'Input string converted to NULL') FROM dual;
结果是'输入字符串转换为NULL',而不是''。我认为这与问题有关。
当Hibernate读取TIN值为9个空格(或任意数量的空格)且没有其他字符的记录时,它将内存中的值存储为“”。然后,Hibernate似乎会欺骗自己思考,可以说,该值已从9个空格变为空字符串。然后,如果将记录写回数据库,Hibernate会尝试写入一个空字符串而不是9个空格,而Oracle显然将其转换为null,然后抛出非空约束违规。
作为参考,这是此专栏的HBM:
<property
name="tin"
type="java.lang.String"
column="TIN"
not-null="true"
length="9">
我的问题是,如何指示Hibernate不要将只包含空格的值转换为空字符串?
更新1:我刚回去测试像'text'这样的字符串,发现Hibernate也修剪了这些空格,使字符串'text'并且自欺欺人地认为值已经改变了。我肯定错过了什么。这似乎不是默认行为。
更新2:看起来将HBM转换为Java源的hbm2java Ant任务可能是String trims的来源。还在调查。
谢谢, 杰夫
编辑:更改问题措辞更准确。
答案 0 :(得分:4)
解决这个问题的一种方法是create a Hibernate UserType。在hibernate.org的链接中有一些指令,其中包含一些已经为String转义的类。我意识到这并没有直接回答'如何告诉hibernate不要将9个空格转换为空字符串',但它会解决数据库端的存储问题。
该页面上有两个实现 - 一个可以转义所有字符串(可以按照您想要的方式处理9个空格的情况),另一个只能转义值''。听起来前者可能更适合你。
为了记录 - 我自己正在使用这种方法。您需要做的就是在类路径中使用类,并将HBM.xml中的“type”属性设置为完全限定的类名(即将type =“my.fully.qualified.HibernateUserType”添加到property元素中)。
在Java方面,你的类仍将直接处理java.lang.String和你期望看到的值,但在休眠方面,它们将使用UserType类。
答案 1 :(得分:3)
原来问题不在于Hibernate。我正在开发的项目是为了使用hbm2java Ant任务从HBM文件生成Java POJO而设置的。这反过来引用了getters / setters / equals / toString / etc的源模板,该模板是为了修剪setter中的所有java.lang.String属性而编写的。为了解决这个问题,我钝化了一个我遇到问题的类,这样就不再在每个构建中生成它,然后删除了TIN属性上的trim。
答案 2 :(得分:2)
我不知道hibernate。但我确实知道Oracle确实将空字符串视为Null值。并没有任何解决方法。