Skip to content

Commit

Permalink
Various changes around how basic values are handled in terms of mappi…
Browse files Browse the repository at this point in the history
…ng consumption for annotations and how value conversions happen

* Split BasicType "resolution" into 2 - one used for reading (mapping model) versus one used from writing (legacy persister model)
* @SqlTypeCode, @SqlType, @SqlTypeRegistration
* @javatype, @JavaTypeRegistration
* @mutability
* jdbc_mappings.adoc section for DomainModel chapter

[*] At the moment, neither @SqlTypeRegistration nor @JavaTypeRegistration support has been implemented
[*] Still need to make sure @mutability is propogated properly in all the cases
[*] jdbc_mappings.adoc still needs a lot of attention
  • Loading branch information
sebersole committed Apr 21, 2020
1 parent 52a1012 commit ced4f5e
Show file tree
Hide file tree
Showing 158 changed files with 4,751 additions and 1,751 deletions.
Expand Up @@ -28,4 +28,5 @@ include::collections.adoc[]
include::natural_id.adoc[]
include::dynamic_model.adoc[]
include::inheritance.adoc[]
include::immutability.adoc[]
include::immutability.adoc[]
include::jdbc_mappings.adoc[]
@@ -0,0 +1,66 @@
[[jdbc-mapping]]
=== JDBC Mappings

Historically Hibernate's BasicType / UserType system is based on a static binding between a Java type
(`JavaTypeDescriptor`) and a SQL/JDBC type (`SqlTypeDescriptor`). 6.0 introduces the ability to influence
the `JavaTypeDescriptor` and `SqlTypeDescriptor` independently. Under this new approach, the resolution of a
basic value mapping comes down to:

* `JavaTypeDescriptor` to use
* `SqlTypeDescriptor` to use
* `BasicValueConverter` to use (if one)
* `MutabilityPlan` to use

Each of these pieces can be influenced independently.

==== JavaTypeDescriptor

`@JavaType` can be used to explicitly specify the `JavaTypeDescriptor` to use for a particular mapping.

`@JavaTypeRegistration` can be used to replace the default `Class` -> `JavaTypeDescriptor` mapping as part
of the `JavaTypeDescriptorRegistry`.

`@Temporal` hints at the `JavaTypeDescriptor` to use in certain cases. E.g. `java.util.Date` can represent a
`java.sql.Date`, `java.sql.Time` or `java.sql.Timestamp` - the `TemporalType` specified by the `@Temporal`
indicates which specific `JavaTypeDescriptor` to use...

An `AttributeConverter` can also influence the `JavaTypeDescriptor` used in certain cases.


==== SqlTypeDescriptor

`@SqlType` can be used to explicitly specify the `SqlTypeDescriptor` to use for a particular mapping.

`@SqlTypeCode` can be used to indicate the `SqlTypeDescriptorRegistry` entry to use. `@SqlTypeRegistration` can
be used to register a `SqlTypeDescriptor` with the `SqlTypeDescriptorRegistry`.

`@MapKeySqlType` and `@MapKeySqlTypeCode` work the same as `@SqlType` and `@SqlTypeCode`, respectively, except
describing the `SqlTypeDescriptor` to use for the map's key. In which case, `@SqlType` and `@SqlTypeCode` refer
to the map's values.

For character and binary data, the JPA `@Lob` annotation can be used to indicate that a JDBC BLOB, CLOB, NCLOB should
be used.

For character data, `@Nationalized` can be used to indicate that the JDBC nationalized variant should be used.
E.g. `Types.CLOB` -> `Types.CLOB`, `Types.VARCHAR` -> `Types.NVARCHAR`, etc

`@Enumerated` influences the `SqlTypeDescriptor` to use by the `EnumType` specified. `EnumType#ORDINAL` implies
that `Types.TINYINT` should be used. `EnumType#STRING` implies that `Types.VARCHAR` should be used.

`@Temporal` can also influence the `SqlTypeDescriptor` used.

An `AttributeConverter` can also influence the `SqlTypeDescriptor` to use by the Java type it reports for its
"relational type"


==== BasicValueConverter

At the moment the only ways to apply a `BasicValueConverter` are by using `@Enumerated` and by applying a JPA
`AttributeConverter`.


==== MutabilityPlan

`MutabilityPlan` can be influenced by either `@Immutable` or `@Mutability`.

By default, `JavaTypeDescriptor#getMutabilityPlan` is used
@@ -0,0 +1,30 @@
/*
* 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 http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.annotations;

import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;

import org.hibernate.type.descriptor.java.BasicJavaDescriptor;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* @author Steve Ebersole
*/
@Inherited
@java.lang.annotation.Target({METHOD, FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
public @interface JavaType {
/**
* The JavaTypeDescriptor to use
*/
Class<? extends BasicJavaDescriptor<?>> value();
}
@@ -0,0 +1,34 @@
/*
* 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 http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.annotations;

import java.lang.annotation.Inherited;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;

import org.hibernate.type.descriptor.java.JavaTypeDescriptor;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* @author Steve Ebersole
*/
@java.lang.annotation.Target({METHOD, FIELD, ANNOTATION_TYPE})
@Inherited
@Retention(RUNTIME)
@Repeatable( JavaTypeRegistrations.class )
public @interface JavaTypeRegistration {
Class<?> javaType();

/**
* todo (6.0) : limit to BasicJavaDescriptor?
*/
Class<? extends JavaTypeDescriptor<?>> descriptorClass();
}
@@ -0,0 +1,25 @@
/*
* 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 http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.annotations;

import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* @author Steve Ebersole
*/
@java.lang.annotation.Target({METHOD, FIELD, ANNOTATION_TYPE})
@Inherited
@Retention(RUNTIME)
public @interface JavaTypeRegistrations {
JavaTypeRegistration[] value();
}
@@ -0,0 +1,25 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.annotations;

import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* @author Steve Ebersole
*/
@java.lang.annotation.Target({METHOD, FIELD, ANNOTATION_TYPE})
@Inherited
@Retention(RUNTIME)
public @interface MapKeyJavaType {
JavaType value();
}
@@ -0,0 +1,28 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.annotations;

import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* Same function as {@link SqlType}, but used to define the SQL type descriptor to
* use for the map-key
*
* @author Steve Ebersole
*/
@java.lang.annotation.Target({METHOD, FIELD, ANNOTATION_TYPE})
@Inherited
@Retention(RUNTIME)
public @interface MapKeySqlType {
SqlType value();
}
@@ -0,0 +1,28 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.annotations;

import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* Same function as {@link SqlTypeCode}, but used to define the SQL type descriptor to
* use for the map-key
*
* @author Steve Ebersole
*/
@java.lang.annotation.Target({METHOD, FIELD, ANNOTATION_TYPE})
@Inherited
@Retention(RUNTIME)
public @interface MapKeySqlTypeCode {
SqlTypeCode value();
}
@@ -0,0 +1,31 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.annotations;

import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;

import org.hibernate.type.descriptor.java.MutabilityPlan;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* Used to specify a MutabilityPlan
*
* @see Immutable
*
* @author Steve Ebersole
*/
@java.lang.annotation.Target({METHOD, FIELD, ANNOTATION_TYPE})
@Inherited
@Retention(RUNTIME)
public @interface Mutability {
Class<? extends MutabilityPlan<?>> value();
}
@@ -0,0 +1,50 @@
/*
* 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 http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.annotations;

import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;

import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* Allows specifying the specific {@link org.hibernate.type.descriptor.sql.SqlTypeDescriptor}
* to use for a particular column mapping. Can reference a {@link ManagedBean} - see
* {@link ManagedBeanRegistry}
*
* ````
* @Entity
* class User {
* ...
* @SqlType ( MyCustomSqlIntegerDescriptor.class )
* int getAge() { ... }
*
* @SqlType ( MyCustomSqlVarcharDescriptor.class )
* String getName() { ... }
* }
* ````
*
* @apiNote Should not be used in combination with {@link SqlTypeCode}
*
* @see org.hibernate.type.descriptor.sql.SqlTypeDescriptor
* @see org.hibernate.type.descriptor.sql.spi.SqlTypeDescriptorRegistry
*
* @author Steve Ebersole
*/
@java.lang.annotation.Target({METHOD, FIELD, ANNOTATION_TYPE})
@Inherited
@Retention(RUNTIME)
public @interface SqlType {
Class<? extends SqlTypeDescriptor> value();
}

0 comments on commit ced4f5e

Please sign in to comment.