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 474bdf4e15..7ffcf67bd3 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,7 +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.ReflectHelper.getDefaultSupplier; import static org.hibernate.internal.util.StringHelper.getNonEmptyOrConjunctionIfBothNonEmpty; import static org.hibernate.internal.util.StringHelper.isEmpty; import static org.hibernate.internal.util.StringHelper.isNotEmpty; @@ -1337,7 +1337,7 @@ public abstract class CollectionBinder { fromResultCheckStyle( sqlInsert.check() ) ); if ( sqlInsert.verify() != Expectation.class ) { - collection.setInsertExpectation( getDefaultConstructor( sqlInsert.verify() ) ); + collection.setInsertExpectation( getDefaultSupplier( sqlInsert.verify() ) ); } } @@ -1349,7 +1349,7 @@ public abstract class CollectionBinder { fromResultCheckStyle( sqlUpdate.check() ) ); if ( sqlUpdate.verify() != Expectation.class ) { - collection.setUpdateExpectation( getDefaultConstructor( sqlUpdate.verify() ) ); + collection.setUpdateExpectation( getDefaultSupplier( sqlUpdate.verify() ) ); } } @@ -1361,7 +1361,7 @@ public abstract class CollectionBinder { fromResultCheckStyle( sqlDelete.check() ) ); if ( sqlDelete.verify() != Expectation.class ) { - collection.setDeleteExpectation( getDefaultConstructor( sqlDelete.verify() ) ); + collection.setDeleteExpectation( getDefaultSupplier( sqlDelete.verify() ) ); } } @@ -1373,7 +1373,7 @@ public abstract class CollectionBinder { fromResultCheckStyle( sqlDeleteAll.check() ) ); if ( sqlDeleteAll.verify() != Expectation.class ) { - collection.setDeleteAllExpectation( getDefaultConstructor( sqlDeleteAll.verify() ) ); + collection.setDeleteAllExpectation( getDefaultSupplier( 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 83cd2e91a0..1cc1aa9d8d 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,7 +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.ReflectHelper.getDefaultSupplier; import static org.hibernate.internal.util.StringHelper.isEmpty; import static org.hibernate.internal.util.StringHelper.isNotEmpty; import static org.hibernate.internal.util.StringHelper.nullIfEmpty; @@ -1391,7 +1391,7 @@ public class EntityBinder { fromResultCheckStyle( sqlInsert.check() ) ); if ( sqlInsert.verify() != Expectation.class ) { - persistentClass.setInsertExpectation( getDefaultConstructor( sqlInsert.verify() ) ); + persistentClass.setInsertExpectation( getDefaultSupplier( sqlInsert.verify() ) ); } } @@ -1406,7 +1406,7 @@ public class EntityBinder { fromResultCheckStyle( sqlUpdate.check() ) ); if ( sqlUpdate.verify() != Expectation.class ) { - persistentClass.setUpdateExpectation( getDefaultConstructor( sqlUpdate.verify() ) ); + persistentClass.setUpdateExpectation( getDefaultSupplier( sqlUpdate.verify() ) ); } } @@ -1421,7 +1421,7 @@ public class EntityBinder { fromResultCheckStyle( sqlDelete.check() ) ); if ( sqlDelete.verify() != Expectation.class ) { - persistentClass.setDeleteExpectation( getDefaultConstructor( sqlDelete.verify() ) ); + persistentClass.setDeleteExpectation( getDefaultSupplier( sqlDelete.verify() ) ); } } @@ -2268,7 +2268,7 @@ public class EntityBinder { fromResultCheckStyle( sqlInsert.check() ) ); if ( sqlInsert.verify() != Expectation.class ) { - join.setInsertExpectation( getDefaultConstructor( sqlInsert.verify() ) ); + join.setInsertExpectation( getDefaultSupplier( sqlInsert.verify() ) ); } } else if ( matchingTable != null ) { @@ -2291,7 +2291,7 @@ public class EntityBinder { fromResultCheckStyle( sqlUpdate.check() ) ); if ( sqlUpdate.verify() != Expectation.class ) { - join.setUpdateExpectation( getDefaultConstructor( sqlUpdate.verify() ) ); + join.setUpdateExpectation( getDefaultSupplier( sqlUpdate.verify() ) ); } } else if ( matchingTable != null ) { @@ -2314,7 +2314,7 @@ public class EntityBinder { fromResultCheckStyle( sqlDelete.check() ) ); if ( sqlDelete.verify() != Expectation.class ) { - join.setDeleteExpectation( getDefaultConstructor( sqlDelete.verify() ) ); + join.setDeleteExpectation( getDefaultSupplier( 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 0f88ff8391..0d95cb386a 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,7 +12,7 @@ import org.hibernate.annotations.ResultCheckStyle; import org.checkerframework.checker.nullness.qual.Nullable; import org.hibernate.jdbc.Expectation; -import java.lang.reflect.Constructor; +import java.util.function.Supplier; /** * For persistence operations (INSERT, UPDATE, DELETE) what style of @@ -92,17 +92,21 @@ public enum ExecuteUpdateResultCheckStyle { return customSql != null && callable ? PARAM : COUNT; } - public static @Nullable Constructor expectationConstructor( + public static @Nullable Supplier expectationConstructor( @Nullable ExecuteUpdateResultCheckStyle style) { return style == null ? null : style.expectationConstructor(); } - public Constructor expectationConstructor() { - try { - return expectationClass().getDeclaredConstructor(); - } - catch ( NoSuchMethodException e ) { - throw new AssertionFailure("Could not instantiate Expectation", e); + public Supplier expectationConstructor() { + switch (this) { + case NONE: + return Expectation.None::new; + case COUNT: + return Expectation.RowCount::new; + case PARAM: + return Expectation.OutParameter::new; + default: + throw new AssertionFailure( "Unrecognized ExecuteUpdateResultCheckStyle"); } } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/ReflectHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/ReflectHelper.java index 50452cda86..0158697781 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/ReflectHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/ReflectHelper.java @@ -10,6 +10,7 @@ import java.beans.Introspector; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -17,6 +18,7 @@ import java.lang.reflect.ParameterizedType; import java.lang.reflect.TypeVariable; import java.lang.reflect.WildcardType; import java.util.Locale; +import java.util.function.Supplier; import org.hibernate.AssertionFailure; import org.hibernate.MappingException; @@ -39,7 +41,6 @@ import jakarta.persistence.Transient; * @author Steve Ebersole * @author Chris Cranford */ -@SuppressWarnings("unchecked") public final class ReflectHelper { public static final Class[] NO_PARAM_SIGNATURE = ArrayHelper.EMPTY_CLASS_ARRAY; @@ -298,6 +299,35 @@ public final class ReflectHelper { } } + public static Supplier getDefaultSupplier(Class clazz) { + if ( isAbstractClass( clazz ) ) { + throw new IllegalArgumentException( "Abstract class cannot be instantiated: " + clazz.getName() ); + } + + try { + final Constructor constructor = clazz.getDeclaredConstructor( NO_PARAM_SIGNATURE ); + ensureAccessibility( constructor ); + return () -> { + try { + return constructor.newInstance(); + } + catch ( InstantiationException|IllegalAccessException|InvocationTargetException e ) { + throw new org.hibernate.InstantiationException( "Constructor threw exception", clazz, e ); + } + }; + } + catch ( NoSuchMethodException nme ) { + return () -> { + try { + return clazz.newInstance(); + } + catch ( InstantiationException|IllegalAccessException e ) { + throw new org.hibernate.InstantiationException( "Default constructor threw exception", clazz, e ); + } + }; + } + } + /** * Determine if the given class is declared abstract. * 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 b072a25e47..7d871b2d43 100644 --- a/hibernate-core/src/main/java/org/hibernate/jdbc/Expectations.java +++ b/hibernate-core/src/main/java/org/hibernate/jdbc/Expectations.java @@ -6,13 +6,12 @@ */ package org.hibernate.jdbc; -import java.lang.reflect.Constructor; import java.sql.CallableStatement; import java.sql.PreparedStatement; +import java.util.function.Supplier; import org.hibernate.AssertionFailure; import org.hibernate.HibernateException; -import org.hibernate.InstantiationException; import org.hibernate.Internal; import org.hibernate.StaleStateException; import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; @@ -42,26 +41,20 @@ public class Expectations { * @since 6.5 */ @Internal - public static Expectation createExpectation(Constructor expectation, boolean callable) { + public static Expectation createExpectation(Supplier 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 ) { + private static Expectation instantiate(Supplier supplier, boolean callable) { + if ( supplier == 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 ); - } + return supplier.get(); } } 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 31a6e774e6..dfc6dadca9 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Collection.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Collection.java @@ -6,7 +6,6 @@ */ package org.hibernate.mapping; -import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -108,10 +107,10 @@ public abstract class Collection implements Fetchable, Value, Filterable, SoftDe private String loaderName; - private Constructor insertExpectation; - private Constructor updateExpectation; - private Constructor deleteExpectation; - private Constructor deleteAllExpectation; + private Supplier insertExpectation; + private Supplier updateExpectation; + private Supplier deleteExpectation; + private Supplier deleteAllExpectation; /** * hbm.xml binding @@ -877,35 +876,35 @@ public abstract class Collection implements Fetchable, Value, Filterable, SoftDe return softDeleteColumn; } - public Constructor getInsertExpectation() { + public Supplier getInsertExpectation() { return insertExpectation; } - public void setInsertExpectation(Constructor insertExpectation) { + public void setInsertExpectation(Supplier insertExpectation) { this.insertExpectation = insertExpectation; } - public Constructor getUpdateExpectation() { + public Supplier getUpdateExpectation() { return updateExpectation; } - public void setUpdateExpectation(Constructor updateExpectation) { + public void setUpdateExpectation(Supplier updateExpectation) { this.updateExpectation = updateExpectation; } - public Constructor getDeleteExpectation() { + public Supplier getDeleteExpectation() { return deleteExpectation; } - public void setDeleteExpectation(Constructor deleteExpectation) { + public void setDeleteExpectation(Supplier deleteExpectation) { this.deleteExpectation = deleteExpectation; } - public Constructor getDeleteAllExpectation() { + public Supplier getDeleteAllExpectation() { return deleteAllExpectation; } - public void setDeleteAllExpectation(Constructor deleteAllExpectation) { + public void setDeleteAllExpectation(Supplier 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 aba1583fbd..7418078f11 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Join.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Join.java @@ -7,10 +7,10 @@ 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; +import java.util.function.Supplier; import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle; import org.hibernate.jdbc.Expectation; @@ -51,9 +51,9 @@ public class Join implements AttributeContainer, Serializable { private boolean customDeleteCallable; private ExecuteUpdateResultCheckStyle deleteCheckStyle; - private Constructor insertExpectation; - private Constructor updateExpectation; - private Constructor deleteExpectation; + private Supplier insertExpectation; + private Supplier updateExpectation; + private Supplier deleteExpectation; @Override public void addProperty(Property property) { @@ -235,27 +235,27 @@ public class Join implements AttributeContainer, Serializable { this.optional = nullable; } - public Constructor getInsertExpectation() { + public Supplier getInsertExpectation() { return insertExpectation; } - public void setInsertExpectation(Constructor insertExpectation) { + public void setInsertExpectation(Supplier insertExpectation) { this.insertExpectation = insertExpectation; } - public Constructor getUpdateExpectation() { + public Supplier getUpdateExpectation() { return updateExpectation; } - public void setUpdateExpectation(Constructor updateExpectation) { + public void setUpdateExpectation(Supplier updateExpectation) { this.updateExpectation = updateExpectation; } - public Constructor getDeleteExpectation() { + public Supplier getDeleteExpectation() { return deleteExpectation; } - public void setDeleteExpectation(Constructor deleteExpectation) { + public void setDeleteExpectation(Supplier 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 8b82e9523f..f03e4bb1a0 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java @@ -7,7 +7,6 @@ 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; @@ -15,6 +14,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.StringTokenizer; +import java.util.function.Supplier; import org.hibernate.Internal; import org.hibernate.MappingException; @@ -122,9 +122,9 @@ public abstract class PersistentClass implements IdentifiableTypeClass, Attribut private Component declaredIdentifierMapper; private OptimisticLockStyle optimisticLockStyle; - private Constructor insertExpectation; - private Constructor updateExpectation; - private Constructor deleteExpectation; + private Supplier insertExpectation; + private Supplier updateExpectation; + private Supplier deleteExpectation; private boolean isCached; private CacheLayout queryCacheLayout; @@ -1263,27 +1263,27 @@ public abstract class PersistentClass implements IdentifiableTypeClass, Attribut return null; } - public Constructor getInsertExpectation() { + public Supplier getInsertExpectation() { return insertExpectation; } - public void setInsertExpectation(Constructor insertExpectation) { + public void setInsertExpectation(Supplier insertExpectation) { this.insertExpectation = insertExpectation; } - public Constructor getUpdateExpectation() { + public Supplier getUpdateExpectation() { return updateExpectation; } - public void setUpdateExpectation(Constructor updateExpectation) { + public void setUpdateExpectation(Supplier updateExpectation) { this.updateExpectation = updateExpectation; } - public Constructor getDeleteExpectation() { + public Supplier getDeleteExpectation() { return deleteExpectation; } - public void setDeleteExpectation(Constructor deleteExpectation) { + public void setDeleteExpectation(Supplier 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 17627893a4..e08cd6ff13 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,14 +20,9 @@ public @interface NoResultCheck { class Binder implements TypeBinder { @Override public void bind(NoResultCheck annotation, MetadataBuildingContext buildingContext, PersistentClass persistentClass) { - 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); - } + persistentClass.setInsertExpectation(Expectation.None::new); + persistentClass.setUpdateExpectation(Expectation.None::new); + persistentClass.setDeleteExpectation(Expectation.None::new); } @Override