diff --git a/core/src/main/java/org/jdbi/v3/core/mapper/reflect/ConstructorInstanceFactory.java b/core/src/main/java/org/jdbi/v3/core/mapper/reflect/ConstructorInstanceFactory.java index 06c8c3411..32b06fcfb 100644 --- a/core/src/main/java/org/jdbi/v3/core/mapper/reflect/ConstructorInstanceFactory.java +++ b/core/src/main/java/org/jdbi/v3/core/mapper/reflect/ConstructorInstanceFactory.java @@ -26,20 +26,19 @@ import static java.util.Objects.requireNonNull; +import static org.jdbi.v3.core.mapper.reflect.ConstructorMapper.CONSTRUCTOR_CACHE; + class ConstructorInstanceFactory extends InstanceFactory { private final Constructor constructor; - private final Supplier typeSupplier; - ConstructorInstanceFactory(Constructor constructor) { super(constructor); this.constructor = requireNonNull(constructor, "constructor is null"); - this.typeSupplier = getTypeSupplier(constructor, super::getTypes); } @Override Type[] getTypes() { - return typeSupplier.get(); + return getTypes(constructor, super::getTypes); } @Override @@ -76,13 +75,17 @@ private static boolean isGenericInformationLost(Constructor factory) { return lossDetected; } - private static Supplier getTypeSupplier(Constructor constructor, Supplier defaultSupplier) { + private static Type[] getTypes(Constructor constructor, Supplier defaultSupplier) { + return CONSTRUCTOR_CACHE.computeIfAbsent(constructor, ctor -> getTypeSupplier(ctor, defaultSupplier)); + } + + private static Type[] getTypeSupplier(Constructor constructor, Supplier defaultSupplier) { if (isGenericInformationLost(constructor)) { - return () -> getFields(constructor) + return getFields(constructor) .map(Field::getGenericType) .toArray(Type[]::new); } - return defaultSupplier; + return defaultSupplier.get(); } private static Stream getFields(Constructor constructor) { diff --git a/core/src/main/java/org/jdbi/v3/core/mapper/reflect/ConstructorMapper.java b/core/src/main/java/org/jdbi/v3/core/mapper/reflect/ConstructorMapper.java index 07c6b5e70..ca8e95e2e 100644 --- a/core/src/main/java/org/jdbi/v3/core/mapper/reflect/ConstructorMapper.java +++ b/core/src/main/java/org/jdbi/v3/core/mapper/reflect/ConstructorMapper.java @@ -75,6 +75,9 @@ public final class ConstructorMapper implements RowMapper { + "that your result set has the columns expected, annotate the " + "parameter names explicitly with @ColumnName, or annotate nullable parameters as @Nullable"; + + static final Map CONSTRUCTOR_CACHE = new ConcurrentHashMap<>(); + /** * Use the only declared constructor to map a class. *