diff --git a/jOOQ/pom.xml b/jOOQ/pom.xml
index 3567eaded4..41ce6fae9c 100644
--- a/jOOQ/pom.xml
+++ b/jOOQ/pom.xml
@@ -101,6 +101,11 @@
provided
true
+
+ org.jetbrains.kotlin
+ kotlin-reflect
+ 1.2.30
+
diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultRecordMapper.java b/jOOQ/src/main/java/org/jooq/impl/DefaultRecordMapper.java
index fac803a103..8dd34d9cbf 100644
--- a/jOOQ/src/main/java/org/jooq/impl/DefaultRecordMapper.java
+++ b/jOOQ/src/main/java/org/jooq/impl/DefaultRecordMapper.java
@@ -50,6 +50,7 @@ import static org.jooq.impl.Tools.getMatchingMembers;
import static org.jooq.impl.Tools.getMatchingSetters;
import static org.jooq.impl.Tools.getPropertyName;
import static org.jooq.impl.Tools.hasColumnAnnotations;
+import static org.jooq.impl.Tools.fieldNameStrings;
import static org.jooq.tools.reflect.Reflect.accessible;
import java.beans.ConstructorProperties;
@@ -79,6 +80,11 @@ import java.util.stream.Stream;
import javax.persistence.Column;
+import kotlin.jvm.JvmClassMappingKt;
+import kotlin.reflect.KClass;
+import kotlin.reflect.KFunction;
+import kotlin.reflect.KParameter;
+import kotlin.reflect.full.KClasses;
import org.jooq.Attachable;
import org.jooq.Configuration;
import org.jooq.Field;
@@ -343,6 +349,33 @@ public class DefaultRecordMapper implements RecordMapper kotlinClass = JvmClassMappingKt.getKotlinClass(type);
+ if (kotlinClass.isData()) {
+ KFunction extends E> primaryConstructor = KClasses.getPrimaryConstructor(kotlinClass);
+ List parameters = primaryConstructor.getParameters();
+
+ if (parameters.size() != fields.length) {
+ throw new MappingException("Primary constructor of Kotlin data class " + type + " did not match row type " + rowType);
+ }
+
+ for (String fieldName : fieldNameStrings(fields)) {
+ String name = StringUtils.toCamelCaseLC(fieldName);
+ boolean found = false;
+ for (KParameter kParameter : parameters) {
+ String parameterName = kParameter.getName();
+ if (name.equals(parameterName)) {
+ found = true;
+ }
+ }
+ if (!found) {
+ throw new MappingException("Primary constructor of Kotlin data class " + type + " did not match row type " + rowType);
+ }
+ }
+ delegate = new KotlinDataClassMapper(primaryConstructor);
+ return;
+ }
+
// [#1340] Allow for using non-public default constructors
try {
delegate = new MutablePOJOMapper(new ConstructorCall(accessible(type.getDeclaredConstructor())), instance);
@@ -981,6 +1014,44 @@ public class DefaultRecordMapper implements RecordMapper {
+
+ private final KFunction extends E> constructor;
+ private final List parameterNames;
+ private final Class[] parameterTypes;
+ private final Object[] parameterValues;
+
+ KotlinDataClassMapper(KFunction extends E> constructor) {
+ this.constructor = constructor;
+ int n = constructor.getParameters().size();
+ this.parameterNames = new ArrayList<>(n);
+ this.parameterValues = new Object[n];
+ this.parameterTypes = new Class[n];
+
+ List parameters = constructor.getParameters();
+ for (int i = 0; i < parameters.size(); i++) {
+ KParameter kParam = parameters.get(i);
+ parameterNames.add(kParam.getName());
+ parameterTypes[i] = JvmClassMappingKt.getJavaClass(((KClass>) kParam.getType().getClassifier()));
+ }
+ }
+
+ @Override
+ public E map(R record) {
+ for (int i = 0; i < fields.length; i++) {
+ String name = StringUtils.toCamelCaseLC(fields[i].getName());
+ int index = parameterNames.indexOf(name);
+ if (index < 0) {
+ throw new MappingException("An error ocurred when mapping record to " + type);
+ }
+ parameterValues[index] = record.get(i);
+ }
+
+ Object[] converted = Convert.convert(parameterValues, parameterTypes);
+ return constructor.call(converted);
+ }
+ }
+
private static E attach(E attachable, Record record) {
// [#2869] Attach the mapped outcome if it is Attachable and if the context's
// Settings.attachRecords flag is set
diff --git a/jOOQ/src/main/resources/META-INF/ABOUT.txt b/jOOQ/src/main/resources/META-INF/ABOUT.txt
index d0eb994a84..a65a2c4a4c 100644
--- a/jOOQ/src/main/resources/META-INF/ABOUT.txt
+++ b/jOOQ/src/main/resources/META-INF/ABOUT.txt
@@ -55,6 +55,7 @@ Authors and contributors of jOOQ or parts of jOOQ in alphabetical order:
- Victor Z. Peng
- Vladimir Kulev
- Vladimir Vinogradov
+- Vojtech Polivka
- Wang Gaoyuan
- Zoltan Tamasi