5.2.3. 自定义值类型

开发者创建属于他们自己的值类型也是很容易的。比如说,你可能希望持久化java.lang.BigInteger类型的属性,持久化成为VARCHAR字段。Hibernate没有内置这样一种类型。自定义类型能够映射一个属性(或集合元素)到不止一个数据库表字段。比如说,你可能有这样的Java属性:getName()/setName(),这是java.lang.String类型的,对应的持久化到三个字段:FIRST_NAME, INITIAL, SURNAME

要实现一个自定义类型,可以实现org.hibernate.UserTypeorg.hibernate.CompositeUserType中的任一个,并且使用类型的Java全限定类名来定义属性。请查看org.hibernate.test.DoubleStringType这个例子,看看它是怎么做的。

  1. <property name="twoStrings" type="org.hibernate.test.DoubleStringType">
  2. <column name="first_string"/>
  3. <column name="second_string"/>
  4. </property>

注意使用&lt;column&gt;标签来把一个属性映射到多个字段的做法。

CompositeUserType, EnhancedUserType, UserCollectionType, 和 UserVersionType 接口为更特殊的使用方式提供支持。

你甚至可以在一个映射文件中提供参数给一个UserType。 为了这样做,你的UserType必须实现org.hibernate.usertype.ParameterizedType接口。为了给自定义类型提供参数,你可以在映射文件中使用&lt;type&gt;元素。

  1. <property name="priority">
  2. <type name="com.mycompany.usertypes.DefaultValueIntegerType">
  3. <param name="default">0</param>
  4. </type>
  5. </property>

现在,UserType 可以从传入的Properties对象中得到default 参数的值。

如果你非常频繁地使用某一UserType,可以为他定义一个简称。这可以通过使用 &lt;typedef&gt;元素来实现。Typedefs为一自定义类型赋予一个名称,并且如果此类型是参数化的,还可以包含一系列默认的参数值。

  1. <typedef class="com.mycompany.usertypes.DefaultValueIntegerType" name="default_zero">
  2. <param name="default">0</param>
  3. </typedef>
  1. <property name="priority" type="default_zero"/>

也可以根据具体案例通过属性映射中的类型参数覆盖在typedef中提供的参数。

尽管 Hibernate 内建的丰富的类型和对组件的支持意味着你可能很少 需要使用自定义类型。不过,为那些在你的应用中经常出现的(非实体)类使用自定义类型也是一个好方法。例如,一个MonetaryAmount类使用CompositeUserType来映射是不错的选择,虽然他可以很容易地被映射成组件。这样做的动机之一是抽象。使用自定义类型,以后假若你改变表示金额的方法时,它可以保证映射文件不需要修改。