Hibernate.orgCommunity Documentation
Table of Contents
        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 Product
        object with a number of attributes such as a sku, name, 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 Hibernate type, which is an implementation of the
        org.hibernate.type.Type interface.  In addition, a
        Hibernate type describes various aspects of behavior of the Java type such as "how is
        equality checked?" or "how are values cloned?".
    
A Hibernate type is neither a Java type nor a SQL datatype; it provides a information about both.
When you encounter the term type in regards to Hibernate be aware that usage might refer to the Java type, the SQL/JDBC type or the Hibernate type.
Hibernate categorizes types into two high-level groups: value types (see Section 6.1, “Value types”) and entity types (see Section 6.2, “Entity types”).
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 Section 6.1.1, “Basic value types”), composite types (see Section 6.1.2, “Composite types”) amd collection types (see Section 6.1.3, “Collection types”).
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.
org.hibernate.type.StringTypeMaps a string to the JDBC VARCHAR type. This is the standard mapping for a string if no Hibernate type is specified.
                                Registered under string and java.lang.String
                                in the type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.MaterializedClobMaps a string to a JDBC CLOB type
                                Registered under materialized_clob in the type registry (see
                                Section 6.5, “Type registry”).
                            
org.hibernate.type.TextTypeMaps a string to a JDBC LONGVARCHAR type
                                Registered under text in the type registry (see
                                Section 6.5, “Type registry”).
                            
org.hibernate.type.CharacterType
                                Maps a char or java.lang.Character to a JDBC CHAR
                            
                                Registered under char and java.lang.Character in the
                                type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.BooleanTypeMaps a boolean to a JDBC BIT type
                                Registered under boolean and java.lang.Boolean in
                                the type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.NumericBooleanTypeMaps a boolean to a JDBC INTEGER type as 0 = false, 1 = true
                                Registered under numeric_boolean in the type registry (see
                                Section 6.5, “Type registry”).
                            
org.hibernate.type.YesNoTypeMaps a boolean to a JDBC CHAR type as ('N' | 'n') = false, ( 'Y' | 'y' ) = true
                                Registered under yes_no in the type registry (see
                                Section 6.5, “Type registry”).
                            
org.hibernate.type.TrueFalseTypeMaps a boolean to a JDBC CHAR type as ('F' | 'f') = false, ( 'T' | 't' ) = true
                                Registered under true_false in the type registry (see
                                Section 6.5, “Type registry”).
                            
org.hibernate.type.ByteType
                                Maps a byte or java.lang.Byte to a JDBC TINYINT
                            
                                Registered under byte and java.lang.Byte in the
                                type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.ShortType
                                Maps a short or java.lang.Short to a JDBC SMALLINT
                            
                                Registered under short and java.lang.Short in the
                                type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.IntegerTypes
                                Maps an int or java.lang.Integer to a JDBC INTEGER
                            
                                Registered under int and java.lang.Integerin the
                                type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.LongType
                                Maps a long or java.lang.Long to a JDBC BIGINT
                            
                                Registered under long and java.lang.Long in the
                                type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.FloatType
                                Maps a float or java.lang.Float to a JDBC FLOAT
                            
                                Registered under float and java.lang.Float in the
                                type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.DoubleType
                                Maps a double or java.lang.Double to a JDBC DOUBLE
                            
                                Registered under double and java.lang.Double in the
                                type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.BigIntegerType
                                Maps a java.math.BigInteger to a JDBC NUMERIC
                            
                                Registered under big_integer and java.math.BigInteger in the
                                type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.BigDecimalType
                                Maps a java.math.BigDecimal to a JDBC NUMERIC
                            
                                Registered under big_decimal and java.math.BigDecimal in the
                                type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.TimestampType
                                Maps a java.sql.Timestamp to a JDBC TIMESTAMP
                            
                                Registered under timestamp, java.sql.Timestamp and
                                java.util.Date in the type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.TimeType
                                Maps a java.sql.Time to a JDBC TIME
                            
                                Registered under time and java.sql.Time in the
                                type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.DateType
                                Maps a java.sql.Date to a JDBC DATE
                            
                                Registered under date and java.sql.Date in the
                                type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.CalendarType
                                Maps a java.util.Calendar to a JDBC TIMESTAMP
                            
                                Registered under calendar, java.util.Calendar and
                                java.util.GregorianCalendar in the type registry (see
                                Section 6.5, “Type registry”).
                            
org.hibernate.type.CalendarDateType
                                Maps a java.util.Calendar to a JDBC DATE
                            
                                Registered under calendar_date in the type registry (see
                                Section 6.5, “Type registry”).
                            
org.hibernate.type.CurrencyType
                                Maps a java.util.Currency to a JDBC VARCHAR (using the Currency code)
                            
                                Registered under currency and java.util.Currency in the
                                type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.LocaleType
                                Maps a java.util.Locale to a JDBC VARCHAR (using the Locale code)
                            
                                Registered under locale and java.util.Locale in the
                                type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.TimeZoneType
                                Maps a java.util.TimeZone to a JDBC VARCHAR (using the TimeZone ID)
                            
                                Registered under timezone and java.util.TimeZone in the
                                type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.UrlType
                                Maps a java.net.URL to a JDBC VARCHAR (using the external form)
                            
                                Registered under url and java.net.URL in the
                                type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.ClassType
                                Maps a java.lang.Class to a JDBC VARCHAR (using the Class name)
                            
                                Registered under class and java.lang.Class in the
                                type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.BlobType
                                Maps a java.sql.Blob to a JDBC BLOB
                            
                                Registered under blob and java.sql.Blob in the
                                type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.ClobType
                                Maps a java.sql.Clob to a JDBC CLOB
                            
                                Registered under clob and java.sql.Clob in the
                                type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.BinaryTypeMaps a primitive byte[] to a JDBC VARBINARY
                                Registered under binary and byte[] in the
                                type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.MaterializedBlobTypeMaps a primitive byte[] to a JDBC BLOB
                                Registered under materialized_blob in the type registry (see
                                Section 6.5, “Type registry”).
                            
org.hibernate.type.ImageTypeMaps a primitive byte[] to a JDBC LONGVARBINARY
                                Registered under image in the type registry (see
                                Section 6.5, “Type registry”).
                            
org.hibernate.type.BinaryTypeMaps a java.lang.Byte[] to a JDBC VARBINARY
                                Registered under wrapper-binary, Byte[] and
                                java.lang.Byte[] in the type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.CharArrayTypeMaps a char[] to a JDBC VARCHAR
                                Registered under characters and char[]
                                in the type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.CharacterArrayTypeMaps a java.lang.Character[] to a JDBC VARCHAR
                                Registered under wrapper-characters, Character[]
                                and java.lang.Character[] in the type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.UUIDBinaryTypeMaps a java.util.UUID to a JDBC BINARY
                                Registered under uuid-binary and java.util.UUID
                                in the type registry (see Section 6.5, “Type registry”).
                            
org.hibernate.type.UUIDCharTypeMaps a java.util.UUID to a JDBC CHAR (though VARCHAR is fine too for existing schemas)
                                Registered under uuid-char in the type registry (see
                                Section 6.5, “Type registry”).
                            
org.hibernate.type.PostgresUUIDType
                                Maps a java.util.UUID to the PostgreSQL UUID data type (through
                                Types#OTHER which is how the PostgreSQL JDBC driver defines it).
                            
                                Registered under pg-uuid in the type registry (see
                                Section 6.5, “Type registry”).
                            
org.hibernate.type.SerializableTypeMaps implementors of java.lang.Serializable to a JDBC VARBINARY
                                Unlike the other value types, there are multiple instances of this type.  It
                                gets registered once under java.io.Serializable.
                                Additionally it gets registered under the specific
                                java.io.Serializable implementation class names.
                            
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.
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 nor does it define an identifier.
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.
Collections are covered in Chapter 7, Collection mapping.
            The definition of entities is covered in detail in Chapter 4, 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 Membership, both the User and
            Group entities remain.
            
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 Chapter 8, Association Mappings.
Why do we spend so much time categorizing the various types of types? What is the significance of the distinction?
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 update the sku of that Product to null to make it "go away", but even there the access is done through the Product).
Nor can you define an association to that Product sku. You can define an association to Product based on its sku, assuming sku is unique, but that is totally different.
TBC...
            Hibernate makes it relatively easy for developers to create their own value types.  For
            example, you might want to persist properties of type java.lang.BigInteger to
            VARCHAR columns.  Custom types are not limited to mapping values to a single table
            column.  So, for example, you might want to concatenate together FIRST_NAME,
            INITIAL and SURNAME columns into a java.lang.String.
        
            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 java.math.BigDecimal
            and java.util.Currency together into a custom Money class.
        
                The first approach is to directly implement the org.hibernate.type.Type
                interface (or one of its derivatives).  Probably, you will be more interested in the more specific
                org.hibernate.type.BasicType contract which would allow registration of
                the type (see Section 6.5, “Type 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
                Money, which is the key we would use to register our type in the registry:
            
Example 6.1. Defining and registering the custom Type
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 );
        }
    }
    ...
}
Configuration cfg = new Configuration();
cfg.registerTypeOverride( new MoneyType() );
cfg...;
            It is important that we registered the type before adding mappings.
                    Both org.hibernate.usertype.UserType and
                    org.hibernate.usertype.CompositeUserType were originally
                    added to isolate user code from internal changes to the org.hibernate.type.Type
                    interfaces.
                
                The second approach is the use the org.hibernate.usertype.UserType
                interface, which presents a somewhat simplified view of the org.hibernate.type.Type
                interface.  Using a org.hibernate.usertype.UserType, our
                Money custom type would look as follows:
            
Example 6.2. Defining the custom UserType
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 );
        }
    }
    ...
}
            
                There is not much difference between the org.hibernate.type.Type example
                and the org.hibernate.usertype.UserType example, but that is only because
                of the snippets shown.  If you choose the org.hibernate.type.Type approach
                there are quite a few more methods you would need to implement as compared to the
                org.hibernate.usertype.UserType.
            
                The third and final approach is the use the org.hibernate.usertype.CompositeUserType
                interface, which differs from org.hibernate.usertype.UserType in that it
                gives us the ability to provide Hibernate the information to handle the composition within the
                Money class (specifically the 2 attributes).  This would give us the capability,
                for example, to reference the amount attribute in an HQL query.  Using a
                org.hibernate.usertype.CompositeUserType, our
                Money custom type would look as follows:
            
Example 6.3. Defining the custom CompositeUserType
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 );
        }
    }
    ...
}
            
            Internally Hibernate uses a registry of basic types (see Section 6.1.1, “Basic value types”) when
            it needs to resolve the specific org.hibernate.type.Type 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.
        
            To register a new type or to override an existing type registration, applications would make use of the
            registerTypeOverride method of the org.hibernate.cfg.Configuration
            class when bootstrapping Hibernate.  For example, lets say you want Hibernate to use your custom
            SuperDuperStringType; during bootstrap you would call:
        
Example 6.4. Overriding the standard StringType
Configuration cfg = ...; cfg.registerTypeOverride( new SuperDuperStringType() );
            The argument to registerTypeOverride is a org.hibernate.type.BasicType
            which is a specialization of the org.hibernate.type.Type we saw before.  It
            adds a single method:
        
Example 6.5. Snippet from BasicType.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();
            
        
            One approach is to use inheritance (SuperDuperStringType extends 
            org.hibernate.type.StringType); another is to use delegation.