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
+ *
+ *
+ * - The first constructor is chosen (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 invoking that constructor, values are converted onto constructor
+ * argument types
+ *
+ *
*
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);
}