much more about basic types
This commit is contained in:
parent
1f5a8c0f1b
commit
5a036069fb
|
@ -379,8 +379,8 @@ The JPA specification defines a quite limited set of basic types:
|
||||||
| Strings | `java.lang` | `String`
|
| Strings | `java.lang` | `String`
|
||||||
| Arbitrary-precision numeric types | `java.math` | `BigInteger`, `BigDecimal`
|
| Arbitrary-precision numeric types | `java.math` | `BigInteger`, `BigDecimal`
|
||||||
| Date/time types | `java.time` | `LocalDate`, `LocalTime`, `LocalDateTime`, `OffsetDateTime`, `Instant`
|
| Date/time types | `java.time` | `LocalDate`, `LocalTime`, `LocalDateTime`, `OffsetDateTime`, `Instant`
|
||||||
| Deprecated date/time types | `java.util` | `Date`, `Calendar`
|
| Deprecated date/time types 💀 | `java.util` | `Date`, `Calendar`
|
||||||
| Deprecated JDBC date/time types | `java.sql` | `Date`, `Time`, `Timestamp`
|
| Deprecated JDBC date/time types 💀 | `java.sql` | `Date`, `Time`, `Timestamp`
|
||||||
| Binary and character arrays | | `byte[]`, `char[]`
|
| Binary and character arrays | | `byte[]`, `char[]`
|
||||||
| UUIDs | `java.util` | `UUID`
|
| UUIDs | `java.util` | `UUID`
|
||||||
| Enumerated types | | Any `enum`
|
| Enumerated types | | Any `enum`
|
||||||
|
@ -393,6 +393,13 @@ The JPA specification defines a quite limited set of basic types:
|
||||||
We're begging you to use types from the `java.time` package instead of anything which inherits `java.util.Date`.
|
We're begging you to use types from the `java.time` package instead of anything which inherits `java.util.Date`.
|
||||||
====
|
====
|
||||||
|
|
||||||
|
[CAUTION]
|
||||||
|
.Serialization is usually a bad idea
|
||||||
|
====
|
||||||
|
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.
|
||||||
|
====
|
||||||
|
|
||||||
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.
|
||||||
On the other hand, if an attribute cannot be null, use of `@Basic(optional=false)` is highly recommended.
|
On the other hand, if an attribute cannot be null, use of `@Basic(optional=false)` is highly recommended.
|
||||||
|
|
||||||
|
@ -404,7 +411,7 @@ String middleName; // may be null
|
||||||
----
|
----
|
||||||
|
|
||||||
[TIP]
|
[TIP]
|
||||||
.`optional` vs `nullable` in JPA
|
.Should I use `optional=false` or `nullable=false` in JPA?
|
||||||
====
|
====
|
||||||
There are two ways to mark a mapped column `not null` in JPA:
|
There are two ways to mark a mapped column `not null` in JPA:
|
||||||
|
|
||||||
|
@ -451,7 +458,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 you _don't_ set `autoapply=true`, then you must explicitly apply the converter using the `@Convert` annotation:
|
||||||
|
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
|
@ -464,6 +471,88 @@ All this is nice, but it probably won't surprise you that Hibernate goes beyond
|
||||||
|
|
||||||
=== Compositional basic types
|
=== Compositional basic types
|
||||||
|
|
||||||
|
Hibernate considers a "basic type" to be formed by the marriage of two objects:
|
||||||
|
|
||||||
|
- a `JavaType`, which models the semantics of a certain Java class, and
|
||||||
|
- a `JdbcType`, representing a SQL type which is understood by JDBC.
|
||||||
|
|
||||||
|
An instance of `org.hibernate.type.descriptor.java.JavaType` represents a particular Java class.
|
||||||
|
It is able to:
|
||||||
|
|
||||||
|
- compare instances of the class to determine if an attribute of that class type is dirty (modified),
|
||||||
|
- produce a useful hash code for an instance of the class,
|
||||||
|
- coerce values to other types, and, in particular,
|
||||||
|
- convert an instance of the class to one of several other equivalent Java representations at the request of its partner `JdbcType`.
|
||||||
|
|
||||||
|
For example, `IntegerJavaType` knows how to convert an `Integer` or `int` value to the types `Long`, `BigInteger`, and `String`, among others.
|
||||||
|
|
||||||
|
We may explicitly specify a Java type using the `@JavaType` annotation, but for the built-in ``JavaType``s this is never necessary.
|
||||||
|
|
||||||
|
[source,java]
|
||||||
|
----
|
||||||
|
@JavaType(LongJavaType.class) // not needed, this is the default JavaType for long
|
||||||
|
long currentTimeMillis;
|
||||||
|
----
|
||||||
|
|
||||||
|
For a user-written `JavaType`, the annotation is more useful:
|
||||||
|
|
||||||
|
[source,java]
|
||||||
|
----
|
||||||
|
@JavaType(BitSetJavaType.class)
|
||||||
|
BitSet bitSet;
|
||||||
|
----
|
||||||
|
|
||||||
|
Alternatively, the `@JavaTypeRegistration` 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.
|
||||||
|
|
||||||
|
For example, `VarcharJdbcType` takes care of:
|
||||||
|
|
||||||
|
- writing Java strings to JDBC ``PreparedStatement``s by calling `setString()`, and
|
||||||
|
- reading Java strings from JDBC ``ResultSet``s using `getString()`.
|
||||||
|
|
||||||
|
By pairing `LongJavaType` with `VarcharJdbcType` in holy matrimony, we produce a basic type which maps ``Long``s and primitive ``longs``s to the SQL type `VARCHAR`.
|
||||||
|
|
||||||
|
We may explicitly specify a JDBC type using the `@JdbcType` annotation.
|
||||||
|
|
||||||
|
[source,java]
|
||||||
|
----
|
||||||
|
@JdbcType(VarcharJdbcType.class)
|
||||||
|
long currentTimeMillis;
|
||||||
|
----
|
||||||
|
|
||||||
|
Alternatively, we may specify a JDBC type code:
|
||||||
|
|
||||||
|
[source,java]
|
||||||
|
----
|
||||||
|
@JdbcTypeCode(Types.VARCHAR)
|
||||||
|
long currentTimeMillis;
|
||||||
|
----
|
||||||
|
|
||||||
|
The `@JdbcTypeRegistration` annotation may be used to register a user-written `JdbcType` as the default for a given SQL type code.
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
.JDBC types and JDBC type codes
|
||||||
|
====
|
||||||
|
The types defined by the JDBC specification are enumerated by the integer type codes in the class `java.sql.Types`.
|
||||||
|
Each JDBC type is an abstraction of a commonly-available type in SQL.
|
||||||
|
For example, `Types.VARCHAR` represents the SQL type `VARCHAR` (or `VARCHAR2` on Oracle).
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
For example, to form a basic type using `LongJavaType` and `TimestampJdbcType`, we would provide an `AttributeConverter<Long,Timestamp>`.
|
||||||
|
|
||||||
|
[source,java]
|
||||||
|
----
|
||||||
|
@JdbcType(TimestampJdbcType.class)
|
||||||
|
@Convert(converter = LongToTimestampConverter.class)
|
||||||
|
long currentTimeMillis;
|
||||||
|
----
|
||||||
|
|
||||||
|
|
||||||
=== `equals()` and `hashCode()`
|
=== `equals()` and `hashCode()`
|
||||||
|
|
||||||
Entity classes should override `equals()` and `hashCode()`. People new to
|
Entity classes should override `equals()` and `hashCode()`. People new to
|
||||||
|
|
Loading…
Reference in New Issue