Browse Source

DATAJDBC-341 - Map NULL values in EntityRowMapper for columns not being fetched in the query.

Original pull request: #170.
pull/201/head
Thomas Lang 6 years ago committed by Jens Schauder
parent
commit
c2062dbb9d
No known key found for this signature in database
GPG Key ID: 996B1389BA0721C3
  1. 35
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/BasicJdbcConverter.java
  2. 55
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/EntityRowMapperUnitTests.java

35
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/BasicJdbcConverter.java

@ -59,10 +59,10 @@ import org.springframework.util.Assert; @@ -59,10 +59,10 @@ import org.springframework.util.Assert;
* @author Jens Schauder
* @author Christoph Strobl
* @author Myeonghyeon Lee
* @since 1.1
* @see MappingContext
* @see SimpleTypeHolder
* @see CustomConversions
* @since 1.1
*/
public class BasicJdbcConverter extends BasicRelationalConverter implements JdbcConverter {
@ -401,7 +401,35 @@ public class BasicJdbcConverter extends BasicRelationalConverter implements Jdbc @@ -401,7 +401,35 @@ public class BasicJdbcConverter extends BasicRelationalConverter implements Jdbc
continue;
}
propertyAccessor.setProperty(property, readOrLoadProperty(idValue, property));
// check if property is in the result set
// if not - leave it out
// DATAJDBC-341
if (property.isEntity() || property.isEmbedded()) {
propertyAccessor.setProperty(property, readOrLoadProperty(idValue, property));
} else {
try {
if (resultSet.findColumn(property.getColumnName().getReference(identifierProcessing)) > 0) {
propertyAccessor.setProperty(property, readOrLoadProperty(idValue, property));
} else {
try {
propertyAccessor.setProperty(property, readOrLoadProperty(idValue, property));
} catch (Exception exception) {
LOG.info(
"The result set is not corresponding to the target entity. Left out properties will be set to standard values (NULL for reference types, 0 for primitives.");
}
}
} catch (SQLException e) {
String columnAlias = path.extendBy(property).getColumnAlias().getReference(identifierProcessing);
try {
if (resultSet.findColumn(columnAlias) > 0) {
propertyAccessor.setProperty(property, readOrLoadProperty(idValue, property));
}
} catch (SQLException ex) {
LOG.info(String.format("Cannot find column named %s within the result set!", property.getColumnName()));
}
}
}
}
return propertyAccessor.getBean();
@ -523,7 +551,8 @@ public class BasicJdbcConverter extends BasicRelationalConverter implements Jdbc @@ -523,7 +551,8 @@ public class BasicJdbcConverter extends BasicRelationalConverter implements Jdbc
try {
return resultSet.getObject(backreferenceName);
} catch (SQLException o_O) {
throw new MappingException(String.format("Could not read value %s from result set!", backreferenceName), o_O);
LOG.info(String.format("Could not read value %s from result set! Use null as value.", backreferenceName), o_O);
return null;
}
}

55
spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/EntityRowMapperUnitTests.java

@ -32,11 +32,7 @@ import lombok.With; @@ -32,11 +32,7 @@ import lombok.With;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -87,6 +83,35 @@ public class EntityRowMapperUnitTests { @@ -87,6 +83,35 @@ public class EntityRowMapperUnitTests {
}
};
@Test // DATAJDBC-341
public void mapNotNeededValueTypePropertiesToNull() throws SQLException {
ResultSet rs = mockResultSet(singletonList("id"), //
ID_FOR_ENTITY_NOT_REFERENCING_MAP, "alpha");
rs.next();
Trivial extracted = createRowMapper(Trivial.class).mapRow(rs, 1);
assertThat(extracted) //
.isNotNull() //
.extracting(e -> e.id, e -> e.name) //
.containsExactly(ID_FOR_ENTITY_NOT_REFERENCING_MAP, null);
}
@Test // DATAJDBC-341
public void mapNotNeededPrimitiveTypePropertiesToNull() throws SQLException {
ResultSet rs = mockResultSet(singletonList("id"), //
ID_FOR_ENTITY_NOT_REFERENCING_MAP, "alpha");
rs.next();
TrivialMapPropertiesToNullIfNotNeeded extracted = createRowMapper(TrivialMapPropertiesToNullIfNotNeeded.class)
.mapRow(rs, 1);
assertThat(extracted) //
.isNotNull() //
.extracting(e -> e.id, e -> e.age) //
.containsExactly(ID_FOR_ENTITY_NOT_REFERENCING_MAP, 0);
}
@Test // DATAJDBC-113
public void simpleEntitiesGetProperlyExtracted() throws SQLException {
@ -477,6 +502,19 @@ public class EntityRowMapperUnitTests { @@ -477,6 +502,19 @@ public class EntityRowMapperUnitTests {
String name;
}
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
@Getter
static class TrivialMapPropertiesToNullIfNotNeeded {
@Id Long id;
int age;
String phone;
Boolean isSupreme;
long referenceToCustomer;
}
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
@ -762,11 +800,18 @@ public class EntityRowMapperUnitTests { @@ -762,11 +800,18 @@ public class EntityRowMapperUnitTests {
return isAfterLast() || isBeforeFirst() ? 0 : index + 1;
case "toString":
return this.toString();
case "findColumn":
return isThereAColumnNamed(invocation.getArgument(0));
default:
throw new OperationNotSupportedException(invocation.getMethod().getName());
}
}
private int isThereAColumnNamed(String name) {
Optional<Map<String, Object>> first = values.stream().filter(s -> s.equals(name)).findFirst();
return (first.isPresent()) ? 1 : 0;
}
private boolean isAfterLast() {
return index >= values.size() && !values.isEmpty();
}

Loading…
Cancel
Save