From 19388972dce008b35b6cd9eeb3ce5762aeebd942 Mon Sep 17 00:00:00 2001 From: Gail Badner Date: Tue, 10 Jul 2018 23:47:29 -0700 Subject: [PATCH] HHH-12730 : User types built using 5.1 are not binary compatible with 5.3 --- .../AbstractPersistentCollection.java | 21 ++ .../internal/PersistentArrayHolder.java | 29 +- .../collection/internal/PersistentBag.java | 26 ++ .../collection/spi/PersistentCollection.java | 32 ++ .../type/AbstractStandardBasicType.java | 27 ++ .../ProcedureParameterExtractionAware.java | 39 ++ .../type/ProcedureParameterNamedBinder.java | 22 ++ .../org/hibernate/type/SingleColumnType.java | 61 +++ .../main/java/org/hibernate/type/Type.java | 356 +++++++++++++++++- .../java/org/hibernate/type/VersionType.java | 29 ++ .../hibernate/usertype/CompositeUserType.java | 98 +++++ .../usertype/UserCollectionType.java | 47 +++ .../java/org/hibernate/usertype/UserType.java | 45 ++- .../hibernate/usertype/UserVersionType.java | 30 ++ 14 files changed, 855 insertions(+), 7 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/collection/internal/AbstractPersistentCollection.java b/hibernate-core/src/main/java/org/hibernate/collection/internal/AbstractPersistentCollection.java index fc8389a824..a770e4b222 100644 --- a/hibernate-core/src/main/java/org/hibernate/collection/internal/AbstractPersistentCollection.java +++ b/hibernate-core/src/main/java/org/hibernate/collection/internal/AbstractPersistentCollection.java @@ -26,6 +26,7 @@ import org.hibernate.engine.internal.ForeignKeys; import org.hibernate.engine.spi.CollectionEntry; import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.Status; import org.hibernate.engine.spi.TypedValue; @@ -1281,6 +1282,26 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers } } + /** + * Removes entity entries that have an equal identifier with the incoming entity instance + * + * @param list The list containing the entity instances + * @param entityInstance The entity instance to match elements. + * @param entityName The entity name + * @param session The session + * + * @deprecated {@link #identityRemove(Collection, Object, String, SharedSessionContractImplementor)} + * should be used instead. + */ + @Deprecated + public static void identityRemove( + Collection list, + Object entityInstance, + String entityName, + SessionImplementor session) { + identityRemove( list, entityInstance, entityName, (SharedSessionContractImplementor) session ); + } + @Override public Object getIdentifier(Object entry, int i) { throw new UnsupportedOperationException(); diff --git a/hibernate-core/src/main/java/org/hibernate/collection/internal/PersistentArrayHolder.java b/hibernate-core/src/main/java/org/hibernate/collection/internal/PersistentArrayHolder.java index bb36565ab7..866766afef 100644 --- a/hibernate-core/src/main/java/org/hibernate/collection/internal/PersistentArrayHolder.java +++ b/hibernate-core/src/main/java/org/hibernate/collection/internal/PersistentArrayHolder.java @@ -16,6 +16,7 @@ import java.util.Collections; import java.util.Iterator; import org.hibernate.HibernateException; +import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.loader.CollectionAliases; @@ -55,6 +56,20 @@ public class PersistentArrayHolder extends AbstractPersistentCollection { setInitialized(); } + /** + * Constructs a PersistentCollection instance for holding an array. + * + * @param session The session + * @param array The array (the persistent "collection"). + * + * @deprecated {@link #PersistentArrayHolder(SharedSessionContractImplementor, Object)} + * should be used instead. + */ + @Deprecated + public PersistentArrayHolder(SessionImplementor session, Object array) { + this( (SharedSessionContractImplementor) session, array ); + } + /** * Constructs a PersistentCollection instance for holding an array. * @@ -66,7 +81,19 @@ public class PersistentArrayHolder extends AbstractPersistentCollection { elementClass = persister.getElementClass(); } - + /** + * Constructs a PersistentCollection instance for holding an array. + * + * @param session The session + * @param persister The persister for the array + * + * @deprecated {@link #PersistentArrayHolder(SharedSessionContractImplementor, CollectionPersister)} + * should be used instead. + */ + @Deprecated + public PersistentArrayHolder(SessionImplementor session, CollectionPersister persister) { + this( (SharedSessionContractImplementor) session, persister ); + } @Override public Serializable getSnapshot(CollectionPersister persister) throws HibernateException { diff --git a/hibernate-core/src/main/java/org/hibernate/collection/internal/PersistentBag.java b/hibernate-core/src/main/java/org/hibernate/collection/internal/PersistentBag.java index 3762d456e2..30ecd2b5e5 100644 --- a/hibernate-core/src/main/java/org/hibernate/collection/internal/PersistentBag.java +++ b/hibernate-core/src/main/java/org/hibernate/collection/internal/PersistentBag.java @@ -16,6 +16,7 @@ import java.util.List; import java.util.ListIterator; import org.hibernate.HibernateException; +import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.loader.CollectionAliases; import org.hibernate.persister.collection.CollectionPersister; @@ -49,6 +50,17 @@ public class PersistentBag extends AbstractPersistentCollection implements List super( session ); } + /** + * Constructs a PersistentBag + * + * @param session The session + * + * @deprecated {@link #PersistentBag(SharedSessionContractImplementor)} should be used instead. + */ + @Deprecated + public PersistentBag(SessionImplementor session) { + this( ( SharedSessionContractImplementor) session ); + } /** * Constructs a PersistentBag * @@ -71,6 +83,20 @@ public class PersistentBag extends AbstractPersistentCollection implements List setDirectlyAccessible( true ); } + /** + * Constructs a PersistentBag + * + * @param session The session + * @param coll The base elements. + * + * @deprecated {@link #PersistentBag(SharedSessionContractImplementor, Collection)} + * should be used instead. + */ + @Deprecated + public PersistentBag(SessionImplementor session, Collection coll) { + this( (SharedSessionContractImplementor) session, coll ); + } + @Override public boolean isWrapper(Object collection) { return bag==collection; diff --git a/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentCollection.java b/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentCollection.java index a087beab6f..e902062235 100644 --- a/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentCollection.java +++ b/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentCollection.java @@ -13,6 +13,7 @@ import java.util.Collection; import java.util.Iterator; import org.hibernate.HibernateException; +import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.loader.CollectionAliases; import org.hibernate.persister.collection.CollectionPersister; @@ -127,6 +128,20 @@ public interface PersistentCollection { */ boolean unsetSession(SharedSessionContractImplementor currentSession); + /** + * Disassociate this collection from the given session. + * + * @param currentSession The session we are disassociating from. Used for validations. + * + * @return true if this was currently associated with the given session + * + * @deprecated {@link #unsetSession(SharedSessionContractImplementor)} should be used instead. + */ + @Deprecated + default boolean unsetSession(SessionImplementor currentSession) { + return unsetSession( (SharedSessionContractImplementor) currentSession ); + } + /** * Associate the collection with the given session. * @@ -139,6 +154,23 @@ public interface PersistentCollection { */ boolean setCurrentSession(SharedSessionContractImplementor session) throws HibernateException; + /** + * Associate the collection with the given session. + * + * @param session The session to associate with + * + * @return false if the collection was already associated with the session + * + * @throws HibernateException if the collection was already associated + * with another open session + * + * @deprecated {@link #setCurrentSession(SharedSessionContractImplementor)} should be used instead. + */ + @Deprecated + default boolean setCurrentSession(SessionImplementor session) throws HibernateException { + return setCurrentSession( (SharedSessionContractImplementor) session ); + } + /** * Read the state of the collection from a disassembled cached value * diff --git a/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java b/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java index eb91251e35..1cc1878a0e 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java @@ -20,6 +20,7 @@ import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer; import org.hibernate.engine.jdbc.Size; import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.type.descriptor.WrapperOptions; @@ -257,6 +258,15 @@ public abstract class AbstractStandardBasicType return nullSafeGet( rs, name, (WrapperOptions) session ); } + /** + * @deprecated {@link #nullSafeGet(ResultSet, String, SharedSessionContractImplementor)} + * should be used instead. + */ + @Deprecated + public final T nullSafeGet(ResultSet rs, String name, final SessionImplementor session) throws SQLException { + return nullSafeGet( rs, name, (SharedSessionContractImplementor) session ); + } + protected final T nullSafeGet(ResultSet rs, String name, WrapperOptions options) throws SQLException { return remapSqlTypeDescriptor( options ).getExtractor( javaTypeDescriptor ).extract( rs, name, options ); } @@ -265,6 +275,14 @@ public abstract class AbstractStandardBasicType return nullSafeGet( rs, name, session ); } + /** + * @deprecated {@link #get(ResultSet, String, SharedSessionContractImplementor)} should be used instead. + */ + @Deprecated + public Object get(ResultSet rs, String name, SessionImplementor session) throws HibernateException, SQLException { + return get( rs, name, (SharedSessionContractImplementor) session ); + } + @Override @SuppressWarnings({ "unchecked" }) public final void nullSafeSet( @@ -288,6 +306,15 @@ public abstract class AbstractStandardBasicType nullSafeSet( st, value, index, session ); } + /** + * @deprecated {@link #set(PreparedStatement, Object, int, SharedSessionContractImplementor)} + * should be used instead. + */ + @Deprecated + public void set(PreparedStatement st, T value, int index, SessionImplementor session) throws HibernateException, SQLException { + set( st, value, index, (SharedSessionContractImplementor) session ); + } + @Override @SuppressWarnings({ "unchecked" }) public final String toLoggableString(Object value, SessionFactoryImplementor factory) { diff --git a/hibernate-core/src/main/java/org/hibernate/type/ProcedureParameterExtractionAware.java b/hibernate-core/src/main/java/org/hibernate/type/ProcedureParameterExtractionAware.java index 6c3cce7b6c..32a57ae4fc 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/ProcedureParameterExtractionAware.java +++ b/hibernate-core/src/main/java/org/hibernate/type/ProcedureParameterExtractionAware.java @@ -9,6 +9,7 @@ package org.hibernate.type; import java.sql.CallableStatement; import java.sql.SQLException; +import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; /** @@ -39,6 +40,25 @@ public interface ProcedureParameterExtractionAware { */ T extract(CallableStatement statement, int startIndex, SharedSessionContractImplementor session) throws SQLException; + /** + * Perform the extraction + * + * @param statement The CallableStatement from which to extract the parameter value(s). + * @param startIndex The parameter index from which to start extracting; assumes the values (if multiple) are contiguous + * @param session The originating session + * + * @return The extracted value. + * + * @throws SQLException Indicates an issue calling into the CallableStatement + * @throws IllegalStateException Thrown if this method is called on instances that return {@code false} for {@link #canDoExtraction} + * + * @deprecated {@link #extract(CallableStatement, int, SharedSessionContractImplementor)} should be used instead. + */ + @Deprecated + default T extract(CallableStatement statement, int startIndex, SessionImplementor session) throws SQLException { + return extract( statement, startIndex, (SharedSessionContractImplementor) session ); + } + /** * Perform the extraction * @@ -52,4 +72,23 @@ public interface ProcedureParameterExtractionAware { * @throws IllegalStateException Thrown if this method is called on instances that return {@code false} for {@link #canDoExtraction} */ T extract(CallableStatement statement, String[] paramNames, SharedSessionContractImplementor session) throws SQLException; + + /** + * Perform the extraction + * + * @param statement The CallableStatement from which to extract the parameter value(s). + * @param paramNames The parameter names. + * @param session The originating session + * + * @return The extracted value. + * + * @throws SQLException Indicates an issue calling into the CallableStatement + * @throws IllegalStateException Thrown if this method is called on instances that return {@code false} for {@link #canDoExtraction} + * + * @deprecated {@link #extract(CallableStatement, String[], SharedSessionContractImplementor)} should be used instead. + */ + @Deprecated + default T extract(CallableStatement statement, String[] paramNames, SessionImplementor session) throws SQLException { + return extract( statement, paramNames, (SharedSessionContractImplementor) session ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/ProcedureParameterNamedBinder.java b/hibernate-core/src/main/java/org/hibernate/type/ProcedureParameterNamedBinder.java index c69661a9f1..7e1638026c 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/ProcedureParameterNamedBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/type/ProcedureParameterNamedBinder.java @@ -10,6 +10,7 @@ import java.sql.CallableStatement; import java.sql.SQLException; import org.hibernate.HibernateException; +import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; /** @@ -41,4 +42,25 @@ public interface ProcedureParameterNamedBinder { * @throws SQLException An error from the JDBC driver */ void nullSafeSet(CallableStatement statement, Object value, String name, SharedSessionContractImplementor session) throws SQLException; + + /** + * Bind a value to the JDBC prepared statement, ignoring some columns as dictated by the 'settable' parameter. + * Implementors should handle the possibility of null values. + * Does not support multi-column type + * + * @param statement The CallableStatement to which to bind + * @param value the object to write + * @param name parameter bind name + * @param session The originating session + * + * @throws HibernateException An error from Hibernate + * @throws SQLException An error from the JDBC driver + * + * @deprecated {@link #nullSafeSet(CallableStatement, Object, String, SharedSessionContractImplementor)} + * should be used instead. + */ + @Deprecated + default void nullSafeSet(CallableStatement statement, Object value, String name, SessionImplementor session) throws SQLException { + nullSafeSet( statement, value, name, (SharedSessionContractImplementor) session ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/SingleColumnType.java b/hibernate-core/src/main/java/org/hibernate/type/SingleColumnType.java index dbf8ee4ca9..b0185e3b0c 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/SingleColumnType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/SingleColumnType.java @@ -11,6 +11,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import org.hibernate.HibernateException; +import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; /** @@ -40,6 +41,26 @@ public interface SingleColumnType extends Type { */ T nullSafeGet(ResultSet rs, String name, SharedSessionContractImplementor session) throws HibernateException, SQLException; + /** + * Get a column value from a result set by name. + * + * @param rs The result set from which to extract the value. + * @param name The name of the value to extract. + * @param session The session from which the request originates + * + * @return The extracted value. + * + * @throws org.hibernate.HibernateException Generally some form of mismatch error. + * @throws java.sql.SQLException Indicates problem making the JDBC call(s). + * + * @deprecated {@link #nullSafeGet(ResultSet, String, SharedSessionContractImplementor)} + * should be used instead. + */ + @Deprecated + default T nullSafeGet(ResultSet rs, String name, final SessionImplementor session) throws SQLException { + return nullSafeGet( rs, name, (SharedSessionContractImplementor) session ); + } + /** * Get a column value from a result set, without worrying about the possibility of null values. * @@ -54,6 +75,25 @@ public interface SingleColumnType extends Type { */ Object get(ResultSet rs, String name, SharedSessionContractImplementor session) throws HibernateException, SQLException; + /** + * Get a column value from a result set, without worrying about the possibility of null values. + * + * @param rs The result set from which to extract the value. + * @param name The name of the value to extract. + * @param session The session from which the request originates + * + * @return The extracted value. + * + * @throws org.hibernate.HibernateException Generally some form of mismatch error. + * @throws java.sql.SQLException Indicates problem making the JDBC call(s). + * + * @deprecated {@link #get(ResultSet, String, SharedSessionContractImplementor)} should be used instead. + */ + @Deprecated + default Object get(ResultSet rs, String name, SessionImplementor session) throws HibernateException, SQLException { + return get( rs, name, (SharedSessionContractImplementor) session ); + } + /** * Set a parameter value without worrying about the possibility of null * values. Called from {@link #nullSafeSet} after nullness checks have @@ -68,4 +108,25 @@ public interface SingleColumnType extends Type { * @throws java.sql.SQLException Indicates problem making the JDBC call(s). */ void set(PreparedStatement st, T value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException; + + /** + * Set a parameter value without worrying about the possibility of null + * values. Called from {@link #nullSafeSet} after nullness checks have + * been performed. + * + * @param st The statement into which to bind the parameter value. + * @param value The parameter value to bind. + * @param index The position or index at which to bind the param value. + * @param session The session from which the request originates + * + * @throws org.hibernate.HibernateException Generally some form of mismatch error. + * @throws java.sql.SQLException Indicates problem making the JDBC call(s). + * + * @deprecated {@link #set(PreparedStatement, Object, int, SharedSessionContractImplementor)} + * should be used instead. + */ + @Deprecated + default void set(PreparedStatement st, T value, int index, SessionImplementor session) throws HibernateException, SQLException { + set( st, value, index, (SharedSessionContractImplementor) session ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/Type.java b/hibernate-core/src/main/java/org/hibernate/type/Type.java index 07d90ccf8c..9895ea0e65 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/Type.java +++ b/hibernate-core/src/main/java/org/hibernate/type/Type.java @@ -17,6 +17,7 @@ import org.hibernate.MappingException; import org.hibernate.engine.jdbc.Size; import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; /** @@ -246,6 +247,26 @@ public interface Type extends Serializable { */ boolean isDirty(Object old, Object current, SharedSessionContractImplementor session) throws HibernateException; + /** + * Should the parent be considered dirty, given both the old and current value? + * + * @param old the old value + * @param current the current value + * @param session The session from which the request originated. + * + * @return true if the field is dirty + * + * @throws HibernateException A problem occurred performing the checking + * + * @deprecated {@link #isDirty(Object, Object, SharedSessionContractImplementor)} + * should be used instead. + */ + @Deprecated + default boolean isDirty(Object old, Object current, SessionImplementor session) throws HibernateException { + return isDirty( old, current, (SharedSessionContractImplementor) session ); + } + + /** * Should the parent be considered dirty, given both the old and current value? * @@ -261,6 +282,27 @@ public interface Type extends Serializable { boolean isDirty(Object oldState, Object currentState, boolean[] checkable, SharedSessionContractImplementor session) throws HibernateException; + /** + * Should the parent be considered dirty, given both the old and current value? + * + * @param oldState the old value + * @param currentState the current value + * @param checkable An array of booleans indicating which columns making up the value are actually checkable + * @param session The session from which the request originated. + * + * @return true if the field is dirty + * + * @throws HibernateException A problem occurred performing the checking + * + * @deprecated {@link #isDirty(Object, Object, boolean[], SharedSessionContractImplementor)} + * should be used instead. + */ + @Deprecated + default boolean isDirty(Object oldState, Object currentState, boolean[] checkable, SessionImplementor session) + throws HibernateException { + return isDirty( oldState, currentState, checkable, (SharedSessionContractImplementor) session ); + } + /** * Has the value been modified compared to the current database state? The difference between this * and the {@link #isDirty} methods is that here we need to account for "partially" built values. This is really @@ -283,6 +325,34 @@ public interface Type extends Serializable { SharedSessionContractImplementor session) throws HibernateException; + /** + * Has the value been modified compared to the current database state? The difference between this + * and the {@link #isDirty} methods is that here we need to account for "partially" built values. This is really + * only an issue with association types. For most type implementations it is enough to simply delegate to + * {@link #isDirty} here/ + * + * @param dbState the database state, in a "hydrated" form, with identifiers unresolved + * @param currentState the current state of the object + * @param checkable which columns are actually updatable + * @param session The session from which the request originated. + * + * @return true if the field has been modified + * + * @throws HibernateException A problem occurred performing the checking + * + * @deprecated {@link #isModified(Object, Object, boolean[], SharedSessionContractImplementor)} + * should be used instead. + */ + @Deprecated + default boolean isModified( + Object dbState, + Object currentState, + boolean[] checkable, + SessionImplementor session) + throws HibernateException { + return isModified( dbState, currentState, checkable, (SharedSessionContractImplementor) session ); + } + /** * Extract a value of the {@link #getReturnedClass() mapped class} from the JDBC result set. Implementors * should handle possibility of null values. @@ -302,6 +372,31 @@ public interface Type extends Serializable { Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException; + /** + * Extract a value of the {@link #getReturnedClass() mapped class} from the JDBC result set. Implementors + * should handle possibility of null values. + * + * @param rs The result set from which to extract value. + * @param names the column names making up this type value (use to read from result set) + * @param session The originating session + * @param owner the parent entity + * + * @return The extracted value + * + * @throws HibernateException An error from Hibernate + * @throws SQLException An error from the JDBC driver + * + * @see Type#hydrate(ResultSet, String[], SharedSessionContractImplementor, Object) alternative, 2-phase property initialization + * + * @deprecated {@link #nullSafeGet(ResultSet, String[], SharedSessionContractImplementor, Object)} + * should be used instead. + */ + @Deprecated + default Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) + throws HibernateException, SQLException { + return nullSafeGet( rs, names, (SharedSessionContractImplementor) session, owner ); + } + /** * Extract a value of the {@link #getReturnedClass() mapped class} from the JDBC result set. Implementors * should handle possibility of null values. This form might be called if the type is known to be a @@ -320,6 +415,30 @@ public interface Type extends Serializable { Object nullSafeGet(ResultSet rs, String name, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException; + /** + * Extract a value of the {@link #getReturnedClass() mapped class} from the JDBC result set. Implementors + * should handle possibility of null values. This form might be called if the type is known to be a + * single-column type. + * + * @param rs The result set from which to extract value. + * @param name the column name making up this type value (use to read from result set) + * @param session The originating session + * @param owner the parent entity + * + * @return The extracted value + * + * @throws HibernateException An error from Hibernate + * @throws SQLException An error from the JDBC driver + * + * @deprecated {@link #nullSafeGet(ResultSet, String, SharedSessionContractImplementor, Object)} + * should be used instead. + */ + @Deprecated + default Object nullSafeGet(ResultSet rs, String name, SessionImplementor session, Object owner) + throws HibernateException, SQLException { + return nullSafeGet( rs, name, (SharedSessionContractImplementor) session, owner ); + } + /** * Bind a value represented by an instance of the {@link #getReturnedClass() mapped class} to the JDBC prepared * statement, ignoring some columns as dictated by the 'settable' parameter. Implementors should handle the @@ -342,6 +461,34 @@ public interface Type extends Serializable { SharedSessionContractImplementor session) throws HibernateException, SQLException; + /** + * Bind a value represented by an instance of the {@link #getReturnedClass() mapped class} to the JDBC prepared + * statement, ignoring some columns as dictated by the 'settable' parameter. Implementors should handle the + * possibility of null values. A multi-column type should bind parameters starting from index. + * + * @param st The JDBC prepared statement to which to bind + * @param value the object to write + * @param index starting parameter bind index + * @param settable an array indicating which columns to bind/ignore + * @param session The originating session + * + * @throws HibernateException An error from Hibernate + * @throws SQLException An error from the JDBC driver + * + * @deprecated {@link #nullSafeSet(PreparedStatement, Object, int, boolean[], SharedSessionContractImplementor)} + * should be used instead. + */ + @Deprecated + default void nullSafeSet( + PreparedStatement st, + Object value, + int index, + boolean[] settable, + SessionImplementor session) + throws HibernateException, SQLException { + nullSafeSet( st, value, index, settable, (SharedSessionContractImplementor) session ); + } + /** * Bind a value represented by an instance of the {@link #getReturnedClass() mapped class} to the JDBC prepared * statement. Implementors should handle possibility of null values. A multi-column type should bind parameters @@ -358,6 +505,28 @@ public interface Type extends Serializable { void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException; + /** + * Bind a value represented by an instance of the {@link #getReturnedClass() mapped class} to the JDBC prepared + * statement. Implementors should handle possibility of null values. A multi-column type should bind parameters + * starting from index. + * + * @param st The JDBC prepared statement to which to bind + * @param value the object to write + * @param index starting parameter bind index + * @param session The originating session + * + * @throws HibernateException An error from Hibernate + * @throws SQLException An error from the JDBC driver + * + * @deprecated {@link #nullSafeSet(PreparedStatement, Object, int, SharedSessionContractImplementor)} + * should be used instead. + */ + @Deprecated + default void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) + throws HibernateException, SQLException { + nullSafeSet( st, value, index, (SharedSessionContractImplementor) session ); + } + /** * Generate a representation of the value for logging purposes. * @@ -415,6 +584,27 @@ public interface Type extends Serializable { */ Serializable disassemble(Object value, SharedSessionContractImplementor session, Object owner) throws HibernateException; + /** + * Return a disassembled representation of the object. This is the value Hibernate will use in second level + * caching, so care should be taken to break values down to their simplest forms; for entities especially, this + * means breaking them down into their constituent parts. + * + * @param value the value to cache + * @param session the originating session + * @param owner optional parent entity object (needed for collections) + * + * @return the disassembled, deep cloned state + * + * @throws HibernateException An error from Hibernate + * + * @deprecated {@link #disassemble(Object, SharedSessionContractImplementor, Object)} + * should be used instead. + */ + @Deprecated + default Serializable disassemble(Object value, SessionImplementor session, Object owner) throws HibernateException { + return disassemble( value, (SharedSessionContractImplementor) session, owner ); + } + /** * Reconstruct the object from its disassembled state. This method is the reciprocal of {@link #disassemble} * @@ -427,7 +617,26 @@ public interface Type extends Serializable { * @throws HibernateException An error from Hibernate */ Object assemble(Serializable cached, SharedSessionContractImplementor session, Object owner) throws HibernateException; - + + /** + * Reconstruct the object from its disassembled state. This method is the reciprocal of {@link #disassemble} + * + * @param cached the disassembled state from the cache + * @param session the originating session + * @param owner the parent entity object + * + * @return the (re)assembled object + * + * @throws HibernateException An error from Hibernate + * + * @deprecated {@link #assemble(Serializable, SharedSessionContractImplementor, Object)} + * should be used instead. + */ + @Deprecated + default Object assemble(Serializable cached, SessionImplementor session, Object owner) throws HibernateException { + return assemble( cached, (SharedSessionContractImplementor) session, owner ); + } + /** * Called before assembling a query result set from the query cache, to allow batch fetching * of entities missing from the second-level cache. @@ -437,6 +646,21 @@ public interface Type extends Serializable { */ void beforeAssemble(Serializable cached, SharedSessionContractImplementor session); + /** + * Called before assembling a query result set from the query cache, to allow batch fetching + * of entities missing from the second-level cache. + * + * @param cached The key + * @param session The originating session + * + * @deprecated {@link #beforeAssemble(Serializable, SharedSessionContractImplementor)} should + * be used instead + */ + @Deprecated + default void beforeAssemble(Serializable cached, SessionImplementor session) { + beforeAssemble( cached, (SharedSessionContractImplementor) session ); + } + /** * Extract a value from the JDBC result set. This is useful for 2-phase property initialization - the second * phase is a call to {@link #resolve} @@ -460,12 +684,53 @@ public interface Type extends Serializable { Object hydrate(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException; + /** + * Extract a value from the JDBC result set. This is useful for 2-phase property initialization - the second + * phase is a call to {@link #resolve} + * This hydrated value will be either:
    + *
  • in the case of an entity or collection type, the key
  • + *
  • otherwise, the value itself
  • + *
+ * + * @param rs The JDBC result set + * @param names the column names making up this type value (use to read from result set) + * @param session The originating session + * @param owner the parent entity + * + * @return An entity or collection key, or an actual value. + * + * @throws HibernateException An error from Hibernate + * @throws SQLException An error from the JDBC driver + * + * @see #resolve + * + * @deprecated {@link #hydrate(ResultSet, String[], SharedSessionContractImplementor, Object)} + * should be used instead. + */ + @Deprecated + default Object hydrate(ResultSet rs, String[] names, SessionImplementor session, Object owner) + throws HibernateException, SQLException { + return hydrate( rs, names, (SharedSessionContractImplementor) session, owner ); + } + /** * @see #resolve(Object, SharedSessionContractImplementor, Object, Boolean) */ Object resolve(Object value, SharedSessionContractImplementor session, Object owner) throws HibernateException; + /** + * @see #resolve(Object, SharedSessionContractImplementor, Object, Boolean) + * + * @deprecated {@link #resolve(Object, SharedSessionContractImplementor, Object)} + * should be used instead. + */ + @Deprecated + default Object resolve(Object value, SessionImplementor session, Object owner) + throws HibernateException { + return resolve( value, (SharedSessionContractImplementor) session, owner ); + } + /** * The second phase of 2-phase loading. Only really pertinent for entities and collections. Here we resolve the * identifier to an entity or collection instance @@ -501,7 +766,28 @@ public interface Type extends Serializable { */ Object semiResolve(Object value, SharedSessionContractImplementor session, Object owner) throws HibernateException; - + + /** + * Given a hydrated, but unresolved value, return a value that may be used to reconstruct property-ref + * associations. + * + * @param value The unresolved, hydrated value + * @param session THe originating session + * @param owner The value owner + * + * @return The semi-resolved value + * + * @throws HibernateException An error from Hibernate + * + * @deprecated {@link #semiResolve(Object, SharedSessionContractImplementor, Object)} + * should be used instead. + */ + @Deprecated + default Object semiResolve(Object value, SessionImplementor session, Object owner) + throws HibernateException { + return semiResolve( value, (SharedSessionContractImplementor) session, owner ); + } + /** * As part of 2-phase loading, when we perform resolving what is the resolved type for this type? Generally * speaking the type and its semi-resolved type will be the same. The main deviation from this is in the @@ -536,7 +822,37 @@ public interface Type extends Serializable { SharedSessionContractImplementor session, Object owner, Map copyCache) throws HibernateException; - + + /** + * During merge, replace the existing (target) value in the entity we are merging to + * with a new (original) value from the detached entity we are merging. For immutable + * objects, or null values, it is safe to simply return the first parameter. For + * mutable objects, it is safe to return a copy of the first parameter. For objects + * with component values, it might make sense to recursively replace component values. + * + * @param original the value from the detached entity being merged + * @param target the value in the managed entity + * @param session The originating session + * @param owner The owner of the value + * @param copyCache The cache of already copied/replaced values + * + * @return the value to be merged + * + * @throws HibernateException An error from Hibernate + * + * @deprecated {@link #replace(Object, Object, SharedSessionContractImplementor, Object, Map)} + * should be used instead. + */ + @Deprecated + default Object replace( + Object original, + Object target, + SessionImplementor session, + Object owner, + Map copyCache) throws HibernateException { + return replace( original, target, (SharedSessionContractImplementor) session, owner, copyCache ); + } + /** * During merge, replace the existing (target) value in the entity we are merging to * with a new (original) value from the detached entity we are merging. For immutable @@ -562,7 +878,39 @@ public interface Type extends Serializable { Object owner, Map copyCache, ForeignKeyDirection foreignKeyDirection) throws HibernateException; - + + /** + * During merge, replace the existing (target) value in the entity we are merging to + * with a new (original) value from the detached entity we are merging. For immutable + * objects, or null values, it is safe to simply return the first parameter. For + * mutable objects, it is safe to return a copy of the first parameter. For objects + * with component values, it might make sense to recursively replace component values. + * + * @param original the value from the detached entity being merged + * @param target the value in the managed entity + * @param session The originating session + * @param owner The owner of the value + * @param copyCache The cache of already copied/replaced values + * @param foreignKeyDirection For associations, which direction does the foreign key point? + * + * @return the value to be merged + * + * @throws HibernateException An error from Hibernate + * + * @deprecated {@link #replace(Object, Object, SharedSessionContractImplementor, Object, Map, ForeignKeyDirection)} + * should be used instead. + */ + @Deprecated + default Object replace( + Object original, + Object target, + SessionImplementor session, + Object owner, + Map copyCache, + ForeignKeyDirection foreignKeyDirection) throws HibernateException { + return replace( original, target, (SharedSessionContractImplementor) session, owner, copyCache, foreignKeyDirection ); + } + /** * Given an instance of the type, return an array of boolean, indicating * which mapped columns would be null. diff --git a/hibernate-core/src/main/java/org/hibernate/type/VersionType.java b/hibernate-core/src/main/java/org/hibernate/type/VersionType.java index 26f741a6ae..556c68ee2a 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/VersionType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/VersionType.java @@ -8,7 +8,9 @@ package org.hibernate.type; import java.util.Comparator; +import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.internal.SessionImpl; /** * Additional contract for types which may be used to version (and optimistic lock) data. @@ -25,6 +27,19 @@ public interface VersionType extends Type { */ T seed(SharedSessionContractImplementor session); + /** + * Generate an initial version. + * + * @param session The session from which this request originates. + * @return an instance of the type + * + * @deprecated {@link #seed(SharedSessionContractImplementor)} should be used instead. + */ + @Deprecated + default T seed(SessionImplementor session) { + return seed( (SharedSessionContractImplementor) session ); + } + /** * Increment the version. * @@ -34,6 +49,20 @@ public interface VersionType extends Type { */ T next(T current, SharedSessionContractImplementor session); + /** + * Increment the version. + * + * @param session The session from which this request originates. + * @param current the current version + * @return an instance of the type + * + * @deprecated {@link #next(Object, SharedSessionContractImplementor)} should be used instead. + */ + @Deprecated + default T next(T current, SessionImplementor session) { + return next( current, (SharedSessionContractImplementor) session ); + } + /** * Get a comparator for version values. * diff --git a/hibernate-core/src/main/java/org/hibernate/usertype/CompositeUserType.java b/hibernate-core/src/main/java/org/hibernate/usertype/CompositeUserType.java index 2b24ff4a65..738ed6b87b 100644 --- a/hibernate-core/src/main/java/org/hibernate/usertype/CompositeUserType.java +++ b/hibernate-core/src/main/java/org/hibernate/usertype/CompositeUserType.java @@ -11,6 +11,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import org.hibernate.HibernateException; +import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.type.Type; @@ -107,6 +108,27 @@ public interface CompositeUserType { */ Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException; + /** + * Retrieve an instance of the mapped class from a JDBC resultset. Implementors + * should handle possibility of null values. + * + * @param rs a JDBC result set + * @param names the column names + * @param session + * @param owner the containing entity + * @return Object + * @throws HibernateException + * @throws SQLException + * + * @deprecated {@link #nullSafeGet(ResultSet, String[], SharedSessionContractImplementor, Object)} + * should be used instead. + */ + @Deprecated + default Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) + throws HibernateException, SQLException { + return nullSafeGet( rs, names, (SharedSessionContractImplementor) session, owner ); + } + /** * Write an instance of the mapped class to a prepared statement. Implementors * should handle possibility of null values. A multi-column type should be written @@ -121,6 +143,26 @@ public interface CompositeUserType { */ void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException; + /** + * Write an instance of the mapped class to a prepared statement. Implementors + * should handle possibility of null values. A multi-column type should be written + * to parameters starting from index. + * + * @param st a JDBC prepared statement + * @param value the object to write + * @param index statement parameter index + * @param session + * @throws HibernateException + * @throws SQLException + * + * @deprecated {@link #nullSafeSet(PreparedStatement, Object, int, SharedSessionContractImplementor)} + * should be used instead. + */ + @Deprecated + default void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) + throws HibernateException, SQLException { + nullSafeSet( st, value, index, (SharedSessionContractImplementor) session ); + } /** * Return a deep copy of the persistent state, stopping at entities and at collections. * @@ -150,6 +192,24 @@ public interface CompositeUserType { */ Serializable disassemble(Object value, SharedSessionContractImplementor session) throws HibernateException; + /** + * Transform the object into its cacheable representation. At the very least this + * method should perform a deep copy. That may not be enough for some implementations, + * however; for example, associations must be cached as identifier values. (optional + * operation) + * + * @param value the object to be cached + * @param session + * @return a cachable representation of the object + * @throws HibernateException + * + * @deprecated {@link #disassemble(Object, SharedSessionContractImplementor)} should be used instead. + */ + @Deprecated + default Serializable disassemble(Object value, SessionImplementor session) throws HibernateException { + return disassemble( value, (SharedSessionContractImplementor) session ); + } + /** * Reconstruct an object from the cacheable representation. At the very least this * method should perform a deep copy. (optional operation) @@ -162,6 +222,25 @@ public interface CompositeUserType { */ Object assemble(Serializable cached, SharedSessionContractImplementor session, Object owner) throws HibernateException; + /** + * Reconstruct an object from the cacheable representation. At the very least this + * method should perform a deep copy. (optional operation) + * + * @param cached the object to be cached + * @param session + * @param owner the owner of the cached object + * @return a reconstructed object from the cachable representation + * @throws HibernateException + * + * @deprecated {@link #assemble(Serializable, SharedSessionContractImplementor, Object)} should + * be used instead. + */ + @Deprecated + default Object assemble(Serializable cached, SessionImplementor session, Object owner) + throws HibernateException { + return assemble( cached, (SharedSessionContractImplementor) session, owner ); + } + /** * During merge, replace the existing (target) value in the entity we are merging to * with a new (original) value from the detached entity we are merging. For immutable @@ -173,4 +252,23 @@ public interface CompositeUserType { * @throws HibernateException */ Object replace(Object original, Object target, SharedSessionContractImplementor session, Object owner) throws HibernateException; + + /** + * During merge, replace the existing (target) value in the entity we are merging to + * with a new (original) value from the detached entity we are merging. For immutable + * objects, or null values, it is safe to simply return the first parameter. For + * mutable objects, it is safe to return a copy of the first parameter. However, since + * composite user types often define component values, it might make sense to recursively + * replace component values in the target object. + * + * @throws HibernateException + * + * @deprecated {@link #replace(Object, Object, SharedSessionContractImplementor, Object)} + * should be used instead. + */ + @Deprecated + default Object replace(Object original, Object target, SessionImplementor session, Object owner) + throws HibernateException { + return replace( original, target, (SharedSessionContractImplementor) session, owner ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/usertype/UserCollectionType.java b/hibernate-core/src/main/java/org/hibernate/usertype/UserCollectionType.java index 5856c3534d..1a6d2c6406 100644 --- a/hibernate-core/src/main/java/org/hibernate/usertype/UserCollectionType.java +++ b/hibernate-core/src/main/java/org/hibernate/usertype/UserCollectionType.java @@ -11,6 +11,7 @@ import java.util.Map; import org.hibernate.HibernateException; import org.hibernate.collection.spi.PersistentCollection; +import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.persister.collection.CollectionPersister; @@ -28,11 +29,33 @@ public interface UserCollectionType { PersistentCollection instantiate(SharedSessionContractImplementor session, CollectionPersister persister) throws HibernateException; + /** + * Instantiate an uninitialized instance of the collection wrapper + * + * @deprecated {@link #instantiate(SharedSessionContractImplementor, CollectionPersister)} + * should be used instead. + */ + @Deprecated + default PersistentCollection instantiate(SessionImplementor session, CollectionPersister persister) + throws HibernateException { + return instantiate( (SharedSessionContractImplementor) session, persister ); + } + /** * Wrap an instance of a collection */ PersistentCollection wrap(SharedSessionContractImplementor session, Object collection); + /** + * Wrap an instance of a collection + * + * @deprecated {@link #wrap(SharedSessionContractImplementor, Object)} should be used instead. + */ + @Deprecated + default PersistentCollection wrap(SessionImplementor session, Object collection) { + return wrap( (SharedSessionContractImplementor) session, collection ); + } + /** * Return an iterator over the elements of this collection - the passed collection * instance may or may not be a wrapper @@ -60,6 +83,30 @@ public interface UserCollectionType { Map copyCache, SharedSessionContractImplementor session) throws HibernateException; + /** + * Replace the elements of a collection with the elements of another collection + * + * @deprecated {@link #replaceElements(Object, Object, CollectionPersister, Object, Map, SharedSessionContractImplementor)} + * should be used instead. + */ + @Deprecated + default Object replaceElements( + Object original, + Object target, + CollectionPersister persister, + Object owner, + Map copyCache, + SessionImplementor session) throws HibernateException { + return replaceElements( + original, + target, + persister, + owner, + copyCache, + (SharedSessionContractImplementor) session + ); + } + /** * Instantiate an empty instance of the "underlying" collection (not a wrapper), * but with the given anticipated size (i.e. accounting for initial size diff --git a/hibernate-core/src/main/java/org/hibernate/usertype/UserType.java b/hibernate-core/src/main/java/org/hibernate/usertype/UserType.java index 4947f0cebf..3cf60ff758 100644 --- a/hibernate-core/src/main/java/org/hibernate/usertype/UserType.java +++ b/hibernate-core/src/main/java/org/hibernate/usertype/UserType.java @@ -12,9 +12,8 @@ import java.sql.ResultSet; import java.sql.SQLException; import org.hibernate.HibernateException; -import org.hibernate.boot.model.JavaTypeDescriptor; +import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.type.spi.TypeConfiguration; /** * This interface should be implemented by user-defined "types". @@ -95,6 +94,26 @@ public interface UserType { */ Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException; + /** + * Retrieve an instance of the mapped class from a JDBC resultset. Implementors + * should handle possibility of null values. + * + * @param rs a JDBC result set + * @param names the column names + * @param session + * @param owner the containing entity @return Object + * @throws HibernateException + * @throws SQLException + * + * @deprecated {@link #nullSafeGet(ResultSet, String[], SharedSessionContractImplementor, Object)} + * should be used instead. + */ + @Deprecated + default Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) + throws HibernateException, SQLException { + return nullSafeGet( rs, names, (SharedSessionContractImplementor) session, owner ); + } + /** * Write an instance of the mapped class to a prepared statement. Implementors * should handle possibility of null values. A multi-column type should be written @@ -110,6 +129,28 @@ public interface UserType { */ void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException; + /** + * Write an instance of the mapped class to a prepared statement. Implementors + * should handle possibility of null values. A multi-column type should be written + * to parameters starting from index. + * + * + * @param st a JDBC prepared statement + * @param value the object to write + * @param index statement parameter index + * @param session + * @throws HibernateException + * @throws SQLException + * + * @deprecated {@link #nullSafeSet(PreparedStatement, Object, int, SharedSessionContractImplementor)} + * should be used instead. + */ + @Deprecated + default void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) + throws HibernateException, SQLException { + nullSafeSet( st, value, index, (SharedSessionContractImplementor) session ); + } + /** * Return a deep copy of the persistent state, stopping at entities and at * collections. It is not necessary to copy immutable objects, or null diff --git a/hibernate-core/src/main/java/org/hibernate/usertype/UserVersionType.java b/hibernate-core/src/main/java/org/hibernate/usertype/UserVersionType.java index 7ae9d9c73d..daa7425c2c 100755 --- a/hibernate-core/src/main/java/org/hibernate/usertype/UserVersionType.java +++ b/hibernate-core/src/main/java/org/hibernate/usertype/UserVersionType.java @@ -8,6 +8,7 @@ package org.hibernate.usertype; import java.util.Comparator; +import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; /** @@ -26,6 +27,21 @@ public interface UserVersionType extends UserType, Comparator { */ Object seed(SharedSessionContractImplementor session); + /** + * Generate an initial version. + * + * @param session The session from which this request originates. May be + * null; currently this only happens during startup when trying to determine + * the "unsaved value" of entities. + * @return an instance of the type + * + * @deprecated {@link #seed(SharedSessionContractImplementor)} should be used instead. + */ + @Deprecated + default Object seed(SessionImplementor session) { + return seed( (SharedSessionContractImplementor) session ); + } + /** * Increment the version. * @@ -35,4 +51,18 @@ public interface UserVersionType extends UserType, Comparator { */ Object next(Object current, SharedSessionContractImplementor session); + /** + * Increment the version. + * + * @param session The session from which this request originates. + * @param current the current version + * @return an instance of the type + * + * @deprecated {@link #next(Object, SharedSessionContractImplementor)} should be used instead. + */ + @Deprecated + default Object next(Object current, SessionImplementor session) { + return next( current, (SharedSessionContractImplementor) session ); + } + }