[jOOQ/jOOQ#6598] Fixed also @ConstructorProperties mapping
This commit is contained in:
parent
622b07b1e0
commit
8fba879f62
@ -39,10 +39,8 @@ package org.jooq.impl;
|
||||
|
||||
import static java.lang.Boolean.FALSE;
|
||||
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;
|
||||
import static org.jooq.impl.Tools.EMPTY_FIELD;
|
||||
import static org.jooq.impl.Tools.getAnnotatedGetter;
|
||||
import static org.jooq.impl.Tools.getAnnotatedMembers;
|
||||
import static org.jooq.impl.Tools.getAnnotatedSetters;
|
||||
@ -386,7 +384,7 @@ public class DefaultRecordMapper<R extends Record, E> implements RecordMapper<R,
|
||||
ConstructorProperties properties = constructor.getAnnotation(ConstructorProperties.class);
|
||||
|
||||
if (properties != null) {
|
||||
delegate = new ImmutablePOJOMapperWithParameterNames(constructor, Arrays.asList(properties.value()));
|
||||
delegate = new ImmutablePOJOMapperWithParameterNames(constructor, Arrays.asList(properties.value()), true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -435,7 +433,7 @@ public class DefaultRecordMapper<R extends Record, E> implements RecordMapper<R,
|
||||
}
|
||||
|
||||
Constructor<E> javaConstructor = (Constructor<E>) this.type.getConstructor(parameterTypes);
|
||||
delegate = new ImmutablePOJOMapperWithParameterNames(javaConstructor, parameterNames);
|
||||
delegate = new ImmutablePOJOMapperWithParameterNames(javaConstructor, parameterNames, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -466,7 +464,7 @@ public class DefaultRecordMapper<R extends Record, E> implements RecordMapper<R,
|
||||
Parameter[] parameters = constructor.getParameters();
|
||||
|
||||
if (parameters != null && parameters.length > 0)
|
||||
delegate = new ImmutablePOJOMapperWithParameterNames(constructor, collectParameterNames(parameters));
|
||||
delegate = new ImmutablePOJOMapperWithParameterNames(constructor, collectParameterNames(parameters), supportsNesting);
|
||||
}
|
||||
|
||||
|
||||
@ -487,7 +485,7 @@ public class DefaultRecordMapper<R extends Record, E> implements RecordMapper<R,
|
||||
Parameter[] parameters = constructor.getParameters();
|
||||
|
||||
if (parameters != null && parameters.length > 0) {
|
||||
delegate = new ImmutablePOJOMapperWithParameterNames(constructor, collectParameterNames(parameters));
|
||||
delegate = new ImmutablePOJOMapperWithParameterNames(constructor, collectParameterNames(parameters), true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -684,22 +682,22 @@ public class DefaultRecordMapper<R extends Record, E> implements RecordMapper<R,
|
||||
*/
|
||||
private class MutablePOJOMapper implements RecordMapper<R, E> {
|
||||
|
||||
private final Callable<E> constructor;
|
||||
private final boolean useAnnotations;
|
||||
private final List<java.lang.reflect.Field>[] members;
|
||||
private final List<java.lang.reflect.Method>[] methods;
|
||||
private final Map<String, List<RecordMapper<R, Object>>> nested;
|
||||
private final E instance;
|
||||
private final Callable<E> constructor;
|
||||
private final boolean useAnnotations;
|
||||
private final List<java.lang.reflect.Field>[] members;
|
||||
private final List<java.lang.reflect.Method>[] methods;
|
||||
private Map<String, List<RecordMapper<Record, Object>>> nestedMappers;
|
||||
private Map<String, List<Field<?>>> nestedMappedFields;
|
||||
private Map<String, List<Integer>> nestedIndexLookup;
|
||||
private final E instance;
|
||||
|
||||
MutablePOJOMapper(Callable<E> constructor, E instance) {
|
||||
this.constructor = constructor;
|
||||
this.useAnnotations = hasColumnAnnotations(configuration, type);
|
||||
this.members = new List[fields.length];
|
||||
this.methods = new List[fields.length];
|
||||
this.nested = new HashMap<>();
|
||||
this.instance = instance;
|
||||
|
||||
Map<String, Field<?>[]> nestedFields = new HashMap<>();
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
Field<?> field = fields[i];
|
||||
String name = field.getName();
|
||||
@ -718,13 +716,22 @@ public class DefaultRecordMapper<R extends Record, E> implements RecordMapper<R,
|
||||
if (dot > -1) {
|
||||
String prefix = name.substring(0, dot);
|
||||
|
||||
Field<?>[] f = nestedFields.get(prefix);
|
||||
if (f == null) {
|
||||
f = nCopies(fields.length, field("")).toArray(EMPTY_FIELD);
|
||||
nestedFields.put(prefix, f);
|
||||
if (nestedMappedFields == null) {
|
||||
this.nestedMappers = new HashMap<>();
|
||||
this.nestedMappedFields = new HashMap<>();
|
||||
this.nestedIndexLookup = new HashMap<>();
|
||||
}
|
||||
|
||||
f[i] = field(name(name.substring(prefix.length() + 1)), field.getDataType());
|
||||
List<Field<?>> f = nestedMappedFields.get(prefix);
|
||||
if (f == null)
|
||||
nestedMappedFields.put(prefix, f = new ArrayList<>());
|
||||
|
||||
List<Integer> indexes = nestedIndexLookup.get(prefix);
|
||||
if (indexes == null)
|
||||
nestedIndexLookup.put(prefix, indexes = new ArrayList<>());
|
||||
|
||||
f.add(field(name(name.substring(prefix.length() + 1)), field.getDataType()));
|
||||
indexes.add(i);
|
||||
|
||||
members[i] = Collections.emptyList();
|
||||
methods[i] = Collections.emptyList();
|
||||
@ -738,25 +745,27 @@ public class DefaultRecordMapper<R extends Record, E> implements RecordMapper<R,
|
||||
}
|
||||
}
|
||||
|
||||
for (Entry<String, Field<?>[]> entry : nestedFields.entrySet()) {
|
||||
String prefix = entry.getKey();
|
||||
List<RecordMapper<R, Object>> list = new ArrayList<>();
|
||||
if (nestedMappedFields != null) {
|
||||
for (Entry<String, List<Field<?>>> entry : nestedMappedFields.entrySet()) {
|
||||
String prefix = entry.getKey();
|
||||
List<RecordMapper<Record, Object>> list = new ArrayList<>();
|
||||
|
||||
for (java.lang.reflect.Field member : getMatchingMembers(configuration, type, prefix)) {
|
||||
list.add(configuration
|
||||
.recordMapperProvider()
|
||||
.provide(new Fields<>(entry.getValue()), member.getType())
|
||||
);
|
||||
for (java.lang.reflect.Field member : getMatchingMembers(configuration, type, prefix)) {
|
||||
list.add(configuration
|
||||
.recordMapperProvider()
|
||||
.provide(new Fields<>(entry.getValue()), member.getType())
|
||||
);
|
||||
}
|
||||
|
||||
for (Method method : getMatchingSetters(configuration, type, prefix)) {
|
||||
list.add(configuration
|
||||
.recordMapperProvider()
|
||||
.provide(new Fields<>(entry.getValue()), method.getParameterTypes()[0])
|
||||
);
|
||||
}
|
||||
|
||||
nestedMappers.put(prefix, list);
|
||||
}
|
||||
|
||||
for (Method method : getMatchingSetters(configuration, type, prefix)) {
|
||||
list.add(configuration
|
||||
.recordMapperProvider()
|
||||
.provide(new Fields<>(entry.getValue()), method.getParameterTypes()[0])
|
||||
);
|
||||
}
|
||||
|
||||
nested.put(prefix, list);
|
||||
}
|
||||
}
|
||||
|
||||
@ -790,21 +799,29 @@ public class DefaultRecordMapper<R extends Record, E> implements RecordMapper<R,
|
||||
}
|
||||
}
|
||||
|
||||
for (Entry<String, List<RecordMapper<R, Object>>> entry : nested.entrySet()) {
|
||||
String prefix = entry.getKey();
|
||||
if (nestedMappers != null) {
|
||||
for (Entry<String, List<RecordMapper<Record, Object>>> entry : nestedMappers.entrySet()) {
|
||||
String prefix = entry.getKey();
|
||||
|
||||
for (RecordMapper<R, Object> mapper : entry.getValue()) {
|
||||
Object value = mapper.map(record);
|
||||
for (RecordMapper<Record, Object> mapper : entry.getValue()) {
|
||||
RecordImplN rec = new RecordImplN(nestedMappedFields.get(prefix));
|
||||
|
||||
for (java.lang.reflect.Field member : getMatchingMembers(configuration, type, prefix)) {
|
||||
List<Integer> indexes = nestedIndexLookup.get(prefix);
|
||||
for (int index = 0; index < indexes.size(); index++)
|
||||
rec.set(index, record.get(indexes.get(index)));
|
||||
|
||||
// [#935] Avoid setting final fields
|
||||
if ((member.getModifiers() & Modifier.FINAL) == 0)
|
||||
map(value, result, member);
|
||||
Object value = mapper.map(rec);
|
||||
|
||||
for (java.lang.reflect.Field member : getMatchingMembers(configuration, type, prefix)) {
|
||||
|
||||
// [#935] Avoid setting final fields
|
||||
if ((member.getModifiers() & Modifier.FINAL) == 0)
|
||||
map(value, result, member);
|
||||
}
|
||||
|
||||
for (Method method : getMatchingSetters(configuration, type, prefix))
|
||||
method.invoke(result, value);
|
||||
}
|
||||
|
||||
for (Method method : getMatchingSetters(configuration, type, prefix))
|
||||
method.invoke(result, value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -887,15 +904,15 @@ public class DefaultRecordMapper<R extends Record, E> implements RecordMapper<R,
|
||||
*/
|
||||
private class ImmutablePOJOMapper implements RecordMapper<R, E> {
|
||||
|
||||
private final Constructor<E> constructor;
|
||||
private final Class<?>[] parameterTypes;
|
||||
private final Constructor<E> constructor;
|
||||
private final Class<?>[] parameterTypes;
|
||||
private final boolean nested;
|
||||
private final int[] nonNestedIndexLookup;
|
||||
private final List<Integer>[] nestedIndexLookup;
|
||||
private final List<Field<?>>[] nestedMappedFields;
|
||||
private final RecordMapper<Record, Object>[] nestedMappers;
|
||||
|
||||
public ImmutablePOJOMapper(Constructor<E> constructor, Class<?>[] parameterTypes, boolean supportsNesting) {
|
||||
ImmutablePOJOMapper(Constructor<E> constructor, Class<?>[] parameterTypes, boolean supportsNesting) {
|
||||
this.constructor = accessible(constructor);
|
||||
this.parameterTypes = parameterTypes;
|
||||
this.nestedMappedFields = new List[prefixes().size()];
|
||||
@ -948,16 +965,22 @@ public class DefaultRecordMapper<R extends Record, E> implements RecordMapper<R,
|
||||
@Override
|
||||
public final E map(R record) {
|
||||
try {
|
||||
return constructor.newInstance(nested
|
||||
? mapNested(record)
|
||||
: Convert.convert(record.intoArray(), parameterTypes)
|
||||
);
|
||||
return constructor.newInstance(nested ? mapNested(record) : mapNonnested(record));
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new MappingException("An error ocurred when mapping record to " + type, e);
|
||||
}
|
||||
}
|
||||
|
||||
private final Object[] mapNonnested(R record) {
|
||||
Object[] converted = new Object[parameterTypes.length];
|
||||
|
||||
for (int i = 0; i < converted.length; i++)
|
||||
set(converted, i, record.get(i, parameterTypes[i]));
|
||||
|
||||
return converted;
|
||||
}
|
||||
|
||||
private final Object[] mapNested(R record) {
|
||||
Object[] converted = new Object[prefixes().size()];
|
||||
|
||||
@ -977,27 +1000,29 @@ public class DefaultRecordMapper<R extends Record, E> implements RecordMapper<R,
|
||||
|
||||
return converted;
|
||||
}
|
||||
|
||||
void set(Object[] array, int i, Object value) {
|
||||
array[i] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an immutable POJO given a constructor and its associated JavaBeans
|
||||
* {@link ConstructorProperties}
|
||||
*/
|
||||
private class ImmutablePOJOMapperWithParameterNames implements RecordMapper<R, E> {
|
||||
private class ImmutablePOJOMapperWithParameterNames extends ImmutablePOJOMapper {
|
||||
|
||||
private final Constructor<E> constructor;
|
||||
private final Class<?>[] parameterTypes;
|
||||
private final List<String> propertyNames;
|
||||
private final boolean useAnnotations;
|
||||
private final List<java.lang.reflect.Field>[] members;
|
||||
private final java.lang.reflect.Method[] methods;
|
||||
private final Integer[] propertyIndexes;
|
||||
|
||||
ImmutablePOJOMapperWithParameterNames(Constructor<E> constructor, List<String> propertyNames) {
|
||||
this.constructor = constructor;
|
||||
ImmutablePOJOMapperWithParameterNames(Constructor<E> constructor, List<String> propertyNames, boolean supportsNesting) {
|
||||
super(constructor, constructor.getParameterTypes(), supportsNesting);
|
||||
|
||||
this.propertyNames = propertyNames;
|
||||
this.useAnnotations = hasColumnAnnotations(configuration, type);
|
||||
this.parameterTypes = constructor.getParameterTypes();
|
||||
this.members = new List[fields.length];
|
||||
this.methods = new Method[fields.length];
|
||||
this.propertyIndexes = new Integer[fields.length];
|
||||
@ -1032,37 +1057,25 @@ public class DefaultRecordMapper<R extends Record, E> implements RecordMapper<R,
|
||||
}
|
||||
|
||||
@Override
|
||||
public final E map(R record) {
|
||||
try {
|
||||
Object[] parameterValues = new Object[parameterTypes.length];
|
||||
void set(Object[] array, int i, Object value) {
|
||||
if (propertyIndexes[i] != null) {
|
||||
array[propertyIndexes[i]] = value;
|
||||
}
|
||||
else {
|
||||
for (java.lang.reflect.Field member : members[i]) {
|
||||
int index = propertyNames.indexOf(member.getName());
|
||||
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
if (propertyIndexes[i] != null) {
|
||||
parameterValues[propertyIndexes[i]] = record.get(i);
|
||||
}
|
||||
else {
|
||||
for (java.lang.reflect.Field member : members[i]) {
|
||||
int index = propertyNames.indexOf(member.getName());
|
||||
|
||||
if (index >= 0)
|
||||
parameterValues[index] = record.get(i);
|
||||
}
|
||||
|
||||
if (methods[i] != null) {
|
||||
String name = getPropertyName(methods[i].getName());
|
||||
int index = propertyNames.indexOf(name);
|
||||
|
||||
if (index >= 0)
|
||||
parameterValues[index] = record.get(i);
|
||||
}
|
||||
}
|
||||
if (index >= 0)
|
||||
array[index] = value;
|
||||
}
|
||||
|
||||
Object[] converted = Convert.convert(parameterValues, parameterTypes);
|
||||
return accessible(constructor).newInstance(converted);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new MappingException("An error ocurred when mapping record to " + type, e);
|
||||
if (methods[i] != null) {
|
||||
String name = getPropertyName(methods[i].getName());
|
||||
int index = propertyNames.indexOf(name);
|
||||
|
||||
if (index >= 0)
|
||||
array[index] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user