diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java index f564e2d35f..474bdf4e15 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java @@ -180,6 +180,7 @@ import static org.hibernate.boot.model.internal.PropertyHolderBuilder.buildPrope import static org.hibernate.boot.model.internal.BinderHelper.extractFromPackage; import static org.hibernate.boot.model.source.internal.hbm.ModelBinder.useEntityWhereClauseForCollections; import static org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle.fromResultCheckStyle; +import static org.hibernate.internal.util.ReflectHelper.getDefaultConstructor; import static org.hibernate.internal.util.StringHelper.getNonEmptyOrConjunctionIfBothNonEmpty; import static org.hibernate.internal.util.StringHelper.isEmpty; import static org.hibernate.internal.util.StringHelper.isNotEmpty; @@ -1336,7 +1337,7 @@ public abstract class CollectionBinder { fromResultCheckStyle( sqlInsert.check() ) ); if ( sqlInsert.verify() != Expectation.class ) { - collection.setInsertExpectation( sqlInsert.verify() ); + collection.setInsertExpectation( getDefaultConstructor( sqlInsert.verify() ) ); } } @@ -1348,7 +1349,7 @@ public abstract class CollectionBinder { fromResultCheckStyle( sqlUpdate.check() ) ); if ( sqlUpdate.verify() != Expectation.class ) { - collection.setUpdateExpectation( sqlUpdate.verify() ); + collection.setUpdateExpectation( getDefaultConstructor( sqlUpdate.verify() ) ); } } @@ -1360,7 +1361,7 @@ public abstract class CollectionBinder { fromResultCheckStyle( sqlDelete.check() ) ); if ( sqlDelete.verify() != Expectation.class ) { - collection.setDeleteExpectation( sqlDelete.verify() ); + collection.setDeleteExpectation( getDefaultConstructor( sqlDelete.verify() ) ); } } @@ -1372,7 +1373,7 @@ public abstract class CollectionBinder { fromResultCheckStyle( sqlDeleteAll.check() ) ); if ( sqlDeleteAll.verify() != Expectation.class ) { - collection.setDeleteAllExpectation( sqlDeleteAll.verify() ); + collection.setDeleteAllExpectation( getDefaultConstructor( sqlDeleteAll.verify() ) ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/EntityBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/EntityBinder.java index 2fb4fbddfb..83cd2e91a0 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/EntityBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/EntityBinder.java @@ -160,6 +160,7 @@ import static org.hibernate.boot.model.internal.TableBinder.bindForeignKey; import static org.hibernate.boot.model.naming.Identifier.toIdentifier; import static org.hibernate.engine.OptimisticLockStyle.fromLockType; import static org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle.fromResultCheckStyle; +import static org.hibernate.internal.util.ReflectHelper.getDefaultConstructor; import static org.hibernate.internal.util.StringHelper.isEmpty; import static org.hibernate.internal.util.StringHelper.isNotEmpty; import static org.hibernate.internal.util.StringHelper.nullIfEmpty; @@ -1390,7 +1391,7 @@ public class EntityBinder { fromResultCheckStyle( sqlInsert.check() ) ); if ( sqlInsert.verify() != Expectation.class ) { - persistentClass.setInsertExpectation( sqlInsert.verify() ); + persistentClass.setInsertExpectation( getDefaultConstructor( sqlInsert.verify() ) ); } } @@ -1405,7 +1406,7 @@ public class EntityBinder { fromResultCheckStyle( sqlUpdate.check() ) ); if ( sqlUpdate.verify() != Expectation.class ) { - persistentClass.setUpdateExpectation( sqlUpdate.verify() ); + persistentClass.setUpdateExpectation( getDefaultConstructor( sqlUpdate.verify() ) ); } } @@ -1420,7 +1421,7 @@ public class EntityBinder { fromResultCheckStyle( sqlDelete.check() ) ); if ( sqlDelete.verify() != Expectation.class ) { - persistentClass.setDeleteExpectation( sqlDelete.verify() ); + persistentClass.setDeleteExpectation( getDefaultConstructor( sqlDelete.verify() ) ); } } @@ -2267,7 +2268,7 @@ public class EntityBinder { fromResultCheckStyle( sqlInsert.check() ) ); if ( sqlInsert.verify() != Expectation.class ) { - join.setInsertExpectation( sqlInsert.verify() ); + join.setInsertExpectation( getDefaultConstructor( sqlInsert.verify() ) ); } } else if ( matchingTable != null ) { @@ -2290,7 +2291,7 @@ public class EntityBinder { fromResultCheckStyle( sqlUpdate.check() ) ); if ( sqlUpdate.verify() != Expectation.class ) { - join.setUpdateExpectation( sqlUpdate.verify() ); + join.setUpdateExpectation( getDefaultConstructor( sqlUpdate.verify() ) ); } } else if ( matchingTable != null ) { @@ -2313,7 +2314,7 @@ public class EntityBinder { fromResultCheckStyle( sqlDelete.check() ) ); if ( sqlDelete.verify() != Expectation.class ) { - join.setDeleteExpectation( sqlDelete.verify() ); + join.setDeleteExpectation( getDefaultConstructor( sqlDelete.verify() ) ); } } else if ( matchingTable != null ) { diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/ExecuteUpdateResultCheckStyle.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/ExecuteUpdateResultCheckStyle.java index 62bf4105dc..0f88ff8391 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/ExecuteUpdateResultCheckStyle.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/ExecuteUpdateResultCheckStyle.java @@ -12,6 +12,8 @@ import org.hibernate.annotations.ResultCheckStyle; import org.checkerframework.checker.nullness.qual.Nullable; import org.hibernate.jdbc.Expectation; +import java.lang.reflect.Constructor; + /** * For persistence operations (INSERT, UPDATE, DELETE) what style of * determining results (success/failure) is to be used. @@ -90,12 +92,17 @@ public enum ExecuteUpdateResultCheckStyle { return customSql != null && callable ? PARAM : COUNT; } - public static @Nullable Class expectationClass(@Nullable ExecuteUpdateResultCheckStyle style) { - if ( style == null ) { - return null; + public static @Nullable Constructor expectationConstructor( + @Nullable ExecuteUpdateResultCheckStyle style) { + return style == null ? null : style.expectationConstructor(); + } + + public Constructor expectationConstructor() { + try { + return expectationClass().getDeclaredConstructor(); } - else { - return style.expectationClass(); + catch ( NoSuchMethodException e ) { + throw new AssertionFailure("Could not instantiate Expectation", e); } } diff --git a/hibernate-core/src/main/java/org/hibernate/jdbc/Expectations.java b/hibernate-core/src/main/java/org/hibernate/jdbc/Expectations.java index 3097d25c3b..b072a25e47 100644 --- a/hibernate-core/src/main/java/org/hibernate/jdbc/Expectations.java +++ b/hibernate-core/src/main/java/org/hibernate/jdbc/Expectations.java @@ -6,6 +6,7 @@ */ package org.hibernate.jdbc; +import java.lang.reflect.Constructor; import java.sql.CallableStatement; import java.sql.PreparedStatement; @@ -41,21 +42,29 @@ public class Expectations { * @since 6.5 */ @Internal - public static Expectation createExpectation(Class expectation, boolean callable) { - if ( expectation == null ) { - expectation = callable ? Expectation.OutParameter.class : Expectation.RowCount.class; - } - final Expectation instance; - try { - instance = expectation.newInstance(); - } - catch ( Exception e ) { - throw new InstantiationException( "Could not instantiate Expectation", expectation, e ); - } - instance.validate(callable); + public static Expectation createExpectation(Constructor expectation, boolean callable) { + final Expectation instance = instantiate( expectation, callable ); + instance.validate( callable ); return instance; } + private static Expectation instantiate(Constructor constructor, boolean callable) { + if ( constructor == null ) { + return callable + ? new Expectation.OutParameter() + : new Expectation.RowCount(); + } + else { + try { + return constructor.newInstance(); + } + catch ( Exception e ) { + throw new InstantiationException( "Could not instantiate Expectation", + constructor.getDeclaringClass(), e ); + } + } + } + static CallableStatement toCallableStatement(PreparedStatement statement) { if ( statement instanceof CallableStatement ) { return (CallableStatement) statement; diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Collection.java b/hibernate-core/src/main/java/org/hibernate/mapping/Collection.java index 1fb23f2d6a..31a6e774e6 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Collection.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Collection.java @@ -6,6 +6,7 @@ */ package org.hibernate.mapping; +import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -37,7 +38,7 @@ import org.hibernate.type.Type; import org.hibernate.usertype.UserCollectionType; import static org.hibernate.internal.util.collections.ArrayHelper.EMPTY_BOOLEAN_ARRAY; -import static org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle.expectationClass; +import static org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle.expectationConstructor; /** * A mapping model object representing a collection. Subclasses specialize to particular kinds of collection. @@ -107,10 +108,10 @@ public abstract class Collection implements Fetchable, Value, Filterable, SoftDe private String loaderName; - private Class insertExpectation; - private Class updateExpectation; - private Class deleteExpectation; - private Class deleteAllExpectation; + private Constructor insertExpectation; + private Constructor updateExpectation; + private Constructor deleteExpectation; + private Constructor deleteAllExpectation; /** * hbm.xml binding @@ -593,7 +594,7 @@ public abstract class Collection implements Fetchable, Value, Filterable, SoftDe this.customSQLInsert = customSQLInsert; this.customInsertCallable = callable; this.insertCheckStyle = checkStyle; - this.insertExpectation = expectationClass( checkStyle ); + this.insertExpectation = expectationConstructor( checkStyle ); } public String getCustomSQLInsert() { @@ -616,7 +617,7 @@ public abstract class Collection implements Fetchable, Value, Filterable, SoftDe this.customSQLUpdate = customSQLUpdate; this.customUpdateCallable = callable; this.updateCheckStyle = checkStyle; - this.updateExpectation = expectationClass( checkStyle ); + this.updateExpectation = expectationConstructor( checkStyle ); } public String getCustomSQLUpdate() { @@ -639,7 +640,7 @@ public abstract class Collection implements Fetchable, Value, Filterable, SoftDe this.customSQLDelete = customSQLDelete; this.customDeleteCallable = callable; this.deleteCheckStyle = checkStyle; - this.deleteExpectation = expectationClass( checkStyle ); + this.deleteExpectation = expectationConstructor( checkStyle ); } public String getCustomSQLDelete() { @@ -665,7 +666,7 @@ public abstract class Collection implements Fetchable, Value, Filterable, SoftDe this.customSQLDeleteAll = customSQLDeleteAll; this.customDeleteAllCallable = callable; this.deleteAllCheckStyle = checkStyle; - this.deleteAllExpectation = expectationClass( checkStyle ); + this.deleteAllExpectation = expectationConstructor( checkStyle ); } public String getCustomSQLDeleteAll() { @@ -876,35 +877,35 @@ public abstract class Collection implements Fetchable, Value, Filterable, SoftDe return softDeleteColumn; } - public Class getInsertExpectation() { + public Constructor getInsertExpectation() { return insertExpectation; } - public void setInsertExpectation(Class insertExpectation) { + public void setInsertExpectation(Constructor insertExpectation) { this.insertExpectation = insertExpectation; } - public Class getUpdateExpectation() { + public Constructor getUpdateExpectation() { return updateExpectation; } - public void setUpdateExpectation(Class updateExpectation) { + public void setUpdateExpectation(Constructor updateExpectation) { this.updateExpectation = updateExpectation; } - public Class getDeleteExpectation() { + public Constructor getDeleteExpectation() { return deleteExpectation; } - public void setDeleteExpectation(Class deleteExpectation) { + public void setDeleteExpectation(Constructor deleteExpectation) { this.deleteExpectation = deleteExpectation; } - public Class getDeleteAllExpectation() { + public Constructor getDeleteAllExpectation() { return deleteAllExpectation; } - public void setDeleteAllExpectation(Class deleteAllExpectation) { + public void setDeleteAllExpectation(Constructor deleteAllExpectation) { this.deleteAllExpectation = deleteAllExpectation; } } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Join.java b/hibernate-core/src/main/java/org/hibernate/mapping/Join.java index fe7ddb6062..aba1583fbd 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Join.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Join.java @@ -7,6 +7,7 @@ package org.hibernate.mapping; import java.io.Serializable; +import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -15,7 +16,7 @@ import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle; import org.hibernate.jdbc.Expectation; import org.hibernate.sql.Alias; -import static org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle.expectationClass; +import static org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle.expectationConstructor; /** * A mapping model object representing some sort of auxiliary table, for @@ -50,9 +51,9 @@ public class Join implements AttributeContainer, Serializable { private boolean customDeleteCallable; private ExecuteUpdateResultCheckStyle deleteCheckStyle; - private Class insertExpectation; - private Class updateExpectation; - private Class deleteExpectation; + private Constructor insertExpectation; + private Constructor updateExpectation; + private Constructor deleteExpectation; @Override public void addProperty(Property property) { @@ -140,7 +141,7 @@ public class Join implements AttributeContainer, Serializable { this.customSQLInsert = customSQLInsert; this.customInsertCallable = callable; this.insertCheckStyle = checkStyle; - this.insertExpectation = expectationClass( checkStyle ); + this.insertExpectation = expectationConstructor( checkStyle ); } public String getCustomSQLInsert() { @@ -163,7 +164,7 @@ public class Join implements AttributeContainer, Serializable { this.customSQLUpdate = customSQLUpdate; this.customUpdateCallable = callable; this.updateCheckStyle = checkStyle; - this.updateExpectation = expectationClass( checkStyle ); + this.updateExpectation = expectationConstructor( checkStyle ); } public String getCustomSQLUpdate() { @@ -186,7 +187,7 @@ public class Join implements AttributeContainer, Serializable { this.customSQLDelete = customSQLDelete; this.customDeleteCallable = callable; this.deleteCheckStyle = checkStyle; - this.deleteExpectation = expectationClass( checkStyle ); + this.deleteExpectation = expectationConstructor( checkStyle ); } public String getCustomSQLDelete() { @@ -234,27 +235,27 @@ public class Join implements AttributeContainer, Serializable { this.optional = nullable; } - public Class getInsertExpectation() { + public Constructor getInsertExpectation() { return insertExpectation; } - public void setInsertExpectation(Class insertExpectation) { + public void setInsertExpectation(Constructor insertExpectation) { this.insertExpectation = insertExpectation; } - public Class getUpdateExpectation() { + public Constructor getUpdateExpectation() { return updateExpectation; } - public void setUpdateExpectation(Class updateExpectation) { + public void setUpdateExpectation(Constructor updateExpectation) { this.updateExpectation = updateExpectation; } - public Class getDeleteExpectation() { + public Constructor getDeleteExpectation() { return deleteExpectation; } - public void setDeleteExpectation(Class deleteExpectation) { + public void setDeleteExpectation(Constructor deleteExpectation) { this.deleteExpectation = deleteExpectation; } } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java b/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java index 917e3cd85e..8b82e9523f 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java @@ -7,6 +7,7 @@ package org.hibernate.mapping; import java.io.Serializable; +import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; @@ -43,7 +44,7 @@ import static java.util.Collections.unmodifiableList; import static java.util.Comparator.comparing; import static org.hibernate.internal.util.StringHelper.qualify; import static org.hibernate.internal.util.StringHelper.root; -import static org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle.expectationClass; +import static org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle.expectationConstructor; import static org.hibernate.mapping.MappingHelper.checkPropertyColumnDuplication; import static org.hibernate.sql.Template.collectColumnNames; @@ -121,9 +122,9 @@ public abstract class PersistentClass implements IdentifiableTypeClass, Attribut private Component declaredIdentifierMapper; private OptimisticLockStyle optimisticLockStyle; - private Class insertExpectation; - private Class updateExpectation; - private Class deleteExpectation; + private Constructor insertExpectation; + private Constructor updateExpectation; + private Constructor deleteExpectation; private boolean isCached; private CacheLayout queryCacheLayout; @@ -802,7 +803,7 @@ public abstract class PersistentClass implements IdentifiableTypeClass, Attribut this.customSQLInsert = customSQLInsert; this.customInsertCallable = callable; this.insertCheckStyle = checkStyle; - this.insertExpectation = expectationClass( checkStyle ); + this.insertExpectation = expectationConstructor( checkStyle ); } public String getCustomSQLInsert() { @@ -825,7 +826,7 @@ public abstract class PersistentClass implements IdentifiableTypeClass, Attribut this.customSQLUpdate = customSQLUpdate; this.customUpdateCallable = callable; this.updateCheckStyle = checkStyle; - this.updateExpectation = expectationClass( checkStyle ); + this.updateExpectation = expectationConstructor( checkStyle ); } public String getCustomSQLUpdate() { @@ -848,7 +849,7 @@ public abstract class PersistentClass implements IdentifiableTypeClass, Attribut this.customSQLDelete = customSQLDelete; this.customDeleteCallable = callable; this.deleteCheckStyle = checkStyle; - this.deleteExpectation = expectationClass( checkStyle ); + this.deleteExpectation = expectationConstructor( checkStyle ); } public String getCustomSQLDelete() { @@ -1262,27 +1263,27 @@ public abstract class PersistentClass implements IdentifiableTypeClass, Attribut return null; } - public Class getInsertExpectation() { + public Constructor getInsertExpectation() { return insertExpectation; } - public void setInsertExpectation(Class insertExpectation) { + public void setInsertExpectation(Constructor insertExpectation) { this.insertExpectation = insertExpectation; } - public Class getUpdateExpectation() { + public Constructor getUpdateExpectation() { return updateExpectation; } - public void setUpdateExpectation(Class updateExpectation) { + public void setUpdateExpectation(Constructor updateExpectation) { this.updateExpectation = updateExpectation; } - public Class getDeleteExpectation() { + public Constructor getDeleteExpectation() { return deleteExpectation; } - public void setDeleteExpectation(Class deleteExpectation) { + public void setDeleteExpectation(Constructor deleteExpectation) { this.deleteExpectation = deleteExpectation; } } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/attributebinder/typebinder/NoResultCheck.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/attributebinder/typebinder/NoResultCheck.java index 969b261cff..17627893a4 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/attributebinder/typebinder/NoResultCheck.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/attributebinder/typebinder/NoResultCheck.java @@ -20,9 +20,14 @@ public @interface NoResultCheck { class Binder implements TypeBinder { @Override public void bind(NoResultCheck annotation, MetadataBuildingContext buildingContext, PersistentClass persistentClass) { - persistentClass.setInsertExpectation(Expectation.None.class); - persistentClass.setUpdateExpectation(Expectation.None.class); - persistentClass.setDeleteExpectation(Expectation.None.class); + try { + persistentClass.setInsertExpectation(Expectation.None.class.getDeclaredConstructor()); + persistentClass.setUpdateExpectation(Expectation.None.class.getDeclaredConstructor()); + persistentClass.setDeleteExpectation(Expectation.None.class.getDeclaredConstructor()); + } + catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } } @Override