From 4f725332af012cc7d89785cd6c4f73c8d1442f2e Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Sun, 2 Aug 2015 14:07:26 -0500 Subject: [PATCH] HHH-9998 - Continue documentation TLC - mapping basic-types --- .../en-US/chapters/domain/DomainModel.xml | 4 +- .../mapping/en-US/Hibernate_Mapping.xml | 17 +- .../en-US/chapters/basic/Basic_Types.xml | 457 +++++++++++++++++- .../en-US/chapters/basic/extras/Blob.sql | 5 + .../chapters/basic/extras/BlobLocator.java | 8 + .../basic/extras/BlobMaterialized.java | 8 + .../en-US/chapters/basic/extras/Clob.sql | 5 + .../chapters/basic/extras/ClobLocator.java | 8 + .../basic/extras/ClobMaterialized.java | 8 + .../extras/ClobMaterializedCharArray.java | 8 + .../basic/extras/EnumAttributeConverter.java | 53 ++ .../chapters/basic/extras/EnumCustomType.java | 82 ++++ .../basic/extras/EnumeratedOrdinal.java | 11 + .../basic/extras/EnumeratedString.java | 11 + .../basic/extras/ExplicitColumnNaming.java | 13 + .../chapters/basic/extras/NCLOB_locator.java | 12 + .../basic/extras/NCLOB_materialized.java | 8 + .../en-US/chapters/basic/extras/NVARCHAR.java | 8 + .../en-US/chapters/collection/Collection.xml | 2 +- .../mapping/en-US/chapters/entity/Entity.xml | 22 + .../mapping/en-US/chapters/id/Identifiers.xml | 53 ++ .../en-US/chapters/natural_id/Natural_Id.xml | 20 + .../org/hibernate/boot/MetadataBuilder.java | 15 +- .../boot/internal/MetadataBuilderImpl.java | 36 +- .../boot/model/TypeContributions.java | 8 +- .../process/spi/MetadataBuildingProcess.java | 14 +- ...tDelegatingMetadataBuilderImplementor.java | 12 +- ...ractDelegatingMetadataBuildingOptions.java | 5 +- .../boot/spi/BasicTypeRegistration.java | 46 ++ .../boot/spi/MetadataBuildingOptions.java | 4 +- .../org/hibernate/type/BasicTypeRegistry.java | 9 +- 31 files changed, 911 insertions(+), 61 deletions(-) create mode 100644 documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/Blob.sql create mode 100644 documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/BlobLocator.java create mode 100644 documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/BlobMaterialized.java create mode 100644 documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/Clob.sql create mode 100644 documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/ClobLocator.java create mode 100644 documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/ClobMaterialized.java create mode 100644 documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/ClobMaterializedCharArray.java create mode 100644 documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/EnumAttributeConverter.java create mode 100644 documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/EnumCustomType.java create mode 100644 documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/EnumeratedOrdinal.java create mode 100644 documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/EnumeratedString.java create mode 100644 documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/ExplicitColumnNaming.java create mode 100644 documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/NCLOB_locator.java create mode 100644 documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/NCLOB_materialized.java create mode 100644 documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/NVARCHAR.java create mode 100644 documentation/src/main/docbook/mapping/en-US/chapters/entity/Entity.xml create mode 100644 documentation/src/main/docbook/mapping/en-US/chapters/id/Identifiers.xml create mode 100644 documentation/src/main/docbook/mapping/en-US/chapters/natural_id/Natural_Id.xml create mode 100644 hibernate-core/src/main/java/org/hibernate/boot/spi/BasicTypeRegistration.java diff --git a/documentation/src/main/docbook/manual/en-US/chapters/domain/DomainModel.xml b/documentation/src/main/docbook/manual/en-US/chapters/domain/DomainModel.xml index a7d4636612..c63bf1f450 100644 --- a/documentation/src/main/docbook/manual/en-US/chapters/domain/DomainModel.xml +++ b/documentation/src/main/docbook/manual/en-US/chapters/domain/DomainModel.xml @@ -34,8 +34,8 @@ This chapter will describe the characteristics of a persistable domain model. However, it will not discuss defining the mapping for the domain model. That is a massive topic in its own right and is the subject of an - entire dedicated manual. See the Hibernate - Domain Model Mapping documentation - from the documentation site. + entire dedicated manual. See the Hibernate Domain Model Mapping Guide from the + documentation site.
diff --git a/documentation/src/main/docbook/mapping/en-US/Hibernate_Mapping.xml b/documentation/src/main/docbook/mapping/en-US/Hibernate_Mapping.xml index 242ce43ed2..a793493954 100644 --- a/documentation/src/main/docbook/mapping/en-US/Hibernate_Mapping.xml +++ b/documentation/src/main/docbook/mapping/en-US/Hibernate_Mapping.xml @@ -48,17 +48,26 @@ + + + diff --git a/documentation/src/main/docbook/mapping/en-US/chapters/basic/Basic_Types.xml b/documentation/src/main/docbook/mapping/en-US/chapters/basic/Basic_Types.xml index 0846a1607b..0e4db10e4d 100644 --- a/documentation/src/main/docbook/mapping/en-US/chapters/basic/Basic_Types.xml +++ b/documentation/src/main/docbook/mapping/en-US/chapters/basic/Basic_Types.xml @@ -381,32 +381,43 @@ + + + To use these hibernate-java8 types just add the hibernate-java8 jar to your classpath; Hibernate + will take care of the rest. See + + + These mappings are managed by a service inside Hibernate called the org.hibernate.type.BasicTypeRegistry, which essentially maintains a map of - org.hibernate.type.BasicType (a org.hibernate.type.Type + org.hibernate.type.BasicType (a org.hibernate.type.Type specialization) instances keyed by a name. That is the purpose of the "BasicTypeRegistry key(s)" column in the previous tables. We will revisit this detail later. +
+ + +
+ The <literal>@Basic</literal> annotation Strictly speaking, a basic type is denoted with the javax.persistence.Basic - annotation. Generally speaking the @Basic annotation can be ignored. + annotation. Generally speaking the @Basic annotation can be ignored. Both of the + following examples are ultimately the same. With <literal>@Basic</literal> + + Without <literal>@Basic</literal> - - Both of the above examples are ultimately the same. - - The JPA specification strictly limits the Java types that can be marked as @@ -434,17 +445,71 @@ If provider portability is a concern, you should stick to just these basic types. Note that JPA 2.1 did add the notion of an javax.persistence.AttributeConverter - to help alleviate some of these concerns; see + to help alleviate some of these concerns; see + + + The @Basic annotation defines 2 attributes. + + + + optional - boolean (defaults to true) - Defines whether this attribute + allows nulls. JPA defines this as "a hint", which essentially means that it affect is + specifically required. As long as the type is not primitive, Hibernate takes this to mean + that the underlying column should be NULLABLE. + + + + + fetch - FetchType (defaults to EAGER) - Defines whether this attribute + should be fetched eagerly or lazily. JPA says that EAGER is a requirement to the provider + (Hibernate) that the value should be fetched when the owner is fetched but that + LAZY is merely a hint that the value be fetched when the attribute is accessed. Hibernate + ignores this setting for basic types unless you are using bytecode enhancement. See + the Hibernate User Guide for additional information on + fetching and on bytecode enhancement. + + + +
+
+ The <literal>@Column</literal> annotation + + JPA defines rules for implicitly determining the name of tables and columns. For a detailed discussion + of implicit naming see . + + + + For basic type attributes, the implicit naming rule is that the column name is the same as the attribute + name. If that implicit naming rule does not meet your requirements, you can explicitly tell Hibernate + (and other providers) the column name to use. + + + + Explicit column naming + + + + + Here we use @Column to explicitly map the description attribute to the + NOTES column, as opposed to the implicit column name description. + + + + The @Column annotation defines other mapping information as well. See its javadocs + for details. + +
+ BasicTypeRegistry We said before that a Hibernate type is not a Java type, nor a SQL type, but that it understands both and performs the marshalling between them. But looking at the - basic type mappings in the previous examples, how did Hibernate know to use + basic type mappings from the previous examples, how did Hibernate know to use its org.hibernate.type.StringType for mapping for java.lang.String attributes or its org.hibernate.type.IntegerType for mapping @@ -454,12 +519,12 @@ The answer lies in a service inside Hibernate called the org.hibernate.type.BasicTypeRegistry, which essentially maintains a map of - org.hibernate.type.BasicType (a org.hibernate.type.Type + org.hibernate.type.BasicType (a org.hibernate.type.Type specialization) instances keyed by a name. - We will see later () that we can explicitly tell Hibernate which + We will see later () that we can explicitly tell Hibernate which BasicType to use for a particular attribute. But first let's explore how implicit resolution works and how applications can adjust implicit resolution. @@ -489,7 +554,7 @@ Applications can also extend (add new BasicType registrations) or override (replace an exiting BasicType registration) using one of the MetadataBuilder#applyBasicType methods or the MetadataBuilder#applyTypes method during bootstrap. For more details, see - +
@@ -514,20 +579,20 @@ This tells Hibernate to store the Strings as nationalized data. This is just for illustration purposes; - for better ways to indicate nationalized character data see + for better ways to indicate nationalized character data see Additionally the description is to be handled as a LOB. Again, for better ways to indicate - LOBs see . + LOBs see . The org.hibernate.annotations.Type#type attribute can name any of the following: - FQN of any org.hibernate.type.Type implementation - Any key registered with BasicTypeRegistry - The name of any known "type definitions" + FQN of any org.hibernate.type.Type implementation + Any key registered with BasicTypeRegistry + The name of any known "type definitions" @@ -567,44 +632,386 @@ + + For additional information on developing and registering custom types, see the + Hibernate Integration Guide. +
Mapping enums + - - blah blah blah + Hibernate supports the mapping of Java enums as basic value types in a number of different ways. + +
+ @Enumerated + + The original JPA-compliant way to map enums was via the @Enumerated + and @MapKeyEnumerated for map keys annotations which works on the principle that + the enum values are stored according to one of 2 strategies indicated by + javax.persistence.EnumType: + + + + ORDINAL - stored according to the enum value's ordinal position within + the enum class, as indicated by java.lang.Enum#ordinal + + + + + STRING - stored according to the enum value's name, as indicated by + java.lang.Enum#name + + + + + + + @Enumerated(ORDINAL) example + + + + + In the ORDINAL example, the gender column is defined as an (nullable) INTEGER type and would hold: + + + NULL - null + + + 0 - MALE + + + 1 - FEMALE + + + + + + @Enumerated(STRING) example + + + + + In the STRING example, the gender column is defined as an (nullable) VARCHAR type and would hold: + + + NULL - null + + + MALE - MALE + + + FEMALE - FEMALE + + + +
+ +
+ AttributeConverter + + You can also map enums in a JPA compliant way using a JPA 2.1 AttributeConverter. Let's revisit the + Gender enum example, but instead we want to store the more standardized 'M' + and 'F' codes. + + + + Enum mapping with AttributeConverter example + + + + + Here, the gender column is defined as a CHAR type and would hold: + + + NULL - null + + + 'M' - MALE + + + 'F' - FEMALE + + + + + + For additional details on using AttributeConverters, see . + + + + Note that JPA explicitly disallows the use of an AttributeConverter with an attribute marked + as @Enumerated. So if using the AttributeConverter approach, be sure to not mark the + attribute as @Enumerated. + +
+ +
+ Custom type + + + You can also map enums using a Hibernate custom type mapping. Let's again revisit the Gender enum + example, this time using a custom Type to store the more standardized 'M' + and 'F' codes. + + + + Enum mapping with custom Type example + + + + + Again, the gender column is defined as a CHAR type and would hold: + + + NULL - null + + + 'M' - MALE + + + 'F' - FEMALE + + + + + + For additional details on using custom types, see . + +
-
+
Mapping LOBs + - - blah blah blah + Mapping LOBs (database Large OBjects) come in 2 forms, those using the JDBC locator types and those + materializing the LOB data. + + + Locator versus materialized + + JDBC LOB locators exist to allow efficient access to the LOB data. They allow the JDBC driver to + stream parts of the LOB data as needed, potentially freeing up memory space. However they can be + unnatural to deal with and have certain limitations. For example, a LOB locator is only portably + valid during the duration of the transaction in which it was obtained. + + + The idea of materialized LOBs is to trade-off the potential efficiency (not all drivers handle LOB + data efficiently) for a more natural programming paradigm using familiar Java types such as + String or byte[], etc for these LOBs. + + + Materialized deals with the entire LOB contents in memory, whereas LOB locators (in theory) allow + streaming parts of the LOB contents into memory as needed. + + + + + The JDBC LOB locator types include: + + + java.sql.Blob + java.sql.Clob + java.sql.NClob + + + + + + Mapping materialized forms of these LOB values would use more familiar Java types + such as String, char[], byte[], etc. The trade off for "more familiar" is usually + performance. + + + + For a first look lets assume we have a CLOB column that we would like to map (NCLOB character LOB data + will be covered in ). + + + + CLOB - SQL + + + + + Let's first map this using the JDBC locator. + + + + CLOB - locator mapping + + + + + We could also map a materialized form. + + + + CLOB - materialized mapping + + + + + + How JDBC deals with LOB data varies from driver to driver. Hibernate tries to handle all these variances + for you. However some drivers do not allow Hibernate to always do that in an automatic fashion + (looking directly at you PostgreSQL JDBC drivers). In such cases you may have to do some extra + to get LOBs working. Such discussions are beyond the scope of this guide however. + + + + + + We might even want the materialized data as a char array (for some crazy reason). + + + + CLOB - materialized char[] mapping + + + + + We'd map BLOB data in a similar fashion. + + + + BLOB - SQL + + + + + Let's first map this using the JDBC locator. + + + + BLOB - locator mapping + + + + + We could also map a materialized BLOB form. + + + + BLOB - materialized mapping + + + +
Mapping Nationalized Character Data + - - blah blah blah + JDBC 4 added the ability to explicitly handle nationalized character data. To this end + it added specific nationalized character data types. + + + + NCHAR + NVARCHAR + LONGNVARCHAR + NCLOB + + + + + + To map a specific attribute to a nationalized variant datatype, Hibernate defines the + @Nationalized annotation. + + + + NVARCHAR mapping + + + + + NCLOB (locator) mapping + + + + + NCLOB (materialized) mapping + + + + + If you application and database are entirely nationalized you may instead want to enable nationalized + character data as the default. You can do this via the + hibernate.use_nationalized_character_data setting or by calling + MetadataBuilder#enableGlobalNationalizedCharacterDataSupport during bootstrap.
Mapping UUID Values + - - blah blah blah + Hibernate also allows you to map UUID values, again in a number of ways. + + + + The default UUID mapping is as binary because it represents more efficient storage. However + many applications prefer the readability of character storage. To switch the default mapping, + simply call MetadataBuilder.applyBasicType( UUIDCharType.INSTANCE, UUID.class.getName() ) + + + +
+ UUID as binary + + As mentioned, the default mapping for UUID attributes. Maps the UUID to a byte[] + using java.util.UUID#getMostSignificantBits and java.util.UUID#getLeastSignificantBits + and stores that as BINARY data. + + + Chosen as the default simply because it is generally more efficient from storage perspective. + +
+ +
+ UUID as (var)char + + Maps the UUID to a String using java.util.UUID#toString and java.util.UUID#fromString + and stores that as CHAR or VARCHAR data. + +
+ +
+ PostgeSQL-specific UUID + + + When using one of the PostgreSQL Dialects, this becomes the default UUID mapping + + + + Maps the UUID using PostgreSQL's specific UUID data type. The PostgreSQL JDBC driver choses to + map its UUID type to the OTHER code. Note that this can cause difficulty as the + driver chooses to map many different data types to OTHER. + +
+ +
+ UUID as identifier + + Hibernate supports using UUID values as identifiers. They can even be generated! For + details see the discussion of generators in + +
Mapping Date/Time Values + blah blah blah
diff --git a/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/Blob.sql b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/Blob.sql new file mode 100644 index 0000000000..cdf673cd26 --- /dev/null +++ b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/Blob.sql @@ -0,0 +1,5 @@ +create table step( + ... + instruction BLOB not null, + ... +) \ No newline at end of file diff --git a/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/BlobLocator.java b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/BlobLocator.java new file mode 100644 index 0000000000..814926ed53 --- /dev/null +++ b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/BlobLocator.java @@ -0,0 +1,8 @@ +@Entity +public class Step { + ... + @Lob + @Basic + public Blob instructions; + ... +} \ No newline at end of file diff --git a/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/BlobMaterialized.java b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/BlobMaterialized.java new file mode 100644 index 0000000000..14810e0131 --- /dev/null +++ b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/BlobMaterialized.java @@ -0,0 +1,8 @@ +@Entity +public class Step { + ... + @Lob + @Basic + public byte[] instructions; + ... +} \ No newline at end of file diff --git a/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/Clob.sql b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/Clob.sql new file mode 100644 index 0000000000..fbdfb3cfb4 --- /dev/null +++ b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/Clob.sql @@ -0,0 +1,5 @@ +create table product( + ... + description CLOB not null, + ... +) \ No newline at end of file diff --git a/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/ClobLocator.java b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/ClobLocator.java new file mode 100644 index 0000000000..9f20f73537 --- /dev/null +++ b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/ClobLocator.java @@ -0,0 +1,8 @@ +@Entity +public class Product { + ... + @Lob + @Basic + public Clob description; + ... +} \ No newline at end of file diff --git a/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/ClobMaterialized.java b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/ClobMaterialized.java new file mode 100644 index 0000000000..3090bcd2cb --- /dev/null +++ b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/ClobMaterialized.java @@ -0,0 +1,8 @@ +@Entity +public class Product { + ... + @Lob + @Basic + public String description; + ... +} \ No newline at end of file diff --git a/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/ClobMaterializedCharArray.java b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/ClobMaterializedCharArray.java new file mode 100644 index 0000000000..3c25ef0b4b --- /dev/null +++ b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/ClobMaterializedCharArray.java @@ -0,0 +1,8 @@ +@Entity +public class Product { + ... + @Lob + @Basic + public char[] description; + ... +} \ No newline at end of file diff --git a/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/EnumAttributeConverter.java b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/EnumAttributeConverter.java new file mode 100644 index 0000000000..d11552a92a --- /dev/null +++ b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/EnumAttributeConverter.java @@ -0,0 +1,53 @@ +@Entity +public class Person { + ... + @Basic + @Convert( converter=GenderConverter.class ) + public Gender gender; +} + +public enum Gender { + MALE( 'M' ), + FEMALE( 'F' ); + + private final char code; + + private Gender(char code) { + this.code = code; + } + + public char getCode() { + return code; + } + + public static Gender fromCode(char code) { + if ( code == 'M' || code == 'm' ) { + return MALE; + } + if ( code == 'F' || code == 'f' ) { + return FEMALE; + } + throw ... + } +} + +@Converter +public class GenderConverter + implements AttributeConverter { + + public Character convertToDatabaseColumn(Gender value) { + if ( value == null ) { + return null; + } + + return value.getCode(); + } + + public Gender convertToEntityAttribute(Character value) { + if ( value == null ) { + return null; + } + + return Gender.fromCode( value ); + } +} \ No newline at end of file diff --git a/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/EnumCustomType.java b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/EnumCustomType.java new file mode 100644 index 0000000000..5aeab77cb3 --- /dev/null +++ b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/EnumCustomType.java @@ -0,0 +1,82 @@ +import org.hibernate.type.descriptor.java.CharacterTypeDescriptor; + +@Entity +public class Person { + ... + @Basic + @Type( type = GenderType.class ) + public Gender gender; +} + +public enum Gender { + MALE( 'M' ), + FEMALE( 'F' ); + + private final char code; + + private Gender(char code) { + this.code = code; + } + + public char getCode() { + return code; + } + + public static Gender fromCode(char code) { + if ( code == 'M' || code == 'm' ) { + return MALE; + } + if ( code == 'F' || code == 'f' ) { + return FEMALE; + } + throw ... + } +} + +@Converter +public class GenderType + extends AbstractSingleColumnStandardBasicType { + + public static final GenderType INSTANCE = new GenderType(); + + private GenderType() { + super( + CharTypeDescriptor.INSTANCE, + GenderJavaTypeDescriptor.INSTANCE + ); + } + + public String getName() { + return "gender"; + } + + @Override + protected boolean registerUnderJavaType() { + return true; + } +} + +public static class GenderJavaTypeDescriptor + extends AbstractTypeDescriptor { + public static final GenderJavaTypeDescriptor INSTANCE = new GenderJavaTypeDescriptor(); + + public String toString(Gender value) { + return value == null ? null : value.name(); + } + + public Gender fromString(String string) { + return string == null ? null : Gender.valueOf( string ); + } + + public X unwrap(Gender value, Class type, WrapperOptions options) { + return CharacterTypeDescriptor.INSTANCE.unwrap( + value == null ? null : value.getCode(), + type, + options + ); + } + + public Gender wrap(X value, WrapperOptions options) { + return CharacterTypeDescriptor.INSTANCE.wrap( value, options ); + } +} \ No newline at end of file diff --git a/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/EnumeratedOrdinal.java b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/EnumeratedOrdinal.java new file mode 100644 index 0000000000..9680fb88db --- /dev/null +++ b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/EnumeratedOrdinal.java @@ -0,0 +1,11 @@ +@Entity +public class Person { + ... + @Enumerated + public Gender gender; + + public static enum Gender { + MALE, + FEMALE + } +} \ No newline at end of file diff --git a/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/EnumeratedString.java b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/EnumeratedString.java new file mode 100644 index 0000000000..e5541a53c8 --- /dev/null +++ b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/EnumeratedString.java @@ -0,0 +1,11 @@ +@Entity +public class Person { + ... + @Enumerated(STRING) + public Gender gender; + + public static enum Gender { + MALE, + FEMALE + } +} \ No newline at end of file diff --git a/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/ExplicitColumnNaming.java b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/ExplicitColumnNaming.java new file mode 100644 index 0000000000..9eded3a8a4 --- /dev/null +++ b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/ExplicitColumnNaming.java @@ -0,0 +1,13 @@ +@Entity +public class Product { + @Id + @Basic + private Integer id; + @Basic + private String sku; + @Basic + private String name; + @Basic + @Column( name = "NOTES" ) + private String description; +} \ No newline at end of file diff --git a/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/NCLOB_locator.java b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/NCLOB_locator.java new file mode 100644 index 0000000000..41a691007f --- /dev/null +++ b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/NCLOB_locator.java @@ -0,0 +1,12 @@ +@Entity +public class Product { + ... + @Lob + @Basic + @Nationalized + public NClob description; + // Clob also works, because NClob + // extends Clob. The db type is + // still NCLOB either way and + // handled as such +} \ No newline at end of file diff --git a/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/NCLOB_materialized.java b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/NCLOB_materialized.java new file mode 100644 index 0000000000..443686c046 --- /dev/null +++ b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/NCLOB_materialized.java @@ -0,0 +1,8 @@ +@Entity +public class Product { + ... + @Lob + @Basic + @Nationalized + public String description; +} \ No newline at end of file diff --git a/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/NVARCHAR.java b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/NVARCHAR.java new file mode 100644 index 0000000000..0786749d66 --- /dev/null +++ b/documentation/src/main/docbook/mapping/en-US/chapters/basic/extras/NVARCHAR.java @@ -0,0 +1,8 @@ +@Entity +public class Product { + ... + @Basic + @Nationalized + public String description; + ... +} \ No newline at end of file diff --git a/documentation/src/main/docbook/mapping/en-US/chapters/collection/Collection.xml b/documentation/src/main/docbook/mapping/en-US/chapters/collection/Collection.xml index c275fc3028..85eb043d15 100644 --- a/documentation/src/main/docbook/mapping/en-US/chapters/collection/Collection.xml +++ b/documentation/src/main/docbook/mapping/en-US/chapters/collection/Collection.xml @@ -73,7 +73,7 @@ Bags - todo : discuss mapping bags + todo : discuss mapping bags and idbags
diff --git a/documentation/src/main/docbook/mapping/en-US/chapters/entity/Entity.xml b/documentation/src/main/docbook/mapping/en-US/chapters/entity/Entity.xml new file mode 100644 index 0000000000..119fda757f --- /dev/null +++ b/documentation/src/main/docbook/mapping/en-US/chapters/entity/Entity.xml @@ -0,0 +1,22 @@ + + + + Entity + + * POJO, etc discussion from manual/en-US/chapters/domain/DomainModel.xml + * dynamic models (hbm.xml) + * Map mode + * proxy solutions (hibernate-core/src/test/java/org/hibernate/test/dynamicentity/tuplizer2) + * inheritance + * optimistic locking + + \ No newline at end of file diff --git a/documentation/src/main/docbook/mapping/en-US/chapters/id/Identifiers.xml b/documentation/src/main/docbook/mapping/en-US/chapters/id/Identifiers.xml new file mode 100644 index 0000000000..4667e9b5e0 --- /dev/null +++ b/documentation/src/main/docbook/mapping/en-US/chapters/id/Identifiers.xml @@ -0,0 +1,53 @@ + + + + Identifiers + + + Identifiers model the primary key of an entity. They are used to uniquely identify each + specific entity. Every entity must define an identifier. + + + + + Technically the identifier does not have to map to the column(s) physically defined as the entity + table's primary key. They just need to map to column(s) that uniquely identify each row. However + this documentation will continue to use the terms identifier and primary key interchangeably. + + + + + An identifier might be simple (single value) or composite (multiple values). + + + + +
+ Simple identifiers + +
+ +
+ Composite identifiers + + +
+ Composite identifiers - aggregated + +
+ +
+ Composite identifiers - non-aggregated + +
+
+
\ No newline at end of file diff --git a/documentation/src/main/docbook/mapping/en-US/chapters/natural_id/Natural_Id.xml b/documentation/src/main/docbook/mapping/en-US/chapters/natural_id/Natural_Id.xml new file mode 100644 index 0000000000..b5a1933952 --- /dev/null +++ b/documentation/src/main/docbook/mapping/en-US/chapters/natural_id/Natural_Id.xml @@ -0,0 +1,20 @@ + + + + Natural Ids + + * simple + * composite + * caching + * apis + + \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/boot/MetadataBuilder.java b/hibernate-core/src/main/java/org/hibernate/boot/MetadataBuilder.java index 7bb9719c3d..3665362576 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/MetadataBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/MetadataBuilder.java @@ -308,6 +308,17 @@ public interface MetadataBuilder { */ MetadataBuilder applyBasicType(BasicType type); + /** + * Specify an additional or overridden basic type mapping supplying specific + * registration keys. + * + * @param type The type addition or override. + * @param keys The keys under which to register the basic type. + * + * @return {@code this}, for method chaining + */ + MetadataBuilder applyBasicType(BasicType type, String... keys); + /** * Register an additional or overridden custom type mapping. * @@ -316,7 +327,7 @@ public interface MetadataBuilder { * * @return {@code this}, for method chaining */ - MetadataBuilder applyBasicType(UserType type, String[] keys); + MetadataBuilder applyBasicType(UserType type, String... keys); /** * Register an additional or overridden composite custom type mapping. @@ -326,7 +337,7 @@ public interface MetadataBuilder { * * @return {@code this}, for method chaining */ - MetadataBuilder applyBasicType(CompositeUserType type, String[] keys); + MetadataBuilder applyBasicType(CompositeUserType type, String... keys); /** * Apply an explicit TypeContributor (implicit application via ServiceLoader will still happen too) diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java index fa6e8aa414..b0dc3469a8 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java @@ -12,7 +12,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; - import javax.persistence.AttributeConverter; import javax.persistence.SharedCacheMode; @@ -50,6 +49,7 @@ import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.selector.spi.StrategySelector; +import org.hibernate.boot.spi.BasicTypeRegistration; import org.hibernate.boot.spi.JpaOrmXmlPersistenceUnitDefaultAware; import org.hibernate.boot.spi.MappingDefaults; import org.hibernate.boot.spi.MetadataBuilderImplementor; @@ -72,10 +72,9 @@ import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.service.ServiceRegistry; import org.hibernate.type.BasicType; -import org.hibernate.type.CompositeCustomType; -import org.hibernate.type.CustomType; import org.hibernate.usertype.CompositeUserType; import org.hibernate.usertype.UserType; + import org.jboss.jandex.IndexView; import static org.hibernate.internal.log.DeprecationLogger.DEPRECATION_LOGGER; @@ -252,19 +251,25 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont @Override public MetadataBuilder applyBasicType(BasicType type) { - options.basicTypeRegistrations.add( type ); + options.basicTypeRegistrations.add( new BasicTypeRegistration( type ) ); return this; } @Override - public MetadataBuilder applyBasicType(UserType type, String[] keys) { - options.basicTypeRegistrations.add( new CustomType( type, keys ) ); + public MetadataBuilder applyBasicType(BasicType type, String... keys) { + options.basicTypeRegistrations.add( new BasicTypeRegistration( type, keys ) ); return this; } @Override - public MetadataBuilder applyBasicType(CompositeUserType type, String[] keys) { - options.basicTypeRegistrations.add( new CompositeCustomType( type, keys ) ); + public MetadataBuilder applyBasicType(UserType type, String... keys) { + options.basicTypeRegistrations.add( new BasicTypeRegistration( type, keys ) ); + return this; + } + + @Override + public MetadataBuilder applyBasicType(CompositeUserType type, String... keys) { + options.basicTypeRegistrations.add( new BasicTypeRegistration( type, keys ) ); return this; } @@ -276,17 +281,22 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont @Override public void contributeType(BasicType type) { - options.basicTypeRegistrations.add( type ); + options.basicTypeRegistrations.add( new BasicTypeRegistration( type ) ); + } + + @Override + public void contributeType(BasicType type, String... keys) { + options.basicTypeRegistrations.add( new BasicTypeRegistration( type, keys ) ); } @Override public void contributeType(UserType type, String[] keys) { - options.basicTypeRegistrations.add( new CustomType( type, keys ) ); + options.basicTypeRegistrations.add( new BasicTypeRegistration( type, keys ) ); } @Override public void contributeType(CompositeUserType type, String[] keys) { - options.basicTypeRegistrations.add( new CompositeCustomType( type, keys ) ); + options.basicTypeRegistrations.add( new BasicTypeRegistration( type, keys ) ); } @Override @@ -523,7 +533,7 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont private final StandardServiceRegistry serviceRegistry; private final MappingDefaultsImpl mappingDefaults; - private ArrayList basicTypeRegistrations = new ArrayList(); + private ArrayList basicTypeRegistrations = new ArrayList(); private IndexView jandexView; private ClassLoader tempClassLoader; @@ -747,7 +757,7 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont } @Override - public List getBasicTypeRegistrations() { + public List getBasicTypeRegistrations() { return basicTypeRegistrations; } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/TypeContributions.java b/hibernate-core/src/main/java/org/hibernate/boot/model/TypeContributions.java index 7579ffd044..e6096ba1c7 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/TypeContributions.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/TypeContributions.java @@ -16,9 +16,11 @@ import org.hibernate.usertype.UserType; * @author Steve Ebersole */ public interface TypeContributions { - public void contributeType(BasicType type); + void contributeType(BasicType type); - public void contributeType(UserType type, String... keys); + void contributeType(BasicType type, String... keys); - public void contributeType(CompositeUserType type, String... keys); + void contributeType(UserType type, String... keys); + + void contributeType(CompositeUserType type, String... keys); } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/process/spi/MetadataBuildingProcess.java b/hibernate-core/src/main/java/org/hibernate/boot/model/process/spi/MetadataBuildingProcess.java index aae1847212..c31e4bba07 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/process/spi/MetadataBuildingProcess.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/process/spi/MetadataBuildingProcess.java @@ -28,6 +28,7 @@ import org.hibernate.boot.model.source.internal.hbm.ModelBinder; import org.hibernate.boot.model.source.spi.MetadataSourceProcessor; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.spi.AdditionalJaxbMappingProducer; +import org.hibernate.boot.spi.BasicTypeRegistration; import org.hibernate.boot.spi.ClassLoaderAccess; import org.hibernate.boot.spi.MetadataBuildingOptions; import org.hibernate.boot.spi.MetadataContributor; @@ -36,6 +37,7 @@ import org.hibernate.cfg.AttributeConverterDefinition; import org.hibernate.cfg.MetadataSourceType; import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.spi.JdbcServices; +import org.hibernate.type.BasicType; import org.hibernate.type.BasicTypeRegistry; import org.hibernate.type.TypeFactory; import org.hibernate.type.TypeResolver; @@ -330,6 +332,11 @@ public class MetadataBuildingProcess { basicTypeRegistry.register( type ); } + @Override + public void contributeType(BasicType type, String... keys) { + basicTypeRegistry.register( type, keys ); + } + @Override public void contributeType(UserType type, String[] keys) { basicTypeRegistry.register( type, keys ); @@ -351,8 +358,11 @@ public class MetadataBuildingProcess { } // add explicit application registered types - for ( org.hibernate.type.BasicType basicType : options.getBasicTypeRegistrations() ) { - basicTypeRegistry.register( basicType ); + for ( BasicTypeRegistration basicTypeRegistration : options.getBasicTypeRegistrations() ) { + basicTypeRegistry.register( + basicTypeRegistration.getBasicType(), + basicTypeRegistration.getRegistrationKeys() + ); } return basicTypeRegistry; diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingMetadataBuilderImplementor.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingMetadataBuilderImplementor.java index 0c6dab646d..c137525079 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingMetadataBuilderImplementor.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingMetadataBuilderImplementor.java @@ -28,6 +28,7 @@ import org.hibernate.dialect.function.SQLFunction; import org.hibernate.type.BasicType; import org.hibernate.usertype.CompositeUserType; import org.hibernate.usertype.UserType; + import org.jboss.jandex.IndexView; /** @@ -38,6 +39,7 @@ import org.jboss.jandex.IndexView; * @param The type of a specific sub-class; Allows sub-classes to narrow down the return-type of the contract methods * to a specialization of {@link MetadataBuilderImplementor} */ +@SuppressWarnings("unused") public abstract class AbstractDelegatingMetadataBuilderImplementor> implements MetadataBuilderImplementor { private final MetadataBuilderImplementor delegate; @@ -166,13 +168,19 @@ public abstract class AbstractDelegatingMetadataBuilderImplementor getBasicTypeRegistrations() { + public List getBasicTypeRegistrations() { return delegate.getBasicTypeRegistrations(); } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/BasicTypeRegistration.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/BasicTypeRegistration.java new file mode 100644 index 0000000000..1703d68c21 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/BasicTypeRegistration.java @@ -0,0 +1,46 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.boot.spi; + +import org.hibernate.type.BasicType; +import org.hibernate.type.CompositeCustomType; +import org.hibernate.type.CustomType; +import org.hibernate.usertype.CompositeUserType; +import org.hibernate.usertype.UserType; + +/** + * @author Steve Ebersole + */ +public class BasicTypeRegistration { + private final BasicType basicType; + private final String[] registrationKeys; + + public BasicTypeRegistration(BasicType basicType) { + this( basicType, basicType.getRegistrationKeys() ); + } + + public BasicTypeRegistration(BasicType basicType, String[] registrationKeys) { + this.basicType = basicType; + this.registrationKeys = registrationKeys; + } + + public BasicTypeRegistration(UserType type, String[] keys) { + this( new CustomType( type, keys ), keys ); + } + + public BasicTypeRegistration(CompositeUserType type, String[] keys) { + this( new CompositeCustomType( type, keys ), keys ); + } + + public BasicType getBasicType() { + return basicType; + } + + public String[] getRegistrationKeys() { + return registrationKeys; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/MetadataBuildingOptions.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/MetadataBuildingOptions.java index d93c1d33c9..351d5368e5 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/spi/MetadataBuildingOptions.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/MetadataBuildingOptions.java @@ -25,7 +25,6 @@ import org.hibernate.cache.spi.access.AccessType; import org.hibernate.cfg.AttributeConverterDefinition; import org.hibernate.cfg.MetadataSourceType; import org.hibernate.dialect.function.SQLFunction; -import org.hibernate.type.BasicType; import org.jboss.jandex.IndexView; @@ -56,13 +55,14 @@ public interface MetadataBuildingOptions { * Access the list of BasicType registrations. These are the BasicTypes explicitly * registered via calls to:
    *
  • {@link org.hibernate.boot.MetadataBuilder#applyBasicType(org.hibernate.type.BasicType)}
  • + *
  • {@link org.hibernate.boot.MetadataBuilder#applyBasicType(org.hibernate.type.BasicType, String[])}
  • *
  • {@link org.hibernate.boot.MetadataBuilder#applyBasicType(org.hibernate.usertype.UserType, java.lang.String[])}
  • *
  • {@link org.hibernate.boot.MetadataBuilder#applyBasicType(org.hibernate.usertype.CompositeUserType, java.lang.String[])}
  • *
* * @return The BasicType registrations */ - List getBasicTypeRegistrations(); + List getBasicTypeRegistrations(); /** * Access to the Jandex index passed by call to diff --git a/hibernate-core/src/main/java/org/hibernate/type/BasicTypeRegistry.java b/hibernate-core/src/main/java/org/hibernate/type/BasicTypeRegistry.java index 7de9689fbc..1ff9516044 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/BasicTypeRegistry.java +++ b/hibernate-core/src/main/java/org/hibernate/type/BasicTypeRegistry.java @@ -110,6 +110,10 @@ public class BasicTypeRegistry implements Serializable { } public void register(BasicType type) { + register( type, type.getRegistrationKeys() ); + } + + public void register(BasicType type, String[] keys) { if ( locked ) { throw new HibernateException( "Can not alter TypeRegistry at this time" ); } @@ -118,11 +122,12 @@ public class BasicTypeRegistry implements Serializable { throw new HibernateException( "Type to register cannot be null" ); } - if ( type.getRegistrationKeys() == null || type.getRegistrationKeys().length == 0 ) { + if ( keys == null || keys.length == 0 ) { LOG.typeDefinedNoRegistrationKeys( type ); + return; } - for ( String key : type.getRegistrationKeys() ) { + for ( String key : keys ) { // be safe... if ( key == null ) { continue;