如何防止Hibernate修剪字符串?

3
我正在使用Oracle 10g和Hibernate 2.1(旧版本,但不允许升级以修复)。 我有一个表,其中有一个名为TIN的非空列,varchar2(9)。 此列用于存储从平面文件加载的数据,并且可以存储任何长度为9的字符串,包括9个空格(即:' '),如果输入文件有9个空格。 我注意到的是:
  1. Oracle 10g automatically converts empty strings to NULL. So if you execute:

    SELECT NVL('', 'Input string converted to NULL') FROM dual; 
    

    the result is 'Input string converted to NULL', not ''. I think this is relevant to the problem.

  2. When Hibernate reads a record where the TIN value is 9 spaces (or any number of spaces) with no other character, it stores the value in memory as ''. Hibernate then seems to trick itself into thinking, so to speak, that the value has changed from 9 spaces to an empty string. Then if the record is written back to the database, Hibernate tries to to write an empty string rather than 9 spaces and Oracle apparently converts this to null and then throws a not-null constraint violation.

供参考,这是该列的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修剪的源头。仍在调查中。谢谢,Jeff。编辑:更改问题措辞以更加精确。
3个回答

4
一种处理方法是创建一个Hibernate UserType。在hibernate.org的链接中有说明,其中包含一些已经制作好的用于字符串转义的类。我知道这并没有直接回答“如何告诉Hibernate不要将9个空格转换为空字符串”的问题,但它将解决数据库存储问题。
该页面上有2个实现方式 - 一个转义所有字符串(可能以所需方式处理您的9个空格情况),另一个仅转义值''。听起来前者可能更适合您。
记录一下 - 我自己正在使用这种方法。您只需要在类路径中拥有该类,并将HBM.xml中的“type”属性设置为完全限定的类名(即在property元素中添加type =“my.fully.qualified.HibernateUserType”)即可。
在Java方面,您的类仍将直接处理java.lang.String和您期望看到的值,但在Hibernate方面,它们将使用UserType类。

谢谢Joshua。这似乎是一个相当不错的方法。我看到的最大问题是,除了Hibernate之外访问该数据的所有内容都必须知道这些值已经被转义。我想知道Hibernate截取值的行为是否正常/有文档记录。 - jlpp
如果代码中有其他访问数据库的部分不是通过Hibernate实现的,那么这就是一个问题。 - Joshua McKinnon
很遗憾,情况确实如此。已经编写了存储过程以批量处理扁平文件,读/写相同的列。谢谢您的回答,非常实用。 - jlpp

3

事实证明问题并不在Hibernate上。我正在处理的项目是使用hbm2java Ant任务从HBM文件生成Java POJOs。这个任务引用了一个源模板,用于生成getter/setter/equals/toString等方法,该模板编写为在setter中修剪所有java.lang.String属性。为了解决问题,我对其中一个出现问题的类进行了去活动化处理,以便它不再在每次构建时生成,并且删除了TIN属性上的修剪。


2

我不了解Hibernate,但我知道Oracle将空字符串视为Null值。而且没有任何解决方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接