此内容没有您所选择的语言版本。
5.2. Hibernate Types
5.2.1. Entities and Values 复制链接链接已复制到粘贴板!
复制链接链接已复制到粘贴板!
In relation to the persistence service, Java language-level objects are classified into two groups:
An entity exists independently of any other objects holding references to the entity. Contrast this with the usual Java model, where an unreferenced object is garbage collected. Entities must be explicitly saved and deleted. Saves and deletions, however, can be cascaded from a parent entity to its children. This is different from the ODMG model of object persistence by reachability and corresponds more closely to how application objects are usually used in large systems. Entities support circular and shared references. They can also be versioned.
An entity's persistent state consists of references to other entities and instances of value types. Values are primitives: collections (not what is inside a collection), components and certain immutable objects. Unlike entities, values in particular collections and components, are persisted and deleted by reachability. Since value objects and primitives are persisted and deleted along with their containing entity, they cannot be independently versioned. Values have no independent identity, so they cannot be shared by two entities or collections.
Until now, we have been using the term "persistent class" to refer to entities. We will continue to do that. Not all user-defined classes with a persistent state, however, are entities. A component is a user-defined class with value semantics. A Java property of type
java.lang.String also has value semantics. Given this definition, all types (classes) provided by the JDK have value type semantics in Java, while user-defined types can be mapped with entity or value type semantics. This decision is up to the application developer. An entity class in a domain model will normally have shared references to a single instance of that class, while composition or aggregation usually translates to a value type.
We will revisit both concepts throughout this reference guide.
The challenge is to map the Java type system, and the developers' definition of entities and value types, to the SQL/database type system. The bridge between both systems is provided by Hibernate. For entities,
<class>, <subclass> and so on are used. For value types we use <property>, <component>etc., that usually have a type attribute. The value of this attribute is the name of a Hibernate mapping type. Hibernate provides a range of mappings for standard JDK value types out of the box. You can write your own mapping types and implement your own custom conversion strategies.
With the exception of collections, all built-in Hibernate types support null semantics.
5.2.2. Basic Value Types 复制链接链接已复制到粘贴板!
复制链接链接已复制到粘贴板!
The built-in basic mapping types can be roughly categorized into the following:
integer, long, short, float, double, character, byte, boolean, yes_no, true_false- Type mappings from Java primitives or wrapper classes to appropriate (vendor-specific) SQL column types.
boolean, yes_noandtrue_falseare all alternative encodings for a Javabooleanorjava.lang.Boolean. string- A type mapping from
java.lang.StringtoVARCHAR(or OracleVARCHAR2). date, time, timestamp- Type mappings from
java.util.Dateand its subclasses to SQL typesDATE,TIMEandTIMESTAMP(or equivalent). calendar, calendar_date- Type mappings from
java.util.Calendarto SQL typesTIMESTAMPandDATE(or equivalent). big_decimal, big_integer- Type mappings from
java.math.BigDecimalandjava.math.BigIntegertoNUMERIC(or OracleNUMBER). locale, timezone, currency- Type mappings from
java.util.Locale,java.util.TimeZoneandjava.util.CurrencytoVARCHAR(or OracleVARCHAR2). Instances ofLocaleandCurrencyare mapped to their ISO codes. Instances ofTimeZoneare mapped to theirID. class- A type mapping from
java.lang.ClasstoVARCHAR(or OracleVARCHAR2). AClassis mapped to its fully qualified name. binary- Maps byte arrays to an appropriate SQL binary type.
text- Maps long Java strings to a SQL
CLOBorTEXTtype. serializable- Maps serializable Java types to an appropriate SQL binary type. You can also indicate the Hibernate type
serializablewith the name of a serializable Java class or interface that does not default to a basic type. clob, blob- Type mappings for the JDBC classes
java.sql.Clobandjava.sql.Blob. These types can be inconvenient for some applications, since the blob or clob object cannot be reused outside of a transaction. Driver support is patchy and inconsistent. imm_date, imm_time, imm_timestamp, imm_calendar, imm_calendar_date, imm_serializable, imm_binary- Type mappings for what are considered mutable Java types. This is where Hibernate makes certain optimizations appropriate only for immutable Java types, and the application treats the object as immutable. For example, you should not call
Date.setTime()for an instance mapped asimm_timestamp. To change the value of the property, and have that change made persistent, the application must assign a new, nonidentical, object to the property.
Unique identifiers of entities and collections can be of any basic type except
binary, blob and clob. Composite identifiers are also allowed. See below for more information.
The basic value types have corresponding
Type constants defined on org.hibernate.Hibernate. For example, Hibernate.STRING represents the string type.
5.2.3. Custom Value Types 复制链接链接已复制到粘贴板!
复制链接链接已复制到粘贴板!
It is 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. Hibernate does not provide a built-in type for this. Custom types are not limited to mapping a property, or collection element, to a single table column. So, for example, you might have a Java property getName()/setName() of type java.lang.String that is persisted to the columns FIRST_NAME, INITIAL, SURNAME.
To implement a custom type, implement either
org.hibernate.UserType or org.hibernate.CompositeUserType and declare properties using the fully qualified classname of the type. View org.hibernate.test.DoubleStringType to see the kind of things that are possible.
<property name="twoStrings" type="org.hibernate.test.DoubleStringType">
<column name="first_string"/>
<column name="second_string"/>
</property>
<property name="twoStrings" type="org.hibernate.test.DoubleStringType">
<column name="first_string"/>
<column name="second_string"/>
</property>
Notice the use of
<column> tags to map a property to multiple columns.
The
CompositeUserType, EnhancedUserType, UserCollectionType, and UserVersionType interfaces provide support for more specialized uses.
You can even supply parameters to a
UserType in the mapping file. To do this, your UserType must implement the org.hibernate.usertype.ParameterizedType interface. To supply parameters to your custom type, you can use the <type> element in your mapping files.
<property name="priority">
<type name="com.mycompany.usertypes.DefaultValueIntegerType">
<param name="default">0</param>
</type>
</property>
<property name="priority">
<type name="com.mycompany.usertypes.DefaultValueIntegerType">
<param name="default">0</param>
</type>
</property>
The
UserType can now retrieve the value for the parameter named default from the Properties object passed to it.
If you regularly use a certain
UserType, it is useful to define a shorter name for it. You can do this using the <typedef> element. Typedefs assign a name to a custom type, and can also contain a list of default parameter values if the type is parameterized.
<typedef class="com.mycompany.usertypes.DefaultValueIntegerType" name="default_zero">
<param name="default">0</param>
</typedef>
<typedef class="com.mycompany.usertypes.DefaultValueIntegerType" name="default_zero">
<param name="default">0</param>
</typedef>
<property name="priority" type="default_zero"/>
<property name="priority" type="default_zero"/>
It is also possible to override the parameters supplied in a typedef on a case-by-case basis by using type parameters on the property mapping.
Even though Hibernate's rich range of built-in types and support for components means you will rarely need to use a custom type, it is considered good practice to use custom types for non-entity classes that occur frequently in your application. For example, a
MonetaryAmount class is a good candidate for a CompositeUserType, even though it could be mapped as a component. One reason for this is abstraction. With a custom type, your mapping documents would be protected against changes to the way monetary values are represented.