diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultRecordMapper.java b/jOOQ/src/main/java/org/jooq/impl/DefaultRecordMapper.java index 13d575715b..649899d577 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultRecordMapper.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultRecordMapper.java @@ -34,6 +34,7 @@ */ package org.jooq.impl; +import static java.lang.Boolean.TRUE; import static java.util.Collections.nCopies; import static org.jooq.impl.DSL.field; import static org.jooq.impl.DSL.name; @@ -52,6 +53,7 @@ import java.beans.ConstructorProperties; import java.lang.invoke.MethodHandles.Lookup; import java.lang.reflect.Array; import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -63,7 +65,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -82,6 +83,7 @@ import org.jooq.Record1; import org.jooq.RecordMapper; import org.jooq.RecordMapperProvider; import org.jooq.RecordType; +import org.jooq.conf.Settings; import org.jooq.exception.MappingException; import org.jooq.tools.Convert; import org.jooq.tools.StringUtils; @@ -199,11 +201,31 @@ import org.jooq.tools.reflect.Reflect; *
  • A "matching" constructor is one with exactly as many arguments as this * record holds fields
  • *
  • When several "matching" constructors are found, the first one is chosen - * (as reported by {@link Class#getDeclaredConstructors()}
  • + * (as reported by {@link Class#getDeclaredConstructors()}). This choice is + * non-deterministic as neither the JVM nor the JDK guarantee any order of + * methods or constructors. + *
  • When {@link Settings#isMapConstructorParameterNames()} is turned on, and + * parameter names are available through reflection on + * {@link Executable#getParameters()}, then values are mapped by name, otherwise + * by index. (see #4627)
  • *
  • When invoking the "matching" constructor, values are converted onto * constructor argument types
  • * *

    + *

    If no default constructor is available, no "matching" constructor is + * available, but {@link Settings#isMapConstructorParameterNames()} is turned + * on, and parameter names are available through reflection on + * {@link Executable#getParameters()}, the first constructor is used
    + *

    + *

    + *

    *

    If the supplied type is an interface or an abstract class
    *

    * Abstract types are instantiated using Java reflection {@link Proxy} @@ -340,8 +362,9 @@ public class DefaultRecordMapper implements RecordMapper implements RecordMapper 0) - delegate = new ImmutablePOJOMapperWithParameterNames(constructor, - collectParameterNames(parameters)); + delegate = new ImmutablePOJOMapperWithParameterNames(constructor, collectParameterNames(parameters)); } @@ -369,18 +391,21 @@ public class DefaultRecordMapper implements RecordMapper constructor = constructors[0]; Parameter[] parameters = constructor.getParameters(); + if (parameters != null && parameters.length > 0) { delegate = new ImmutablePOJOMapperWithParameterNames(constructor, collectParameterNames(parameters)); return; } } + throw new MappingException("No matching constructor found on type " + type + " for row type " + rowType); }