git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@19607 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
30ea7142e8
commit
a05dc9066a
|
@ -0,0 +1,990 @@
|
||||||
|
<!--
|
||||||
|
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
~
|
||||||
|
~ Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||||
|
~ indicated by the @author tags or express copyright attribution
|
||||||
|
~ statements applied by the authors. All third-party contributions are
|
||||||
|
~ distributed under license by Red Hat Inc.
|
||||||
|
~
|
||||||
|
~ This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
~ copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
~ Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
~
|
||||||
|
~ This program is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
~ for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU Lesser General Public License
|
||||||
|
~ along with this distribution; if not, write to:
|
||||||
|
~ Free Software Foundation, Inc.
|
||||||
|
~ 51 Franklin Street, Fifth Floor
|
||||||
|
~ Boston, MA 02110-1301 USA
|
||||||
|
-->
|
||||||
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
||||||
|
|
||||||
|
<chapter id="types">
|
||||||
|
<title>Types</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
As an Object/Relational Mapping solution, Hibernate deals with both the Java and JDBC representations of
|
||||||
|
application data. An online catalog application, for example, most likely has <classname>Product</classname>
|
||||||
|
object with a number of attributes such as a <literal>sku</literal>, <literal>name</literal>, etc. For these
|
||||||
|
individual attributes, Hibernate must be able to read the values out of the database and write them back. This
|
||||||
|
'marshalling' is the function of a <emphasis>Hibernate type</emphasis>, which is an implementation of the
|
||||||
|
<interfacename>org.hibernate.type.Type</interfacename> interface. In addition, a
|
||||||
|
<emphasis>Hibernate type</emphasis> describes various aspects of behavior of the Java type such as "how is
|
||||||
|
equality checked?" or "how are values cloned?".
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
A Hibernate type is neither a Java type nor a SQL datatype; it provides a information about both.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
When you encounter the term <emphasis>type</emphasis> in regards to Hibernate be aware that usage might
|
||||||
|
refer to the Java type, the SQL/JDBC type or the Hibernate type.
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Hibernate categorizes types into two high-level groups: value types (see <xref linkend="types.value"/>) and
|
||||||
|
entity types (see <xref linkend="types.entity"/>).
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<section id="types.value">
|
||||||
|
<title>Value types</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The main distinguishing characteristic of a value type is the fact that they do not define their own
|
||||||
|
lifecycle. We say that they are "owned" by something else (specifically an entity, as we will see later)
|
||||||
|
which defines their lifecycle. Value types are further classified into 3 sub-categories: basic types (see
|
||||||
|
<xref linkend="types.value.basic"/>), composite types (see <xref linkend="types.value.composite"/>)
|
||||||
|
amd collection types (see <xref linkend="types.value.collection"/>).
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<section id="types.value.basic">
|
||||||
|
<title>Basic value types</title>
|
||||||
|
<para>
|
||||||
|
The norm for basic value types is that they map a single database value (column) to a single,
|
||||||
|
non-aggregated Java type. Hibernate provides a number of built-in basic types, which we will present
|
||||||
|
in the following sections by the Java type. Mainly these follow the natural mappings recommended in the
|
||||||
|
JDBC specification. We will later cover how to override these mapping and how to provide and use
|
||||||
|
alternative type mappings.
|
||||||
|
</para>
|
||||||
|
<section id="types.value.basic.string">
|
||||||
|
<title>java.lang.String</title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.StringType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a string to the JDBC VARCHAR type. This is the standard mapping for a string if
|
||||||
|
no Hibernate type is specified.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>string</literal> and <literal>java.lang.String</literal>
|
||||||
|
in the type registry (see <xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.MaterializedClob</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a string to a JDBC CLOB type
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>materialized_clob</literal> in the type registry (see
|
||||||
|
<xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.TextType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a string to a JDBC LONGVARCHAR type
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>text</literal> in the type registry (see
|
||||||
|
<xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.basic.value.character">
|
||||||
|
<title><classname>java.lang.Character</classname> (or char primitive)</title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.CharacterType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a char or <classname>java.lang.Character</classname> to a JDBC CHAR
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>char</literal> and <literal>java.lang.Character</literal> in the
|
||||||
|
type registry (see <xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.value.basic.boolean">
|
||||||
|
<title><classname>java.lang.Boolean</classname> (or boolean primitive)</title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.BooleanType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a boolean to a JDBC BIT type
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>boolean</literal> and <literal>java.lang.Boolean</literal> in
|
||||||
|
the type registry (see <xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.NumericBooleanType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a boolean to a JDBC INTEGER type as 0 = false, 1 = true
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>numeric_boolean</literal> in the type registry (see
|
||||||
|
<xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.YesNoType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a boolean to a JDBC CHAR type as ('N' | 'n') = false, ( 'Y' | 'y' ) = true
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>yes_no</literal> in the type registry (see
|
||||||
|
<xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.TrueFalseType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a boolean to a JDBC CHAR type as ('F' | 'f') = false, ( 'T' | 't' ) = true
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>true_false</literal> in the type registry (see
|
||||||
|
<xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.basic.value.byte">
|
||||||
|
<title><classname>java.lang.Byte</classname> (or byte primitive)</title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.ByteType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a byte or <classname>java.lang.Byte</classname> to a JDBC TINYINT
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>byte</literal> and <literal>java.lang.Byte</literal> in the
|
||||||
|
type registry (see <xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.basic.value.short">
|
||||||
|
<title><classname>java.lang.Short</classname> (or short primitive)</title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.ShortType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a short or <classname>java.lang.Short</classname> to a JDBC SMALLINT
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>short</literal> and <literal>java.lang.Short</literal> in the
|
||||||
|
type registry (see <xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.basic.value.int">
|
||||||
|
<title><classname>java.lang.Integer</classname> (or int primitive)</title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.IntegerTypes</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps an int or <classname>java.lang.Integer</classname> to a JDBC INTEGER
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>int</literal> and <literal>java.lang.Integer</literal>in the
|
||||||
|
type registry (see <xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.basic.value.long">
|
||||||
|
<title><classname>java.lang.Long</classname> (or long primitive)</title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.LongType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a long or <classname>java.lang.Long</classname> to a JDBC BIGINT
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>long</literal> and <literal>java.lang.Long</literal> in the
|
||||||
|
type registry (see <xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.basic.value.float">
|
||||||
|
<title><classname>java.lang.Float</classname> (or float primitive)</title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.FloatType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a float or <classname>java.lang.Float</classname> to a JDBC FLOAT
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>float</literal> and <literal>java.lang.Float</literal> in the
|
||||||
|
type registry (see <xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.basic.value.double">
|
||||||
|
<title><classname>java.lang.Double</classname> (or double primitive)</title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.DoubleType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a double or <classname>java.lang.Double</classname> to a JDBC DOUBLE
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>double</literal> and <literal>java.lang.Double</literal> in the
|
||||||
|
type registry (see <xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.basic.value.biginteger">
|
||||||
|
<title><classname>java.math.BigInteger</classname></title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.BigIntegerType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a <classname>java.math.BigInteger</classname> to a JDBC NUMERIC
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>big_integer</literal> and <literal>java.math.BigInteger</literal> in the
|
||||||
|
type registry (see <xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.basic.value.bigdecimal">
|
||||||
|
<title><classname>java.math.BigDecimal</classname></title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.BigDecimalType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a <classname>java.math.BigDecimal</classname> to a JDBC NUMERIC
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>big_decimal</literal> and <literal>java.math.BigDecimal</literal> in the
|
||||||
|
type registry (see <xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.basic.value.timestamp">
|
||||||
|
<title><classname>java.util.Date</classname> or <classname>java.sql.Timestamp</classname></title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.TimestampType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a <classname>java.sql.Timestamp</classname> to a JDBC TIMESTAMP
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>timestamp</literal>, <literal>java.sql.Timestamp</literal> and
|
||||||
|
<literal>java.util.Date</literal> in the type registry (see <xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.basic.value.time">
|
||||||
|
<title><classname>java.sql.Time</classname></title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.TimeType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a <classname>java.sql.Time</classname> to a JDBC TIME
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>time</literal> and <literal>java.sql.Time</literal> in the
|
||||||
|
type registry (see <xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.basic.value.date">
|
||||||
|
<title><classname>java.sql.Date</classname></title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.DateType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a <classname>java.sql.Date</classname> to a JDBC DATE
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>date</literal> and <literal>java.sql.Date</literal> in the
|
||||||
|
type registry (see <xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.basic.value.calendar">
|
||||||
|
<title><classname>java.util.Calendar</classname></title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.CalendarType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a <classname>java.util.Calendar</classname> to a JDBC TIMESTAMP
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>calendar</literal>, <literal>java.util.Calendar</literal> and
|
||||||
|
<literal>java.util.GregorianCalendar</literal> in the type registry (see
|
||||||
|
<xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.CalendarDateType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a <classname>java.util.Calendar</classname> to a JDBC DATE
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>calendar_date</literal> in the type registry (see
|
||||||
|
<xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.basic.value.currency">
|
||||||
|
<title><classname>java.util.Currency</classname></title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.CurrencyType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a <classname>java.util.Currency</classname> to a JDBC VARCHAR (using the Currency code)
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>currency</literal> and <literal>java.util.Currency</literal> in the
|
||||||
|
type registry (see <xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.basic.value.locale">
|
||||||
|
<title><classname>java.util.Locale</classname></title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.LocaleType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a <classname>java.util.Locale</classname> to a JDBC VARCHAR (using the Locale code)
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>locale</literal> and <literal>java.util.Locale</literal> in the
|
||||||
|
type registry (see <xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.basic.value.timezone">
|
||||||
|
<title><classname>java.util.TimeZone</classname></title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.TimeZoneType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a <classname>java.util.TimeZone</classname> to a JDBC VARCHAR (using the TimeZone ID)
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>timezone</literal> and <literal>java.util.TimeZone</literal> in the
|
||||||
|
type registry (see <xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.basic.value.class">
|
||||||
|
<title><classname>java.lang.Class</classname></title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.ClassType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a <classname>java.lang.Class</classname> to a JDBC VARCHAR (using the Class name)
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>class</literal> and <literal>java.lang.Class</literal> in the
|
||||||
|
type registry (see <xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.basic.value.blob">
|
||||||
|
<title><classname>java.sql.Blob</classname></title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.BlobType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a <classname>java.sql.Blob</classname> to a JDBC BLOB
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>blob</literal> and <literal>java.sql.Blob</literal> in the
|
||||||
|
type registry (see <xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.basic.value.clob">
|
||||||
|
<title><classname>java.sql.Clob</classname></title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.ClobType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a <classname>java.sql.Clob</classname> to a JDBC CLOB
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>clob</literal> and <literal>java.sql.Clob</literal> in the
|
||||||
|
type registry (see <xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.basic.value.binary">
|
||||||
|
<title>byte[]</title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.BinaryType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a primitive byte[] to a JDBC VARBINARY
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>binary</literal> and <literal>byte[]</literal> in the
|
||||||
|
type registry (see <xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.MaterializedBlobType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a primitive byte[] to a JDBC BLOB
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>materialized_blob</literal> in the type registry (see
|
||||||
|
<xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.basic.value.wrapperbinary">
|
||||||
|
<title>byte[]</title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.BinaryType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a java.lang.Byte[] to a JDBC VARBINARY
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>wrapper-binary</literal>, <literal>Byte[]</literal> and
|
||||||
|
<literal>java.lang.Byte[]</literal> in the type registry (see <xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.basic.value.chararray">
|
||||||
|
<title>char[]</title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.CharArrayType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a char[] to a JDBC VARCHAR
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>characters</literal> and <literal>char[]</literal>
|
||||||
|
in the type registry (see <xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.basic.value.characterarray">
|
||||||
|
<title>char[]</title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.CharacterArrayType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps a java.lang.Character[] to a JDBC VARCHAR
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Registered under <literal>wrapper-characters</literal>, <literal>Character[]</literal>
|
||||||
|
and <literal>java.lang.Character[]</literal> in the type registry (see <xref linkend="types.registry"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
<section id="types.basic.value.serializable">
|
||||||
|
<title>java.io.Serializable</title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><classname>org.hibernate.type.SerializableType</classname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maps implementors of java.lang.Serializable to a JDBC VARBINARY
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Unlike the other value types, there are multiple instances of this type. It
|
||||||
|
gets registered once under <literal>java.io.Serializable</literal>. Additionally it
|
||||||
|
gets registered under the specific <interfacename>java.io.Serializable</interfacename>
|
||||||
|
implementation class names.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="types.value.composite">
|
||||||
|
<title>Composite types</title>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
The Java Persistence API calls these embedded types, while Hibernate traditionally called them
|
||||||
|
components. Just be aware that both terms are used and mean the same thing in the scope of
|
||||||
|
discussing Hibernate.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
<para>
|
||||||
|
Components represent aggregations of values into a single Java type. For example, you might have
|
||||||
|
an Address class that aggregates street, city, state, etc information or a Name class that
|
||||||
|
aggregates the parts of a person's Name. In many ways a component looks exactly like an entity. They
|
||||||
|
are both (generally speaking) classes written specifically for the application. They both might have
|
||||||
|
references to other application-specific classes, as well as to collections and simple JDK types. As
|
||||||
|
discussed before, the only distinguishing factory is the fact that a component does not own its own
|
||||||
|
lifecycle.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="types.value.collection">
|
||||||
|
<title>Collection types</title>
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
It is critical understand that we mean the collection itself, not its contents.
|
||||||
|
The contents of the collection can in turn be basic, component or entity types (though not
|
||||||
|
collections), but the collection itself is owned.
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
<para>
|
||||||
|
Collections are covered in <xref linkend="collections"/>.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="types.entity">
|
||||||
|
<title>Entity types</title>
|
||||||
|
<para>
|
||||||
|
The definition of entities is covered in detail in <xref linkend="persistent-classes"/>. For the purpose of
|
||||||
|
this discussion, it is enough to say that entities are (generally application-specific) classes which
|
||||||
|
correlate to rows in a table. Specifically they correlate to the row by means of a unique identifier.
|
||||||
|
Because of this unique identifier, entities exist independently and define their own lifecycle. As an example,
|
||||||
|
when we delete a <classname>Membership</classname>, both the <classname>User</classname> and
|
||||||
|
<classname>Group</classname> entities remain.
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
This notion of entity independence can be modified by the application developer using the concept of
|
||||||
|
cascades. Cascades allow certain operations to continue (or "cascade") across an association from
|
||||||
|
one entity to another. Cascades are covered in detail in <xref linkend="associations"/>.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="types.category.significance">
|
||||||
|
<title>Significance of type categories</title>
|
||||||
|
<para>
|
||||||
|
Why do we spend so much time categorizing the various types of types? What is the significance of the
|
||||||
|
distinction?
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The main categorization was between entity types and value types. To review we said that entities, by
|
||||||
|
nature of their unique identifier, exist independently of other objects whereas values do not. An
|
||||||
|
application cannot "delete" a Product sku; instead, the sku is removed when the Product itself is
|
||||||
|
deleted (obviously you can <emphasis>update</emphasis> the sku of that Product to null to maker it
|
||||||
|
"go away", but even there the access is done through the Product).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Nor can you define an association <emphasis>to</emphasis> that Product sku. You <emphasis>can</emphasis>
|
||||||
|
define an association to Product <emphasis>based on</emphasis> its sku, assuming sku is unique but that
|
||||||
|
is totally different.
|
||||||
|
|
||||||
|
|
||||||
|
entity types define
|
||||||
|
data that maintains its own lifecycle, while value types define data that only exists dependently. Essentially it defines it own unique identifier. In turn that means
|
||||||
|
that it can be used to share references to that data from other entities (or components or collections).
|
||||||
|
This dependence/independence has a few important ramifications:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
First, entities can be looked up and referenced (as in foreign keys). The same is not true of
|
||||||
|
a value type. For example, a <classname>Product</classname> entity can be looked up by its
|
||||||
|
unique identifier. The sku of that Product
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="types.custom">
|
||||||
|
<title>Custom types</title>
|
||||||
|
<para>
|
||||||
|
Hibernate makes it relatively easy for developers to create their own <emphasis>value</emphasis> types. For
|
||||||
|
example, you might want to persist properties of type <classname>java.lang.BigInteger</classname> to
|
||||||
|
<literal>VARCHAR</literal> columns. Custom types are not limited to mapping values to a single table
|
||||||
|
column. So, for example, you might want to concatenate together <literal>FIRST_NAME</literal>,
|
||||||
|
<literal>INITIAL</literal> and <literal>SURNAME</literal> columsn into a <classname>java,lang.String</classname>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
There are 3 approaches to developing a custom Hibernate type. As a means of illustrating the different
|
||||||
|
approaches, lets consider a use case where we need to compose a <classname>java.math.BigDecimal</classname>
|
||||||
|
and <classname>java.util.Currency</classname> together into a custom <classname>Money</classname> class.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<section id="types.custom.type">
|
||||||
|
<title>Custom types using <interfacename>org.hibernate.type.Type</interfacename></title>
|
||||||
|
<para>
|
||||||
|
The first approach is to directly implement the <interfacename>org.hibernate.type.Type</interfacename>
|
||||||
|
interface (or one of its derivatives). Probably, you will be more interested in the more specific
|
||||||
|
<interfacename>org.hibernate.type.BasicType</interfacename> contract which would allow registration of
|
||||||
|
the type (see <xref linkend="types.registry"/>). The benefit of this registration is that whenever
|
||||||
|
the metadata for a particular property does not specify the Hibernate type to use, Hibernate will
|
||||||
|
consult the registry for the exposed property type. In our example, the property type would be
|
||||||
|
<classname>Money</classname>, which is the key we would use to register our type in the registry:
|
||||||
|
<example id="types.custom.type.ex.definition">
|
||||||
|
<title>Defining and registering the custom Type</title>
|
||||||
|
<programlisting role="JAVA"><![CDATA[public class MoneyType implements BasicType {
|
||||||
|
public String[] getRegistrationKeys() {
|
||||||
|
return new String[] { Money.class.getName() };
|
||||||
|
}
|
||||||
|
|
||||||
|
public int[] sqlTypes(Mapping mapping) {
|
||||||
|
// We will simply use delegation to the standard basic types for BigDecimal and Currency for many of the
|
||||||
|
// Type methods...
|
||||||
|
return new int[] {
|
||||||
|
BigDecimalType.INSTANCE.sqlType(),
|
||||||
|
CurrencyType.INSTANCE.sqlType(),
|
||||||
|
};
|
||||||
|
// we could also have honored any registry overrides via...
|
||||||
|
//return new int[] {
|
||||||
|
// mappings.getTypeResolver().basic( BigDecimal.class.getName() ).sqlTypes( mappings )[0],
|
||||||
|
// mappings.getTypeResolver().basic( Currency.class.getName() ).sqlTypes( mappings )[0]
|
||||||
|
//};
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class getReturnedClass() {
|
||||||
|
return Money.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws SQLException {
|
||||||
|
assert names.length == 2;
|
||||||
|
BigDecimal amount = BigDecimalType.INSTANCE.get( names[0] ); // already handles null check
|
||||||
|
Currency currency = CurrencyType.INSTANCE.get( names[1] ); // already handles null check
|
||||||
|
return amount == null && currency == null
|
||||||
|
? null
|
||||||
|
: new Money( amount, currency );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void nullSafeSet(PreparedStatement st, Object value, int index, boolean[] settable, SessionImplementor session)
|
||||||
|
throws SQLException {
|
||||||
|
if ( value == null ) {
|
||||||
|
BigDecimalType.INSTANCE.set( st, null, index );
|
||||||
|
CurrencyType.INSTANCE.set( st, null, index+1 );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final Money money = (Money) value;
|
||||||
|
BigDecimalType.INSTANCE.set( st, money.getAmount(), index );
|
||||||
|
CurrencyType.INSTANCE.set( st, money.getCurrency(), index+1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
...
|
||||||
|
}]]></programlisting>
|
||||||
|
<programlisting role="JAVA">
|
||||||
|
Configuration cfg = new Configuration();
|
||||||
|
cfg.registerTypeOverride( new MoneyType() );
|
||||||
|
cfg...;
|
||||||
|
</programlisting>
|
||||||
|
</example>
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
It is important that we registered the type <emphasis>before</emphasis> adding mappings.
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="types.custom.ut">
|
||||||
|
<title>Custom types using <interfacename>org.hibernate.usertype.UserType</interfacename></title>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
Both <interfacename>org.hibernate.usertype.UserType</interfacename> and
|
||||||
|
<interfacename>org.hibernate.usertype.CompositeUserType</interfacename> were originally
|
||||||
|
added to isolate user code from internal changes to the <interfacename>org.hibernate.type.Type</interfacename>
|
||||||
|
interfaces.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
<para>
|
||||||
|
The second approach is the use the <interfacename>org.hibernate.usertype.UserType</interfacename>
|
||||||
|
interface, which presents a somewhat simplified view of the <interfacename>org.hibernate.type.Type</interfacename>
|
||||||
|
interface. Using a <interfacename>org.hibernate.usertype.UserType</interfacename>, our
|
||||||
|
<classname>Money</classname> custom type would look as follows:
|
||||||
|
</para>
|
||||||
|
<example id="types.custom.ut.ex.definition">
|
||||||
|
<title>Defining the custom UserType</title>
|
||||||
|
<programlisting role="JAVA"><![CDATA[public class MoneyType implements UserType {
|
||||||
|
public int[] sqlTypes() {
|
||||||
|
return new int[] {
|
||||||
|
BigDecimalType.INSTANCE.sqlType(),
|
||||||
|
CurrencyType.INSTANCE.sqlType(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class getReturnedClass() {
|
||||||
|
return Money.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws SQLException {
|
||||||
|
assert names.length == 2;
|
||||||
|
BigDecimal amount = BigDecimalType.INSTANCE.get( names[0] ); // already handles null check
|
||||||
|
Currency currency = CurrencyType.INSTANCE.get( names[1] ); // already handles null check
|
||||||
|
return amount == null && currency == null
|
||||||
|
? null
|
||||||
|
: new Money( amount, currency );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void nullSafeSet(PreparedStatement st, Object value, int index) throws SQLException {
|
||||||
|
if ( value == null ) {
|
||||||
|
BigDecimalType.INSTANCE.set( st, null, index );
|
||||||
|
CurrencyType.INSTANCE.set( st, null, index+1 );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final Money money = (Money) value;
|
||||||
|
BigDecimalType.INSTANCE.set( st, money.getAmount(), index );
|
||||||
|
CurrencyType.INSTANCE.set( st, money.getCurrency(), index+1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
...
|
||||||
|
}]]></programlisting>
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
There is not much difference between the <interfacename>org.hibernate.type.Type</interfacename> example
|
||||||
|
and the <interfacename>org.hibernate.usertype.UserType</interfacename> example, but that is only because
|
||||||
|
of the snippets shown. If you choose the <interfacename>org.hibernate.type.Type</interfacename> approach
|
||||||
|
there are quite a few more methods you would need to implement as compared to the
|
||||||
|
<interfacename>org.hibernate.usertype.UserType</interfacename>.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="types.custom.cut">
|
||||||
|
<title>Custom types using <interfacename>org.hibernate.usertype.CompositeUserType</interfacename></title>
|
||||||
|
<para>
|
||||||
|
The third and final approach is the use the <interfacename>org.hibernate.usertype.CompositeUserType</interfacename>
|
||||||
|
interface, which differs from <interfacename>org.hibernate.usertype.UserType</interfacename> in that it
|
||||||
|
gives us the ability to provide Hibernate the information to handle the composition within the
|
||||||
|
<classname>Money</classname> class (specifically the 2 attributes). THis would give us the capability,
|
||||||
|
for example, to reference the <literal>amount</literal> attribute in an HQL query. Using a
|
||||||
|
<interfacename>org.hibernate.usertype.UserType</interfacename>, our <classname>Money</classname> custom
|
||||||
|
type would look as follows:
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<example id="types.custom.cut.ex.definition">
|
||||||
|
<title>Defining the custom CompositeUserType</title>
|
||||||
|
<programlisting role="JAVA"><![CDATA[public class MoneyType implements CompositeUserType {
|
||||||
|
public String[] getPropertyNames() {
|
||||||
|
// ORDER IS IMPORTANT! it must match the order the columns are defined in the property mapping
|
||||||
|
return new String[] { "amount", "currency" };
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type[] getPropertyTypes() {
|
||||||
|
return new Type[] { BigDecimalType.INSTANCE, CurrencyType.INSTANCE };
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class getReturnedClass() {
|
||||||
|
return Money.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getPropertyValue(Object component, int propertyIndex) {
|
||||||
|
if ( component == null ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Money money = (Money) component;
|
||||||
|
switch ( propertyIndex ) {
|
||||||
|
case 0: {
|
||||||
|
return money.getAmount();
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
return money.getCurrency();
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw new HibernateException( "Invalid property index [" + propertyIndex + "]" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPropertyValue(Object component, int propertyIndex, Object value) throws HibernateException {
|
||||||
|
if ( component == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Money money = (Money) component;
|
||||||
|
switch ( propertyIndex ) {
|
||||||
|
case 0: {
|
||||||
|
money.setAmount( (BigDecimal) value );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
money.setCurrency( (Currency) value );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw new HibernateException( "Invalid property index [" + propertyIndex + "]" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws SQLException {
|
||||||
|
assert names.length == 2;
|
||||||
|
BigDecimal amount = BigDecimalType.INSTANCE.get( names[0] ); // already handles null check
|
||||||
|
Currency currency = CurrencyType.INSTANCE.get( names[1] ); // already handles null check
|
||||||
|
return amount == null && currency == null
|
||||||
|
? null
|
||||||
|
: new Money( amount, currency );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws SQLException {
|
||||||
|
if ( value == null ) {
|
||||||
|
BigDecimalType.INSTANCE.set( st, null, index );
|
||||||
|
CurrencyType.INSTANCE.set( st, null, index+1 );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final Money money = (Money) value;
|
||||||
|
BigDecimalType.INSTANCE.set( st, money.getAmount(), index );
|
||||||
|
CurrencyType.INSTANCE.set( st, money.getCurrency(), index+1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
...
|
||||||
|
}]]></programlisting>
|
||||||
|
</example>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="types.registry">
|
||||||
|
<title>Type registry</title>
|
||||||
|
<para>
|
||||||
|
Internally Hibernate uses a registry of basic types (see <xref linkend="types.value.basic"/>) when
|
||||||
|
it needs to resolve the specific <interfacename>org.hibernate.type.Type</interfacename> to use in certain
|
||||||
|
situations. It also provides a way for applications to add extra basic type registrations as well as
|
||||||
|
override the standard basic type registrations.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To register a new type or to override an existing type registration, applications would make use of the
|
||||||
|
<methodname>registerTypeOverride</methodname> method of the <classname>org.hibernate.cfg.Configuration</classname>
|
||||||
|
class when bootstrapping Hibernate. For example, lets say you want Hibernate to use your custom
|
||||||
|
<classname>SuperDuperStringType</classname>; during bootstrap you would call:
|
||||||
|
<example id="type.registry.override.ex">
|
||||||
|
<title>Overriding the standard <classname>StringType</classname></title>
|
||||||
|
<programlisting role="JAVA"><![CDATA[Configuration cfg = ...;
|
||||||
|
cfg.registerTypeOverride( new SuperDuperStringType() );]]></programlisting>
|
||||||
|
</example>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The argument to <methodname>registerTypeOverride</methodname> is a <interfacename>org.hibernate.type.BasicType</interfacename>
|
||||||
|
which is a specialization of the <interfacename>org.hibernate.type.Type</interfacename> we saw before. It
|
||||||
|
adds a single method:
|
||||||
|
<example>
|
||||||
|
<title>Snippet from BasicType.java</title>
|
||||||
|
<programlisting role="JAVA" >
|
||||||
|
/**
|
||||||
|
* Get the names under which this type should be registered in the type registry.
|
||||||
|
*
|
||||||
|
* @return The keys under which to register this type.
|
||||||
|
*/
|
||||||
|
public String[] getRegistrationKeys();
|
||||||
|
</programlisting>
|
||||||
|
</example>
|
||||||
|
One approach is to use inheritance (<classname>SuperDuperStringType</classname> extends
|
||||||
|
<classname>org.hibernate.typeStringType</classname>). Another approach is to use delegation.
|
||||||
|
</para>
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
Currently UserType and CompositeUserType cannot be registered with the registry. See
|
||||||
|
<ulink url="http://opensource.atlassian.com/projects/hibernate/browse/HHH-5262"/> for details.
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</chapter>
|
Loading…
Reference in New Issue