O'Reilly    
 Published on O'Reilly (http://oreilly.com/)
 See this if you're having trouble printing code examples


Hibernate Types: Appendix A - Harnessing Hibernate

by James Elliott, Timothy M. O'Brien, Ryan Fowler

Hibernate makes a fundamental distinction between two different kinds of data in terms of how they relate to the persistence service: entities and values.

Harnessing Hibernate book cover

This excerpt is from Harnessing Hibernate . This guide is an ideal introduction to Hibernate, the framework that lets Java developers work with information from a relational database easily and efficiently. Databases are a very different world than Java objects, and with Hibernate, bridging them is significantly easier. This new edition lets you explore the system, from download and configuration through a series of projects that demonstrate how to accomplish a variety of practical goals.

buy button

An entity is something with its own independent existence, regardless of whether it’s currently reachable by any object within a Java virtual machine. Entities can be retrieved from the database through queries, and they must be explicitly saved and deleted by the application. (If cascading relationships have been set up, the act of saving or deleting a parent entity can also save or delete its children, but this is still explicit at the level of the parent.)

Values are stored only as part of the persistent state of an entity. They have no independent existence. They might be primitives, collections, enumerations, or custom user types. Since they are entirely subordinated to the entity in which they exist, they cannot be independently versioned, nor can they be shared by more than one entity or collection.

Notice that a particular Java object might be either an entity or a value—the difference is in how it is designed and presented to the persistence service. Primitive Java types are always values.

Basic Types

Here is a smattering of information about the built-in types, showing how they relate Java classes to SQL column types. We present samples of the variability between databases, but are not trying to show every variant; check out the source code for all the dialect implementations in org.hibernate.dialect for the definitive details (look for registerColumnType⁠⁠(⁠ ⁠) calls).

Hibernate’s basic types fall into a number of groupings:

Simple numeric and Boolean types

These correspond to the primitive Java types that represent numbers, characters, and Boolean values, or their wrapper classes. They get mapped to appropriate SQL column types (based on the SQL dialect in use). They are: boolean, byte, character, double, float, integer, long, short, true_false, and yes_no. The last two are alternate ways to represent a Boolean value within the database; true_false uses the values “T” and “F,” whereas yes_no uses “Y” and “N.”

String type

The Hibernate type string maps from java.lang.String to the appropriate string column type for the SQL dialect (usually VARCHAR, but in Oracle VARCHAR2 is used).

Time types

Hibernate uses date, time, and timestamp to map from java.util.Date (and subclasses) to appropriate SQL types (e.g., DATE, TIME, TIMESTAMP). The timestamp implementation uses the current time within the Java environment; you can use the database’s notion of the current time instead by using dbtimestamp.

If you prefer working with the more convenient java.util.Calendar class, there is no need to translate to and from Date values in your own code; you can map it directly with calendar (which stores the date and time as a TIMESTAMP) or calendar_date (which considers only the date, as a DATE column).

Arbitrary precision numeric

The Hibernate type big_decimal provides a mapping between java.math.BigDecimal to the appropriate SQL type (usually NUMERIC, but Oracle uses NUMBER). Hibernate’s big_integer maps java.math.BigInteger (usually to BIGINT, but Informix calls it INT8 and Oracle again uses NUMBER).

Localization values

The types locale, timezone, and currency are stored as strings (VARCHAR or VARCHAR2, as noted above), and mapped to the Locale, TimeZone, and Currency classes in the java.util package. Locale and Currency are stored using their ISO codes, while TimeZone is stored using its ID property.

Class names

The type class maps instances of java.lang.Class using their fully qualified names, stored in a string column (VARCHAR, or VARCHAR2 in Oracle).

Byte arrays

The type binary stores byte arrays in an appropriate SQL binary type.

Any serializable object

The type serializable can be used to map any serializable Java object into a SQL binary column. This is the fallback type used when attempting to persist an object that doesn’t have a more specific appropriate mapping (and for which you do not want to implement a UserType custom mapping; see the next section). The SQL column type is the same as is used for binary, described later.

JDBC large objects

The types blob and clob provide mappings for the Blob and Clob classes in the java.sql package. If you are dealing with truly large values, your best bet is to declare the properties as either Blob or Clob—even though this introduces an explicit JDBC dependency to your data object, it easily allows Hibernate to leverage JDBC features to lazily load the property value only if you need it.

If you are not worried that the data is too huge, you can spare yourself this direct JDBC interface, declare the property type as String or byte[ ], and map it using text or binary. These correspond to SQL column types of CLOB and VARBINARY (RAW in Oracle, BYTEA in PostgreSQL), respectively, and the values are loaded immediately into the properties when the object is loaded.

Custom Value Types

In addition to mapping your objects as entities, you can also create classes that are mapped to the database as values within other entities, without their own independent existence. This can be as simple as changing the way an existing type is mapped (because you want to use a different column type or representation), or as complex as splitting a value across multiple columns.

Although you can do this on a case-by-case basis within your mapping documents, the principle of avoiding repeated code argues for encapsulating types you use in more than one place into an actual reusable class. Your class will implement either org.hibernate.UserType or org.hibernate.CompositeUserType. This technique is illustrated in Chapter 6.

This is also how you map Java 5’s enum types (and hand-coded instances of the type-safe enumeration pattern in from previous Java versions). You can use a single, reusable custom type mapping for all enumerations, as discussed in Chapter 6.

“Any” Type Mappings

This final kind of mapping is very much a free-for-all. Essentially, it allows you to map references to any of your other mapped entities interchangeably. This is done by providing two columns, one which contains the name of the table to which each reference is being made, and another which provides the ID within that table of the specific entity of interest.

You can’t maintain any sort of foreign key constraints in such a loose relationship. It’s rare to need this kind of mapping at all. One situation in which you might find it useful is if you want to maintain an audit log that can contain actual objects. The reference manual also mentions web application session data as another potential use, but that seems unlikely in a well-structured application.

All Types

The following table shows each of the type classes in the org.hibernate.types package, along with the type name you would use for it in a mapping document, the most common SQL type(s) used in columns storing mapped values, and any relevant comments about its purpose. In many cases, more detailed discussion can be found earlier. To save space, the “Type” that appears at the end of each class name has been removed, except in the case of the Type interface implemented by all the others.

Type classType nameSQL typeNotes
AbstractBynary (perhaps a pun on byte/binary/array?)N/AN/AEncapsulates the code used to bind streams of bytes into VARBINARY-style columns
AbstractCharArray N/AN/AEncapsulates the code used to bind streams of characters into VARCHAR-style columns
AbstractComponent (interface)N/AN/ALets Component types store collections, have cascades, etc.
Abstract N/AN/AAbstract skeleton used by the built-in types
Any any N/ASupports “any“ type mappings
Array array N/AMaps a Java array as a persistent collection
Association (interface)N/AN/ASupports associations between entities
Bag bag N/AMaps collections with bag semantics
BigDecimal big_decimal NUMERIC In Oracle, SQL type is NUMBER
BigInteger big_integer BIGINT In Oracle, SQL type is NUMBER; Informix uses INT8.
Binary binary VARBINARY Basic type for byte arrays, eagerly fetched (see above)
Blob blob BLOB Link to JDBC support for lazily loaded byte arrays
Boolean boolean BIT A basic and primitive type
Byte byte TINYINT A basic and primitive type
CalendarDate calendar_date DATE Maps Calendar, ignoring time
Calendar calendar TIMESTAMP Maps Calendar, including time
Character character CHAR A basic and primitive type
CharacterArray N/A VARCHAR Maps Character[ ] properties
CharArray N/A VARCHAR Maps char[ ] properties
CharBoolean N/A CHAR Abstract skeleton used to implement yes_no and true_false types
Class class VARCHAR or VARCHAR2Basic type that stores a class’ name
Clob clob CLOB Link to JDBC support for lazily loaded char arrays
Collection N/AN/ASupports all persistent collection types
Component component N/AMaps the properties of a contained value class on to a group of columns
CompositeCustom N/AN/AAdapts CompositeUserType implementations to the Type interface
Currency currency VARCHAR or VARCHAR2Stores ISO code for a currency
Custom N/AN/AAdapts UserType implementations to the Type interface
Date date DATE A basic type
DbTimestamp dbtimestamp TIMESTAMP A basic type, uses database notion of “now”
Discriminator (interface)N/AN/AMarker interface for types that can be used for discriminator properties (to select the right mapped subclass)
Double double DOUBLE A basic and primitive type
EmbeddedComponent composite - element N/ASpecializes ComponentType for declaration within a mapping
Entity N/AN/ARepresents a reference to another entity
Float float FLOAT A basic and primitive type
Identifier (interface) id N/AMarker interface for types that store identifiers of entities
IdentifierBag idbag N/AMaps a Collection with bag semantics and surrogate identifier column
Immutable N/AN/AAbstract superclass for immutable types; extends NullableType
Integer integer INTEGER A basic and primitive type
List list N/AMaps a Java List
Literal (interface)N/AN/AMarker interface for types that store SQL literals
Locale locale VARCHAR or VARCHAR2Stores ISO code for a locale
Long long LONG A basic and primitive type
ManyToOne many-to-one N/AAn association between entities
Map map N/AMaps a Java Map
Meta meta-type N/AStores discriminator values for polymorphic mapping using any
Mutable N/AN/AAbstract superclass for mutable types
Nullable N/AN/AAbstract superclass for simple, one column types that can be null
OneToOne one-to-one N/AAn association between entities
OrderedMap N/AN/AExtension of MapType to preserve SQL ordering
OrderedSet N/AN/AExtension of SetType to preserve SQL ordering
Primitive N/AN/AAbstract skeleton for mapping primitive Java types; extends ImmutableType
Serializable serializable Binary (see JDBC Large Objects earlier)Catch-all mapping for serializable classes with no better alternative
Set set N/AMaps a Java Set
Short short SMALLINT A basic and primitive type
SortedMap N/AN/AExtension of MapType to use Java Collections ordering
SortedSet N/AN/AExtension of SetType to use Java Collections ordering
String string VARCHAR or VARCHAR2A basic type
Text text CLOB Eagerly fetches a CLOB into a String property (see above)
Time time TIME A basic type
TimeZone timezone VARCHAR or VARCHAR2Stores time zone ID
Timestamp timestamp TIMESTAMP A basic type, uses JVM notion of “now”
TrueFalse true_false CHAR Stores Booleans as “T” or “F”
Type (interface)N/AN/ASuperinterface of all these types
Version (interface)N/AN/AExtends Type for version stamping
WrapperBinary N/AN/ASeems unfinished
YesNo yes_no CHAR Stores Booleans as “Y” or “N”

There is also a TypeFactory class which provides assistance in building the right Type implementation for a given need, such as when parsing a type name in a mapping document. Reading its source is interesting.

If you enjoyed this excerpt, buy a copy of Harnessing Hibernate .

Copyright © 2009 O'Reilly Media, Inc.