Search in sources :

Example 1 with PropagateNull

use of org.jdbi.v3.core.mapper.PropagateNull in project jdbi by jdbi.

the class BeanMapperTest method propagateNull.

@Test
public void propagateNull() {
    Handle handle = h2Extension.getSharedHandle();
    assertThat(handle.registerRowMapper(BeanMapper.factory(PropagateNullThing.class)).select("SELECT null as testValue, 'foo' as s").mapTo(PropagateNullThing.class).one()).isNull();
}
Also used : ClassPropagateNullThing(org.jdbi.v3.core.mapper.reflect.ConstructorMapperTest.ClassPropagateNullThing) Handle(org.jdbi.v3.core.Handle) Test(org.junit.jupiter.api.Test)

Example 2 with PropagateNull

use of org.jdbi.v3.core.mapper.PropagateNull in project jdbi by jdbi.

the class PojoMapper method specialize0.

private Optional<RowMapper<T>> specialize0(StatementContext ctx, List<String> columnNames, List<ColumnNameMatcher> columnNameMatchers, List<String> unmatchedColumns) {
    final List<PropertyData<T>> propList = new ArrayList<>();
    for (PojoProperty<T> property : getProperties(ctx.getConfig()).getProperties().values()) {
        Nested anno = property.getAnnotation(Nested.class).orElse(null);
        if (property.getAnnotation(Unmappable.class).map(Unmappable::value).orElse(false)) {
            continue;
        }
        if (anno == null) {
            String paramName = prefix + getName(property);
            findColumnIndex(paramName, columnNames, columnNameMatchers, () -> debugName(property)).ifPresent(index -> {
                @SuppressWarnings({ "unchecked", "rawtypes" }) ColumnMapper<?> mapper = ctx.findColumnMapperFor(property.getQualifiedType().mapType(GenericTypes::box)).orElseGet(() -> (ColumnMapper) defaultColumnMapper(property));
                propList.add(new PropertyData<>(property, new SingleColumnMapper<>(mapper, index + 1)));
                unmatchedColumns.remove(columnNames.get(index));
            });
        } else {
            String nestedPrefix = prefix + anno.value();
            if (anyColumnsStartWithPrefix(columnNames, nestedPrefix, columnNameMatchers)) {
                nestedMappers.computeIfAbsent(property, d -> createNestedMapper(ctx, d, nestedPrefix)).specialize0(ctx, columnNames, columnNameMatchers, unmatchedColumns).ifPresent(nestedMapper -> propList.add(new PropertyData<>(property, nestedMapper)));
            }
        }
    }
    if (propList.isEmpty() && !columnNames.isEmpty()) {
        return Optional.empty();
    }
    propList.sort(Comparator.comparing(p -> p.propagateNull ? 1 : 0));
    final Optional<String> nullMarkerColumn = Optional.ofNullable(GenericTypes.getErasedType(type).getAnnotation(PropagateNull.class)).map(PropagateNull::value);
    return Optional.of((r, c) -> {
        if (propagateNull(r, nullMarkerColumn)) {
            return null;
        }
        final PojoBuilder<T> pojo = getProperties(c.getConfig()).create();
        for (PropertyData<T> p : propList) {
            Object value = p.mapper.map(r, ctx);
            if (p.propagateNull && (value == null || (p.isPrimitive && r.wasNull()))) {
                return null;
            }
            if (value != null) {
                pojo.set(p.property, value);
            }
        }
        return pojo.build();
    });
}
Also used : PojoProperty(org.jdbi.v3.core.mapper.reflect.internal.PojoProperties.PojoProperty) PropagateNull(org.jdbi.v3.core.mapper.PropagateNull) ReflectionMappers(org.jdbi.v3.core.mapper.reflect.ReflectionMappers) Nested(org.jdbi.v3.core.mapper.Nested) SingleColumnMapper(org.jdbi.v3.core.mapper.SingleColumnMapper) ConfigRegistry(org.jdbi.v3.core.config.ConfigRegistry) ArrayList(java.util.ArrayList) SQLException(java.sql.SQLException) ColumnName(org.jdbi.v3.core.mapper.reflect.ColumnName) UnableToProduceResultException(org.jdbi.v3.core.result.UnableToProduceResultException) ResultSet(java.sql.ResultSet) Map(java.util.Map) GenericTypes(org.jdbi.v3.core.generic.GenericTypes) RowMapper(org.jdbi.v3.core.mapper.RowMapper) ColumnNameMatcher(org.jdbi.v3.core.mapper.reflect.ColumnNameMatcher) ReflectionMapperUtil.getColumnNames(org.jdbi.v3.core.mapper.reflect.ReflectionMapperUtil.getColumnNames) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) StatementContext(org.jdbi.v3.core.statement.StatementContext) Unchecked(org.jdbi.v3.core.internal.exceptions.Unchecked) PojoBuilder(org.jdbi.v3.core.mapper.reflect.internal.PojoProperties.PojoBuilder) List(java.util.List) Type(java.lang.reflect.Type) ColumnMapper(org.jdbi.v3.core.mapper.ColumnMapper) ReflectionMapperUtil.findColumnIndex(org.jdbi.v3.core.mapper.reflect.ReflectionMapperUtil.findColumnIndex) Optional(java.util.Optional) NoSuchMapperException(org.jdbi.v3.core.mapper.NoSuchMapperException) ReflectionMapperUtil.anyColumnsStartWithPrefix(org.jdbi.v3.core.mapper.reflect.ReflectionMapperUtil.anyColumnsStartWithPrefix) Comparator(java.util.Comparator) Unmappable(org.jdbi.v3.core.annotation.Unmappable) SingleColumnMapper(org.jdbi.v3.core.mapper.SingleColumnMapper) ArrayList(java.util.ArrayList) Nested(org.jdbi.v3.core.mapper.Nested) GenericTypes(org.jdbi.v3.core.generic.GenericTypes) PropagateNull(org.jdbi.v3.core.mapper.PropagateNull)

Example 3 with PropagateNull

use of org.jdbi.v3.core.mapper.PropagateNull in project jdbi by jdbi.

the class FieldMapperTest method propagateNull.

@Test
public void propagateNull() {
    Handle handle = h2Extension.getSharedHandle();
    assertThat(handle.registerRowMapper(FieldMapper.factory(PropagateNullThing.class)).select("SELECT null as testValue, 'foo' as s").mapTo(PropagateNullThing.class).one()).isNull();
}
Also used : ClassPropagateNullThing(org.jdbi.v3.core.mapper.reflect.ConstructorMapperTest.ClassPropagateNullThing) Handle(org.jdbi.v3.core.Handle) Test(org.junit.jupiter.api.Test)

Example 4 with PropagateNull

use of org.jdbi.v3.core.mapper.PropagateNull in project jdbi by jdbi.

the class ConstructorMapper method specialize0.

private Optional<RowMapper<T>> specialize0(StatementContext ctx, List<String> columnNames, List<ColumnNameMatcher> columnNameMatchers, List<String> unmatchedColumns) {
    final int count = factory.getParameterCount();
    final Parameter[] parameters = factory.getParameters();
    boolean matchedColumns = false;
    final List<String> unmatchedParameters = new ArrayList<>();
    final List<ParameterData> paramData = new ArrayList<>();
    for (int i = 0; i < count; i++) {
        final Parameter parameter = parameters[i];
        boolean nullable = isNullable(parameter);
        Nested anno = parameter.getAnnotation(Nested.class);
        if (anno == null) {
            final String paramName = prefix + paramName(parameters, i, constructorProperties);
            final OptionalInt columnIndex = findColumnIndex(paramName, columnNames, columnNameMatchers, () -> debugName(parameter));
            if (columnIndex.isPresent()) {
                int colIndex = columnIndex.getAsInt();
                final QualifiedType<?> type = QualifiedType.of(parameter.getParameterizedType()).withAnnotations(ctx.getConfig(Qualifiers.class).findFor(parameter));
                paramData.add(new ParameterData(i, parameter, ctx.findColumnMapperFor(type).map(mapper -> new SingleColumnMapper<>(mapper, colIndex + 1)).orElseThrow(() -> new IllegalArgumentException(format("Could not find column mapper for type '%s' of parameter '%s' for instance factory '%s'", type, paramName, factory)))));
                matchedColumns = true;
                unmatchedColumns.remove(columnNames.get(colIndex));
            } else if (nullable) {
                paramData.add(new ParameterData(i, parameter, (r, c) -> null));
            } else {
                unmatchedParameters.add(paramName);
            }
        } else {
            final String nestedPrefix = prefix + anno.value();
            final Optional<? extends RowMapper<?>> nestedMapper = nestedMappers.computeIfAbsent(parameter, p -> new ConstructorMapper<>(findFactoryFor(p.getType()), nestedPrefix)).specialize0(ctx, columnNames, columnNameMatchers, unmatchedColumns);
            if (nestedMapper.isPresent()) {
                paramData.add(new ParameterData(i, parameter, nestedMapper.get()));
                matchedColumns = true;
            } else if (nullable) {
                paramData.add(new ParameterData(i, parameter, (r, c) -> null));
            } else {
                unmatchedParameters.add(paramName(parameters, i, constructorProperties));
            }
        }
    }
    if (!matchedColumns) {
        return Optional.empty();
    }
    paramData.sort(Comparator.comparing(p -> p.propagateNull ? 1 : 0));
    if (!unmatchedParameters.isEmpty()) {
        throw new IllegalArgumentException(format(UNMATCHED_CONSTRUCTOR_PARAMETER, factory, unmatchedParameters));
    }
    final Optional<String> nullMarkerColumn = Optional.ofNullable(factory.getAnnotationIncludingType(PropagateNull.class)).map(PropagateNull::value);
    return Optional.of((r, c) -> {
        if (PojoMapper.propagateNull(r, nullMarkerColumn)) {
            return null;
        }
        final Object[] params = new Object[count];
        for (ParameterData p : paramData) {
            params[p.index] = p.mapper.map(r, c);
            if (p.propagateNull && (params[p.index] == null || (p.isPrimitive && r.wasNull()))) {
                return null;
            }
        }
        return factory.newInstance(params);
    });
}
Also used : RowMapperFactory(org.jdbi.v3.core.mapper.RowMapperFactory) ConstructorProperties(java.beans.ConstructorProperties) PropagateNull(org.jdbi.v3.core.mapper.PropagateNull) PojoMapper(org.jdbi.v3.core.mapper.reflect.internal.PojoMapper) Nested(org.jdbi.v3.core.mapper.Nested) JdbiConstructors.findFactoryFor(org.jdbi.v3.core.mapper.reflect.JdbiConstructors.findFactoryFor) SingleColumnMapper(org.jdbi.v3.core.mapper.SingleColumnMapper) Constructor(java.lang.reflect.Constructor) OptionalInt(java.util.OptionalInt) ArrayList(java.util.ArrayList) SQLException(java.sql.SQLException) Parameter(java.lang.reflect.Parameter) ResultSet(java.sql.ResultSet) Map(java.util.Map) QualifiedType(org.jdbi.v3.core.qualifier.QualifiedType) RowMapper(org.jdbi.v3.core.mapper.RowMapper) ReflectionMapperUtil.getColumnNames(org.jdbi.v3.core.mapper.reflect.ReflectionMapperUtil.getColumnNames) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) String.format(java.lang.String.format) StatementContext(org.jdbi.v3.core.statement.StatementContext) List(java.util.List) Stream(java.util.stream.Stream) Annotation(java.lang.annotation.Annotation) ReflectionMapperUtil.findColumnIndex(org.jdbi.v3.core.mapper.reflect.ReflectionMapperUtil.findColumnIndex) Optional(java.util.Optional) Qualifiers(org.jdbi.v3.core.qualifier.Qualifiers) ReflectionMapperUtil.anyColumnsStartWithPrefix(org.jdbi.v3.core.mapper.reflect.ReflectionMapperUtil.anyColumnsStartWithPrefix) Comparator(java.util.Comparator) SingleColumnMapper(org.jdbi.v3.core.mapper.SingleColumnMapper) ArrayList(java.util.ArrayList) Nested(org.jdbi.v3.core.mapper.Nested) OptionalInt(java.util.OptionalInt) PropagateNull(org.jdbi.v3.core.mapper.PropagateNull) Parameter(java.lang.reflect.Parameter)

Example 5 with PropagateNull

use of org.jdbi.v3.core.mapper.PropagateNull in project jdbi by jdbi.

the class FieldMapper method specialize0.

private Optional<RowMapper<T>> specialize0(StatementContext ctx, List<String> columnNames, List<ColumnNameMatcher> columnNameMatchers, List<String> unmatchedColumns) {
    final List<FieldData> fields = new ArrayList<>();
    for (Class<?> aType = type; aType != null; aType = aType.getSuperclass()) {
        for (Field field : aType.getDeclaredFields()) {
            Nested anno = field.getAnnotation(Nested.class);
            if (anno == null) {
                String paramName = prefix + paramName(field);
                findColumnIndex(paramName, columnNames, columnNameMatchers, () -> debugName(field)).ifPresent(index -> {
                    QualifiedType<?> fieldType = QualifiedType.of(field.getGenericType()).withAnnotations(ctx.getConfig(Qualifiers.class).findFor(field));
                    @SuppressWarnings("unchecked") ColumnMapper<?> mapper = ctx.findColumnMapperFor(fieldType).orElse((ColumnMapper) (r, n, c) -> r.getObject(n));
                    fields.add(new FieldData(field, new SingleColumnMapper<>(mapper, index + 1)));
                    unmatchedColumns.remove(columnNames.get(index));
                });
            } else {
                String nestedPrefix = prefix + anno.value().toLowerCase();
                if (anyColumnsStartWithPrefix(columnNames, nestedPrefix, columnNameMatchers)) {
                    nestedMappers.computeIfAbsent(field, f -> new FieldMapper<>(field.getType(), nestedPrefix)).specialize0(ctx, columnNames, columnNameMatchers, unmatchedColumns).ifPresent(mapper -> fields.add(new FieldData(field, mapper)));
                }
            }
        }
    }
    if (fields.isEmpty() && !columnNames.isEmpty()) {
        return Optional.empty();
    }
    Collections.sort(fields, Comparator.comparing(f -> f.propagateNull ? 1 : 0));
    final Optional<String> nullMarkerColumn = Optional.ofNullable(type.getAnnotation(PropagateNull.class)).map(PropagateNull::value);
    return Optional.of((r, c) -> {
        if (PojoMapper.propagateNull(r, nullMarkerColumn)) {
            return null;
        }
        T obj = construct();
        for (FieldData f : fields) {
            Object value = f.mapper.map(r, ctx);
            if (f.propagateNull && (value == null || (f.isPrimitive && r.wasNull()))) {
                return null;
            }
            writeField(obj, f.field, value);
        }
        return obj;
    });
}
Also used : RowMapperFactory(org.jdbi.v3.core.mapper.RowMapperFactory) ReflectionMapperUtil.getColumnNames(org.jdbi.v3.core.mapper.reflect.ReflectionMapperUtil.getColumnNames) PropagateNull(org.jdbi.v3.core.mapper.PropagateNull) PojoMapper(org.jdbi.v3.core.mapper.reflect.internal.PojoMapper) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Nested(org.jdbi.v3.core.mapper.Nested) Field(java.lang.reflect.Field) SingleColumnMapper(org.jdbi.v3.core.mapper.SingleColumnMapper) String.format(java.lang.String.format) ArrayList(java.util.ArrayList) StatementContext(org.jdbi.v3.core.statement.StatementContext) SQLException(java.sql.SQLException) List(java.util.List) ResultSet(java.sql.ResultSet) Map(java.util.Map) ColumnMapper(org.jdbi.v3.core.mapper.ColumnMapper) ReflectionMapperUtil.findColumnIndex(org.jdbi.v3.core.mapper.reflect.ReflectionMapperUtil.findColumnIndex) Optional(java.util.Optional) Qualifiers(org.jdbi.v3.core.qualifier.Qualifiers) QualifiedType(org.jdbi.v3.core.qualifier.QualifiedType) ReflectionMapperUtil.anyColumnsStartWithPrefix(org.jdbi.v3.core.mapper.reflect.ReflectionMapperUtil.anyColumnsStartWithPrefix) Comparator(java.util.Comparator) Collections(java.util.Collections) RowMapper(org.jdbi.v3.core.mapper.RowMapper) SingleColumnMapper(org.jdbi.v3.core.mapper.SingleColumnMapper) ArrayList(java.util.ArrayList) Nested(org.jdbi.v3.core.mapper.Nested) Field(java.lang.reflect.Field) PropagateNull(org.jdbi.v3.core.mapper.PropagateNull)

Aggregations

ResultSet (java.sql.ResultSet)3 SQLException (java.sql.SQLException)3 ArrayList (java.util.ArrayList)3 Comparator (java.util.Comparator)3 List (java.util.List)3 Map (java.util.Map)3 Optional (java.util.Optional)3 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)3 Nested (org.jdbi.v3.core.mapper.Nested)3 PropagateNull (org.jdbi.v3.core.mapper.PropagateNull)3 RowMapper (org.jdbi.v3.core.mapper.RowMapper)3 SingleColumnMapper (org.jdbi.v3.core.mapper.SingleColumnMapper)3 ReflectionMapperUtil.anyColumnsStartWithPrefix (org.jdbi.v3.core.mapper.reflect.ReflectionMapperUtil.anyColumnsStartWithPrefix)3 ReflectionMapperUtil.findColumnIndex (org.jdbi.v3.core.mapper.reflect.ReflectionMapperUtil.findColumnIndex)3 ReflectionMapperUtil.getColumnNames (org.jdbi.v3.core.mapper.reflect.ReflectionMapperUtil.getColumnNames)3 StatementContext (org.jdbi.v3.core.statement.StatementContext)3 String.format (java.lang.String.format)2 Handle (org.jdbi.v3.core.Handle)2 ColumnMapper (org.jdbi.v3.core.mapper.ColumnMapper)2 RowMapperFactory (org.jdbi.v3.core.mapper.RowMapperFactory)2