improve converters discussion
This commit is contained in:
parent
13b7ebd2d6
commit
74e7fa6f04
|
@ -142,6 +142,8 @@ Identifier values may be:
|
||||||
- assigned by the application, that is, by your Java code, or
|
- assigned by the application, that is, by your Java code, or
|
||||||
- generated and assigned by Hibernate.
|
- generated and assigned by Hibernate.
|
||||||
|
|
||||||
|
We'll discuss the second option first.
|
||||||
|
|
||||||
[[generated-identifiers]]
|
[[generated-identifiers]]
|
||||||
=== Generated identifiers
|
=== Generated identifiers
|
||||||
|
|
||||||
|
@ -202,7 +204,7 @@ create sequence seq_book start with 5 increment by 10
|
||||||
.Check the `initialValue` and `allocationSize`
|
.Check the `initialValue` and `allocationSize`
|
||||||
====
|
====
|
||||||
If you let Hibernate export your database schema, the sequence definition will have the right `start with` and `increment` values.
|
If you let Hibernate export your database schema, the sequence definition will have the right `start with` and `increment` values.
|
||||||
But if you're working with a database schema managed outside of Hibernate, makes sure the `initialValue` and `allocationSize` members of `@SequenceGenerator` match the `start with` and `increment` specified in the DDL.
|
But if you're working with a database schema managed outside of Hibernate, make sure the `initialValue` and `allocationSize` members of `@SequenceGenerator` match the `start with` and `increment` specified in the DDL.
|
||||||
====
|
====
|
||||||
|
|
||||||
Any identifier attribute may now make use of the generator named `bookSeq`:
|
Any identifier attribute may now make use of the generator named `bookSeq`:
|
||||||
|
@ -235,9 +237,9 @@ However, the annotations themselves are a little more intrusive than they should
|
||||||
Nor may `@GeneratedValue` be used on a property not annotated `@Id`.
|
Nor may `@GeneratedValue` be used on a property not annotated `@Id`.
|
||||||
Since custom id generation is a rather common requirement, Hibernate provides a very carefully-designed framework for user-defined ``Generator``s.
|
Since custom id generation is a rather common requirement, Hibernate provides a very carefully-designed framework for user-defined ``Generator``s.
|
||||||
|
|
||||||
[TIP]
|
[[user-defined-generators]]
|
||||||
.Defining your own id generators
|
=== User-defined generators
|
||||||
====
|
|
||||||
JPA doesn't define a standard way to extend the set of id generation strategies, but Hibernate does:
|
JPA doesn't define a standard way to extend the set of id generation strategies, but Hibernate does:
|
||||||
|
|
||||||
- the `Generator` hierarchy of interfaces in the package `org.hibernate.generator` lets you define new generators, and
|
- the `Generator` hierarchy of interfaces in the package `org.hibernate.generator` lets you define new generators, and
|
||||||
|
@ -245,12 +247,23 @@ JPA doesn't define a standard way to extend the set of id generation strategies,
|
||||||
|
|
||||||
Furthermore, the `@ValueGenerationType` meta-annotation lets you write an annotation which associates a `Generator` type with a non-`@Id` attribute.
|
Furthermore, the `@ValueGenerationType` meta-annotation lets you write an annotation which associates a `Generator` type with a non-`@Id` attribute.
|
||||||
|
|
||||||
These APIs are new in Hibernate 6, and supersede the classic `IdentifierGenerator` interface from older versions of Hibernate.
|
[NOTE]
|
||||||
You can find out more from the Javadoc for `@IdGeneratorType` and for `org.hibernate.generator`.
|
.The older APIs are still available in Hibernate 6
|
||||||
====
|
====
|
||||||
|
These APIs are new in Hibernate 6, and supersede the classic `IdentifierGenerator` interface and `@GenericGenerator` annotation from older versions of Hibernate.
|
||||||
|
However, the older APIs are still available and custom ``IdentifierGenerator``s written for older versions of Hibernate continue to work in Hibernate 6.
|
||||||
|
====
|
||||||
|
|
||||||
|
You can find out more from the Javadoc for `@IdGeneratorType` and for `org.hibernate.generator`.
|
||||||
|
|
||||||
|
[[natural-identifiers]]
|
||||||
|
=== Natural identifiers
|
||||||
|
|
||||||
Not every id maps to a (system-generated) surrogate key.
|
Not every id maps to a (system-generated) surrogate key.
|
||||||
Primary keys which are meaningful to the user of the system are called _natural keys_.
|
Primary keys which are meaningful to the user of the system are called _natural keys_.
|
||||||
|
|
||||||
|
When the primary key of a table is a natural key, we don't annotate the identifier attribute `@GeneratedValue`, and it's the responsibility of the application code to assign a value to the identifier attribute.
|
||||||
|
|
||||||
Of particular interest are natural keys which comprise more than one database column, and such natural keys are called _composite keys_.
|
Of particular interest are natural keys which comprise more than one database column, and such natural keys are called _composite keys_.
|
||||||
|
|
||||||
[[composite-identifiers]]
|
[[composite-identifiers]]
|
||||||
|
@ -402,7 +415,7 @@ We're begging you to use types from the `java.time` package instead of anything
|
||||||
.Serialization is usually a bad idea
|
.Serialization is usually a bad idea
|
||||||
====
|
====
|
||||||
Serializing a Java object and storing its binary representation in the database is usually wrong.
|
Serializing a Java object and storing its binary representation in the database is usually wrong.
|
||||||
As we'll soon see, Hibernate has much better ways to handle complex Java objects.
|
As we'll soon see in <<embeddable-objects>>, Hibernate has much better ways to handle complex Java objects.
|
||||||
====
|
====
|
||||||
|
|
||||||
The `@Basic` annotation explicitly specifies that an attribute is basic, but it's often not needed, since attributes are assumed basic by default.
|
The `@Basic` annotation explicitly specifies that an attribute is basic, but it's often not needed, since attributes are assumed basic by default.
|
||||||
|
@ -442,8 +455,22 @@ Note that:
|
||||||
Therefore, we recommend `@Basic(optional=false)` in preference to `@Column(nullable=false)` in most circumstances.
|
Therefore, we recommend `@Basic(optional=false)` in preference to `@Column(nullable=false)` in most circumstances.
|
||||||
====
|
====
|
||||||
|
|
||||||
JPA provides the `AttributeConverter` interface, and the `@Converter` annotation to convert any Java type to one of the types listed above, or perform whatever other sort of pre- and post-processing you need on a basic attribute before writing and reading it to or from the database.
|
This limited set of pre-defined basic attribute types can be extended by supplying a _converter_.
|
||||||
Converters substantially widen the set of attribute types that can be handled.
|
|
||||||
|
[[converters]]
|
||||||
|
=== Converters
|
||||||
|
|
||||||
|
A JPA `AttributeConverter` is responsible for:
|
||||||
|
|
||||||
|
- converting a given Java type to one of the types listed above, and/or
|
||||||
|
- perform any other sort of pre- and post-processing you might need to perform on a basic attribute value before writing and reading it to or from the database.
|
||||||
|
|
||||||
|
Converters substantially widen the set of attribute types that can be handled by JPA.
|
||||||
|
|
||||||
|
There are two ways to apply a converter:
|
||||||
|
|
||||||
|
- the `@Convert` annotation applies an `AttributeConverter` to a particular entity attribute, or
|
||||||
|
- the `@Converter` annotation registers an `AttributeConverter` for automatic application to all attributes of a given type.
|
||||||
|
|
||||||
For example, the following converter will be automatically applied to any attribute of type `BitSet`, and takes care of persisting the `BitSet` to a column of type `varbinary`:
|
For example, the following converter will be automatically applied to any attribute of type `BitSet`, and takes care of persisting the `BitSet` to a column of type `varbinary`:
|
||||||
|
|
||||||
|
@ -463,7 +490,7 @@ public static class BitSetConverter implements AttributeConverter<BitSet,byte[]>
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
On the other hand, if you _don't_ set `autoapply=true`, then you must explicitly apply the converter using the `@Convert` annotation:
|
On the other hand, if we _don't_ set `autoapply=true`, then we must explicitly apply the converter using the `@Convert` annotation:
|
||||||
|
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
|
@ -507,7 +534,7 @@ For a user-written `JavaType`, the annotation is more useful:
|
||||||
BitSet bitSet;
|
BitSet bitSet;
|
||||||
----
|
----
|
||||||
|
|
||||||
Alternatively, the `@JavaTypeRegistration` may be used to register `BitSetJavaType` as the default `JavaType` for `BitSet`.
|
Alternatively, the `@JavaTypeRegistration` annotation may be used to register `BitSetJavaType` as the default `JavaType` for `BitSet`.
|
||||||
|
|
||||||
A `org.hibernate.type.descriptor.jdbc.JdbcType` is able to read and write a single Java type from and to JDBC.
|
A `org.hibernate.type.descriptor.jdbc.JdbcType` is able to read and write a single Java type from and to JDBC.
|
||||||
|
|
||||||
|
@ -546,7 +573,7 @@ For example, `Types.VARCHAR` represents the SQL type `VARCHAR` (or `VARCHAR2` on
|
||||||
Since Hibernate understand more SQL types than JDBC, there's an extended list of integer type codes in the class `org.hibernate.type.SqlTypes`.
|
Since Hibernate understand more SQL types than JDBC, there's an extended list of integer type codes in the class `org.hibernate.type.SqlTypes`.
|
||||||
====
|
====
|
||||||
|
|
||||||
If a given `JavaType` does not know how to convert its instances to the type required by its partner `JdbcType`, we must help it out be providing a JPA `AttributeConverter` to perform the conversion.
|
If a given `JavaType` does not know how to convert its instances to the type required by its partner `JdbcType`, we must help it out by providing a JPA `AttributeConverter` to perform the conversion.
|
||||||
|
|
||||||
For example, to form a basic type using `LongJavaType` and `TimestampJdbcType`, we would provide an `AttributeConverter<Long,Timestamp>`.
|
For example, to form a basic type using `LongJavaType` and `TimestampJdbcType`, we would provide an `AttributeConverter<Long,Timestamp>`.
|
||||||
|
|
||||||
|
@ -557,6 +584,8 @@ For example, to form a basic type using `LongJavaType` and `TimestampJdbcType`,
|
||||||
long currentTimeMillis;
|
long currentTimeMillis;
|
||||||
----
|
----
|
||||||
|
|
||||||
|
Let's abandon our analogy right here, before we start calling this basic type a "throuple".
|
||||||
|
|
||||||
[[embeddable-objects]]
|
[[embeddable-objects]]
|
||||||
=== Embeddable objects
|
=== Embeddable objects
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue