diff --git a/infobip-spring-data-common/pom.xml b/infobip-spring-data-common/pom.xml
index 5f6d5126..4d7f0b72 100644
--- a/infobip-spring-data-common/pom.xml
+++ b/infobip-spring-data-common/pom.xml
@@ -33,5 +33,15 @@
org.springframework.data
spring-data-relational
+
+ org.jetbrains.kotlin
+ kotlin-reflect
+ true
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
diff --git a/infobip-spring-data-common/src/main/java/com/infobip/spring/data/common/PreferredConstructorDiscoverer.java b/infobip-spring-data-common/src/main/java/com/infobip/spring/data/common/PreferredConstructorDiscoverer.java
new file mode 100644
index 00000000..91016052
--- /dev/null
+++ b/infobip-spring-data-common/src/main/java/com/infobip/spring/data/common/PreferredConstructorDiscoverer.java
@@ -0,0 +1,118 @@
+package com.infobip.spring.data.common;
+
+import kotlin.jvm.JvmClassMappingKt;
+import kotlin.reflect.KFunction;
+import kotlin.reflect.full.KClasses;
+import kotlin.reflect.jvm.ReflectJvmMapping;
+import org.springframework.core.DefaultParameterNameDiscoverer;
+import org.springframework.core.ParameterNameDiscoverer;
+import org.springframework.data.annotation.PersistenceConstructor;
+import org.springframework.data.mapping.PersistentEntity;
+import org.springframework.data.mapping.PersistentProperty;
+import org.springframework.data.mapping.PreferredConstructor;
+import org.springframework.data.util.ClassTypeInformation;
+import org.springframework.data.util.KotlinReflectionUtils;
+import org.springframework.data.util.TypeInformation;
+import org.springframework.lang.Nullable;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.util.*;
+
+/**
+ * Utility class to find the preferred constructor which is compatible with both Spring Data JDBC and QueryDSL.
+ */
+interface PreferredConstructorDiscoverer {
+
+ @Nullable
+ static > PreferredConstructor discover(Class type) {
+ return Discoverers.findDiscoverer(type)
+ .discover(ClassTypeInformation.from(type), null);
+ }
+
+ enum Discoverers {
+
+ DEFAULT {
+
+ @Nullable
+ @Override
+ > PreferredConstructor discover(
+ TypeInformation type, @Nullable PersistentEntity entity) {
+
+ return Arrays.stream(type.getType().getDeclaredConstructors())
+ .filter(it -> !it.isSynthetic())
+ .filter(it -> it.isAnnotationPresent(PersistenceConstructor.class))
+ .map(it -> buildPreferredConstructor(it, type, entity))
+ .findFirst()
+ .orElseGet(() -> Arrays.stream(type.getType().getDeclaredConstructors())
+ .filter(it -> !it.isSynthetic())
+ .max(Comparator.comparingInt(Constructor::getParameterCount))
+ .map(it -> buildPreferredConstructor(it, type, entity))
+ .orElse(null));
+ }
+ },
+
+ KOTLIN {
+
+ @Nullable
+ @Override
+ > PreferredConstructor discover(
+ TypeInformation type, @Nullable PersistentEntity entity) {
+
+ return Arrays.stream(type.getType().getDeclaredConstructors())
+ .filter(it -> !it.isSynthetic())
+ .filter(it -> it.isAnnotationPresent(PersistenceConstructor.class))
+ .map(it -> buildPreferredConstructor(it, type, entity))
+ .findFirst()
+ .orElseGet(() -> {
+ KFunction primaryConstructor = KClasses
+ .getPrimaryConstructor(JvmClassMappingKt.getKotlinClass(type.getType()));
+
+ if (primaryConstructor == null) {
+ return DEFAULT.discover(type, entity);
+ }
+
+ Constructor javaConstructor = ReflectJvmMapping.getJavaConstructor(primaryConstructor);
+
+ return javaConstructor != null ? buildPreferredConstructor(javaConstructor, type, entity) : null;
+ });
+ }
+ };
+
+ private static final ParameterNameDiscoverer PARAMETER_NAME_DISCOVERER = new DefaultParameterNameDiscoverer();
+
+ private static Discoverers findDiscoverer(Class> type) {
+ return KotlinReflectionUtils.isSupportedKotlinClass(type) ? KOTLIN : DEFAULT;
+ }
+
+ @Nullable
+ abstract > PreferredConstructor discover(TypeInformation type,
+ @Nullable PersistentEntity entity);
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ private static > PreferredConstructor buildPreferredConstructor(
+ Constructor> constructor, TypeInformation typeInformation, @Nullable PersistentEntity entity) {
+
+ if (constructor.getParameterCount() == 0) {
+ return new PreferredConstructor<>((Constructor) constructor);
+ }
+
+ List> parameterTypes = typeInformation.getParameterTypes(constructor);
+ String[] parameterNames = PARAMETER_NAME_DISCOVERER.getParameterNames(constructor);
+
+ PreferredConstructor.Parameter