5.2.3. 自定义值类型
开发者创建属于他们自己的值类型也是很容易的。比如说,你可能希望持久化java.lang.BigInteger
类型的属性,持久化成为VARCHAR
字段。Hibernate没有内置这样一种类型。自定义类型能够映射一个属性(或集合元素)到不止一个数据库表字段。比如说,你可能有这样的Java属性:getName()
/setName()
,这是java.lang.String
类型的,对应的持久化到三个字段:FIRST_NAME
, INITIAL
, SURNAME
。
要实现一个自定义类型,可以实现org.hibernate.UserType
或org.hibernate.CompositeUserType
中的任一个,并且使用类型的Java全限定类名来定义属性。请查看org.hibernate.test.DoubleStringType
这个例子,看看它是怎么做的。
<property name="twoStrings" type="org.hibernate.test.DoubleStringType">
<column name="first_string"/>
<column name="second_string"/>
</property>
注意使用<column>
标签来把一个属性映射到多个字段的做法。
CompositeUserType
, EnhancedUserType
, UserCollectionType
, 和 UserVersionType
接口为更特殊的使用方式提供支持。
你甚至可以在一个映射文件中提供参数给一个UserType
。 为了这样做,你的UserType
必须实现org.hibernate.usertype.ParameterizedType
接口。为了给自定义类型提供参数,你可以在映射文件中使用<type>
元素。
<property name="priority">
<type name="com.mycompany.usertypes.DefaultValueIntegerType">
<param name="default">0</param>
</type>
</property>
现在,UserType
可以从传入的Properties
对象中得到default
参数的值。
如果你非常频繁地使用某一UserType
,可以为他定义一个简称。这可以通过使用 <typedef>
元素来实现。Typedefs为一自定义类型赋予一个名称,并且如果此类型是参数化的,还可以包含一系列默认的参数值。
<typedef class="com.mycompany.usertypes.DefaultValueIntegerType" name="default_zero">
<param name="default">0</param>
</typedef>
<property name="priority" type="default_zero"/>
也可以根据具体案例通过属性映射中的类型参数覆盖在typedef中提供的参数。
尽管 Hibernate 内建的丰富的类型和对组件的支持意味着你可能很少 需要使用自定义类型。不过,为那些在你的应用中经常出现的(非实体)类使用自定义类型也是一个好方法。例如,一个MonetaryAmount
类使用CompositeUserType
来映射是不错的选择,虽然他可以很容易地被映射成组件。这样做的动机之一是抽象。使用自定义类型,以后假若你改变表示金额的方法时,它可以保证映射文件不需要修改。