HHH-17999 use Supplier instead of Constructor

this is quite a lot cleaner

Signed-off-by: Gavin King <gavin@hibernate.org>
This commit is contained in:
Gavin King 2024-04-23 14:04:11 +02:00
parent 0468e04955
commit 2bc78d50b0
9 changed files with 95 additions and 74 deletions

View File

@ -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.internal.BinderHelper.extractFromPackage;
import static org.hibernate.boot.model.source.internal.hbm.ModelBinder.useEntityWhereClauseForCollections; import static org.hibernate.boot.model.source.internal.hbm.ModelBinder.useEntityWhereClauseForCollections;
import static org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle.fromResultCheckStyle; 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.getNonEmptyOrConjunctionIfBothNonEmpty;
import static org.hibernate.internal.util.StringHelper.isEmpty; import static org.hibernate.internal.util.StringHelper.isEmpty;
import static org.hibernate.internal.util.StringHelper.isNotEmpty; import static org.hibernate.internal.util.StringHelper.isNotEmpty;
@ -1337,7 +1337,7 @@ public abstract class CollectionBinder {
fromResultCheckStyle( sqlInsert.check() ) fromResultCheckStyle( sqlInsert.check() )
); );
if ( sqlInsert.verify() != Expectation.class ) { 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() ) fromResultCheckStyle( sqlUpdate.check() )
); );
if ( sqlUpdate.verify() != Expectation.class ) { 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() ) fromResultCheckStyle( sqlDelete.check() )
); );
if ( sqlDelete.verify() != Expectation.class ) { 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() ) fromResultCheckStyle( sqlDeleteAll.check() )
); );
if ( sqlDeleteAll.verify() != Expectation.class ) { if ( sqlDeleteAll.verify() != Expectation.class ) {
collection.setDeleteAllExpectation( getDefaultConstructor( sqlDeleteAll.verify() ) ); collection.setDeleteAllExpectation( getDefaultSupplier( sqlDeleteAll.verify() ) );
} }
} }

View File

@ -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.boot.model.naming.Identifier.toIdentifier;
import static org.hibernate.engine.OptimisticLockStyle.fromLockType; import static org.hibernate.engine.OptimisticLockStyle.fromLockType;
import static org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle.fromResultCheckStyle; 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.isEmpty;
import static org.hibernate.internal.util.StringHelper.isNotEmpty; import static org.hibernate.internal.util.StringHelper.isNotEmpty;
import static org.hibernate.internal.util.StringHelper.nullIfEmpty; import static org.hibernate.internal.util.StringHelper.nullIfEmpty;
@ -1391,7 +1391,7 @@ public class EntityBinder {
fromResultCheckStyle( sqlInsert.check() ) fromResultCheckStyle( sqlInsert.check() )
); );
if ( sqlInsert.verify() != Expectation.class ) { 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() ) fromResultCheckStyle( sqlUpdate.check() )
); );
if ( sqlUpdate.verify() != Expectation.class ) { 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() ) fromResultCheckStyle( sqlDelete.check() )
); );
if ( sqlDelete.verify() != Expectation.class ) { 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() ) fromResultCheckStyle( sqlInsert.check() )
); );
if ( sqlInsert.verify() != Expectation.class ) { if ( sqlInsert.verify() != Expectation.class ) {
join.setInsertExpectation( getDefaultConstructor( sqlInsert.verify() ) ); join.setInsertExpectation( getDefaultSupplier( sqlInsert.verify() ) );
} }
} }
else if ( matchingTable != null ) { else if ( matchingTable != null ) {
@ -2291,7 +2291,7 @@ public class EntityBinder {
fromResultCheckStyle( sqlUpdate.check() ) fromResultCheckStyle( sqlUpdate.check() )
); );
if ( sqlUpdate.verify() != Expectation.class ) { if ( sqlUpdate.verify() != Expectation.class ) {
join.setUpdateExpectation( getDefaultConstructor( sqlUpdate.verify() ) ); join.setUpdateExpectation( getDefaultSupplier( sqlUpdate.verify() ) );
} }
} }
else if ( matchingTable != null ) { else if ( matchingTable != null ) {
@ -2314,7 +2314,7 @@ public class EntityBinder {
fromResultCheckStyle( sqlDelete.check() ) fromResultCheckStyle( sqlDelete.check() )
); );
if ( sqlDelete.verify() != Expectation.class ) { if ( sqlDelete.verify() != Expectation.class ) {
join.setDeleteExpectation( getDefaultConstructor( sqlDelete.verify() ) ); join.setDeleteExpectation( getDefaultSupplier( sqlDelete.verify() ) );
} }
} }
else if ( matchingTable != null ) { else if ( matchingTable != null ) {

View File

@ -12,7 +12,7 @@ import org.hibernate.annotations.ResultCheckStyle;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.hibernate.jdbc.Expectation; import org.hibernate.jdbc.Expectation;
import java.lang.reflect.Constructor; import java.util.function.Supplier;
/** /**
* For persistence operations (INSERT, UPDATE, DELETE) what style of * For persistence operations (INSERT, UPDATE, DELETE) what style of
@ -92,17 +92,21 @@ public enum ExecuteUpdateResultCheckStyle {
return customSql != null && callable ? PARAM : COUNT; return customSql != null && callable ? PARAM : COUNT;
} }
public static @Nullable Constructor<? extends Expectation> expectationConstructor( public static @Nullable Supplier<? extends Expectation> expectationConstructor(
@Nullable ExecuteUpdateResultCheckStyle style) { @Nullable ExecuteUpdateResultCheckStyle style) {
return style == null ? null : style.expectationConstructor(); return style == null ? null : style.expectationConstructor();
} }
public Constructor<? extends Expectation> expectationConstructor() { public Supplier<? extends Expectation> expectationConstructor() {
try { switch (this) {
return expectationClass().getDeclaredConstructor(); case NONE:
} return Expectation.None::new;
catch ( NoSuchMethodException e ) { case COUNT:
throw new AssertionFailure("Could not instantiate Expectation", e); return Expectation.RowCount::new;
case PARAM:
return Expectation.OutParameter::new;
default:
throw new AssertionFailure( "Unrecognized ExecuteUpdateResultCheckStyle");
} }
} }

View File

@ -10,6 +10,7 @@ import java.beans.Introspector;
import java.lang.reflect.AccessibleObject; import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
@ -17,6 +18,7 @@ import java.lang.reflect.ParameterizedType;
import java.lang.reflect.TypeVariable; import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType; import java.lang.reflect.WildcardType;
import java.util.Locale; import java.util.Locale;
import java.util.function.Supplier;
import org.hibernate.AssertionFailure; import org.hibernate.AssertionFailure;
import org.hibernate.MappingException; import org.hibernate.MappingException;
@ -39,7 +41,6 @@ import jakarta.persistence.Transient;
* @author Steve Ebersole * @author Steve Ebersole
* @author Chris Cranford * @author Chris Cranford
*/ */
@SuppressWarnings("unchecked")
public final class ReflectHelper { public final class ReflectHelper {
public static final Class<?>[] NO_PARAM_SIGNATURE = ArrayHelper.EMPTY_CLASS_ARRAY; public static final Class<?>[] NO_PARAM_SIGNATURE = ArrayHelper.EMPTY_CLASS_ARRAY;
@ -298,6 +299,35 @@ public final class ReflectHelper {
} }
} }
public static <T> Supplier<T> getDefaultSupplier(Class<T> clazz) {
if ( isAbstractClass( clazz ) ) {
throw new IllegalArgumentException( "Abstract class cannot be instantiated: " + clazz.getName() );
}
try {
final Constructor<T> 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. * Determine if the given class is declared abstract.
* *

View File

@ -6,13 +6,12 @@
*/ */
package org.hibernate.jdbc; package org.hibernate.jdbc;
import java.lang.reflect.Constructor;
import java.sql.CallableStatement; import java.sql.CallableStatement;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.util.function.Supplier;
import org.hibernate.AssertionFailure; import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.InstantiationException;
import org.hibernate.Internal; import org.hibernate.Internal;
import org.hibernate.StaleStateException; import org.hibernate.StaleStateException;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
@ -42,26 +41,20 @@ public class Expectations {
* @since 6.5 * @since 6.5
*/ */
@Internal @Internal
public static Expectation createExpectation(Constructor<? extends Expectation> expectation, boolean callable) { public static Expectation createExpectation(Supplier<? extends Expectation> expectation, boolean callable) {
final Expectation instance = instantiate( expectation, callable ); final Expectation instance = instantiate( expectation, callable );
instance.validate( callable ); instance.validate( callable );
return instance; return instance;
} }
private static Expectation instantiate(Constructor<? extends Expectation> constructor, boolean callable) { private static Expectation instantiate(Supplier<? extends Expectation> supplier, boolean callable) {
if ( constructor == null ) { if ( supplier == null ) {
return callable return callable
? new Expectation.OutParameter() ? new Expectation.OutParameter()
: new Expectation.RowCount(); : new Expectation.RowCount();
} }
else { else {
try { return supplier.get();
return constructor.newInstance();
}
catch ( Exception e ) {
throw new InstantiationException( "Could not instantiate Expectation",
constructor.getDeclaringClass(), e );
}
} }
} }

View File

@ -6,7 +6,6 @@
*/ */
package org.hibernate.mapping; package org.hibernate.mapping;
import java.lang.reflect.Constructor;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
@ -108,10 +107,10 @@ public abstract class Collection implements Fetchable, Value, Filterable, SoftDe
private String loaderName; private String loaderName;
private Constructor<? extends Expectation> insertExpectation; private Supplier<? extends Expectation> insertExpectation;
private Constructor<? extends Expectation> updateExpectation; private Supplier<? extends Expectation> updateExpectation;
private Constructor<? extends Expectation> deleteExpectation; private Supplier<? extends Expectation> deleteExpectation;
private Constructor<? extends Expectation> deleteAllExpectation; private Supplier<? extends Expectation> deleteAllExpectation;
/** /**
* hbm.xml binding * hbm.xml binding
@ -877,35 +876,35 @@ public abstract class Collection implements Fetchable, Value, Filterable, SoftDe
return softDeleteColumn; return softDeleteColumn;
} }
public Constructor<? extends Expectation> getInsertExpectation() { public Supplier<? extends Expectation> getInsertExpectation() {
return insertExpectation; return insertExpectation;
} }
public void setInsertExpectation(Constructor<? extends Expectation> insertExpectation) { public void setInsertExpectation(Supplier<? extends Expectation> insertExpectation) {
this.insertExpectation = insertExpectation; this.insertExpectation = insertExpectation;
} }
public Constructor<? extends Expectation> getUpdateExpectation() { public Supplier<? extends Expectation> getUpdateExpectation() {
return updateExpectation; return updateExpectation;
} }
public void setUpdateExpectation(Constructor<? extends Expectation> updateExpectation) { public void setUpdateExpectation(Supplier<? extends Expectation> updateExpectation) {
this.updateExpectation = updateExpectation; this.updateExpectation = updateExpectation;
} }
public Constructor<? extends Expectation> getDeleteExpectation() { public Supplier<? extends Expectation> getDeleteExpectation() {
return deleteExpectation; return deleteExpectation;
} }
public void setDeleteExpectation(Constructor<? extends Expectation> deleteExpectation) { public void setDeleteExpectation(Supplier<? extends Expectation> deleteExpectation) {
this.deleteExpectation = deleteExpectation; this.deleteExpectation = deleteExpectation;
} }
public Constructor<? extends Expectation> getDeleteAllExpectation() { public Supplier<? extends Expectation> getDeleteAllExpectation() {
return deleteAllExpectation; return deleteAllExpectation;
} }
public void setDeleteAllExpectation(Constructor<? extends Expectation> deleteAllExpectation) { public void setDeleteAllExpectation(Supplier<? extends Expectation> deleteAllExpectation) {
this.deleteAllExpectation = deleteAllExpectation; this.deleteAllExpectation = deleteAllExpectation;
} }
} }

View File

@ -7,10 +7,10 @@
package org.hibernate.mapping; package org.hibernate.mapping;
import java.io.Serializable; import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.function.Supplier;
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle; import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
import org.hibernate.jdbc.Expectation; import org.hibernate.jdbc.Expectation;
@ -51,9 +51,9 @@ public class Join implements AttributeContainer, Serializable {
private boolean customDeleteCallable; private boolean customDeleteCallable;
private ExecuteUpdateResultCheckStyle deleteCheckStyle; private ExecuteUpdateResultCheckStyle deleteCheckStyle;
private Constructor<? extends Expectation> insertExpectation; private Supplier<? extends Expectation> insertExpectation;
private Constructor<? extends Expectation> updateExpectation; private Supplier<? extends Expectation> updateExpectation;
private Constructor<? extends Expectation> deleteExpectation; private Supplier<? extends Expectation> deleteExpectation;
@Override @Override
public void addProperty(Property property) { public void addProperty(Property property) {
@ -235,27 +235,27 @@ public class Join implements AttributeContainer, Serializable {
this.optional = nullable; this.optional = nullable;
} }
public Constructor<? extends Expectation> getInsertExpectation() { public Supplier<? extends Expectation> getInsertExpectation() {
return insertExpectation; return insertExpectation;
} }
public void setInsertExpectation(Constructor<? extends Expectation> insertExpectation) { public void setInsertExpectation(Supplier<? extends Expectation> insertExpectation) {
this.insertExpectation = insertExpectation; this.insertExpectation = insertExpectation;
} }
public Constructor<? extends Expectation> getUpdateExpectation() { public Supplier<? extends Expectation> getUpdateExpectation() {
return updateExpectation; return updateExpectation;
} }
public void setUpdateExpectation(Constructor<? extends Expectation> updateExpectation) { public void setUpdateExpectation(Supplier<? extends Expectation> updateExpectation) {
this.updateExpectation = updateExpectation; this.updateExpectation = updateExpectation;
} }
public Constructor<? extends Expectation> getDeleteExpectation() { public Supplier<? extends Expectation> getDeleteExpectation() {
return deleteExpectation; return deleteExpectation;
} }
public void setDeleteExpectation(Constructor<? extends Expectation> deleteExpectation) { public void setDeleteExpectation(Supplier<? extends Expectation> deleteExpectation) {
this.deleteExpectation = deleteExpectation; this.deleteExpectation = deleteExpectation;
} }
} }

View File

@ -7,7 +7,6 @@
package org.hibernate.mapping; package org.hibernate.mapping;
import java.io.Serializable; import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
@ -15,6 +14,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import java.util.function.Supplier;
import org.hibernate.Internal; import org.hibernate.Internal;
import org.hibernate.MappingException; import org.hibernate.MappingException;
@ -122,9 +122,9 @@ public abstract class PersistentClass implements IdentifiableTypeClass, Attribut
private Component declaredIdentifierMapper; private Component declaredIdentifierMapper;
private OptimisticLockStyle optimisticLockStyle; private OptimisticLockStyle optimisticLockStyle;
private Constructor<? extends Expectation> insertExpectation; private Supplier<? extends Expectation> insertExpectation;
private Constructor<? extends Expectation> updateExpectation; private Supplier<? extends Expectation> updateExpectation;
private Constructor<? extends Expectation> deleteExpectation; private Supplier<? extends Expectation> deleteExpectation;
private boolean isCached; private boolean isCached;
private CacheLayout queryCacheLayout; private CacheLayout queryCacheLayout;
@ -1263,27 +1263,27 @@ public abstract class PersistentClass implements IdentifiableTypeClass, Attribut
return null; return null;
} }
public Constructor<? extends Expectation> getInsertExpectation() { public Supplier<? extends Expectation> getInsertExpectation() {
return insertExpectation; return insertExpectation;
} }
public void setInsertExpectation(Constructor<? extends Expectation> insertExpectation) { public void setInsertExpectation(Supplier<? extends Expectation> insertExpectation) {
this.insertExpectation = insertExpectation; this.insertExpectation = insertExpectation;
} }
public Constructor<? extends Expectation> getUpdateExpectation() { public Supplier<? extends Expectation> getUpdateExpectation() {
return updateExpectation; return updateExpectation;
} }
public void setUpdateExpectation(Constructor<? extends Expectation> updateExpectation) { public void setUpdateExpectation(Supplier<? extends Expectation> updateExpectation) {
this.updateExpectation = updateExpectation; this.updateExpectation = updateExpectation;
} }
public Constructor<? extends Expectation> getDeleteExpectation() { public Supplier<? extends Expectation> getDeleteExpectation() {
return deleteExpectation; return deleteExpectation;
} }
public void setDeleteExpectation(Constructor<? extends Expectation> deleteExpectation) { public void setDeleteExpectation(Supplier<? extends Expectation> deleteExpectation) {
this.deleteExpectation = deleteExpectation; this.deleteExpectation = deleteExpectation;
} }
} }

View File

@ -20,14 +20,9 @@ public @interface NoResultCheck {
class Binder implements TypeBinder<NoResultCheck> { class Binder implements TypeBinder<NoResultCheck> {
@Override @Override
public void bind(NoResultCheck annotation, MetadataBuildingContext buildingContext, PersistentClass persistentClass) { public void bind(NoResultCheck annotation, MetadataBuildingContext buildingContext, PersistentClass persistentClass) {
try { persistentClass.setInsertExpectation(Expectation.None::new);
persistentClass.setInsertExpectation(Expectation.None.class.getDeclaredConstructor()); persistentClass.setUpdateExpectation(Expectation.None::new);
persistentClass.setUpdateExpectation(Expectation.None.class.getDeclaredConstructor()); persistentClass.setDeleteExpectation(Expectation.None::new);
persistentClass.setDeleteExpectation(Expectation.None.class.getDeclaredConstructor());
}
catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
} }
@Override @Override