Browse Source

DATAJDBC-324 - Add support of read-only columns.

Columns annotated with `ReadOnlyProperty` will be ignored when generating INSERT or UPDATE statements.

Original pull request: #112.
pull/115/head
Oleksandr Kucher 7 years ago committed by Jens Schauder
parent
commit
709d6ef4d5
  1. 9
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/SqlGenerator.java
  2. 89
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/SqlGeneratorUnitTests.java

9
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/SqlGenerator.java

@ -17,6 +17,7 @@ package org.springframework.data.jdbc.core; @@ -17,6 +17,7 @@ package org.springframework.data.jdbc.core;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@ -24,6 +25,7 @@ import java.util.Set; @@ -24,6 +25,7 @@ import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.springframework.data.annotation.ReadOnlyProperty;
import org.springframework.data.jdbc.repository.support.SimpleJdbcRepository;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.mapping.PropertyHandler;
@ -41,6 +43,7 @@ import org.springframework.util.Assert; @@ -41,6 +43,7 @@ import org.springframework.util.Assert;
* @author Jens Schauder
* @author Yoichi Imai
* @author Bastian Wilhelm
* @author Oleksandr Kucher
*/
class SqlGenerator {
@ -48,6 +51,7 @@ class SqlGenerator { @@ -48,6 +51,7 @@ class SqlGenerator {
private final RelationalMappingContext context;
private final List<String> columnNames = new ArrayList<>();
private final List<String> nonIdColumnNames = new ArrayList<>();
private final Set<String> readOnlyColumnNames = new HashSet<>();
private final Lazy<String> findOneSql = Lazy.of(this::createFindOneSelectSql);
private final Lazy<String> findAllSql = Lazy.of(this::createFindAllSql);
@ -93,6 +97,9 @@ class SqlGenerator { @@ -93,6 +97,9 @@ class SqlGenerator {
if (!entity.isIdProperty(property)) {
nonIdColumnNames.add(columnName);
}
if (property.isAnnotationPresent(ReadOnlyProperty.class)) {
readOnlyColumnNames.add(columnName);
}
}
private void initEmbeddedColumnNames(RelationalPersistentProperty property, String prefix) {
@ -328,6 +335,7 @@ class SqlGenerator { @@ -328,6 +335,7 @@ class SqlGenerator {
LinkedHashSet<String> columnNamesForInsert = new LinkedHashSet<>(nonIdColumnNames);
columnNamesForInsert.addAll(additionalColumns);
columnNamesForInsert.removeIf(readOnlyColumnNames::contains);
String tableColumns = String.join(", ", columnNamesForInsert);
@ -344,6 +352,7 @@ class SqlGenerator { @@ -344,6 +352,7 @@ class SqlGenerator {
String setClause = columnNames.stream() //
.filter(s -> !s.equals(entity.getIdColumn())) //
.filter(s -> !readOnlyColumnNames.contains(s)) //
.map(n -> String.format("%s = :%s", n, n)) //
.collect(Collectors.joining(", "));

89
spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/SqlGeneratorUnitTests.java

@ -25,6 +25,7 @@ import org.assertj.core.api.SoftAssertions; @@ -25,6 +25,7 @@ import org.assertj.core.api.SoftAssertions;
import org.junit.Before;
import org.junit.Test;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.ReadOnlyProperty;
import org.springframework.data.jdbc.core.mapping.AggregateReference;
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
import org.springframework.data.jdbc.core.mapping.PersistentPropertyPathTestUtils;
@ -40,6 +41,7 @@ import org.springframework.data.relational.core.mapping.RelationalPersistentProp @@ -40,6 +41,7 @@ import org.springframework.data.relational.core.mapping.RelationalPersistentProp
*
* @author Jens Schauder
* @author Greg Turnquist
* @author Oleksandr Kucher
*/
public class SqlGeneratorUnitTests {
@ -226,6 +228,87 @@ public class SqlGeneratorUnitTests { @@ -226,6 +228,87 @@ public class SqlGeneratorUnitTests {
"id1 = :id");
}
@Test // DATAJDBC-324
public void readOnlyPropertyExcludedFromQuery_when_generateUpdateSql() {
final SqlGenerator sqlGenerator = createSqlGenerator(EntityWithReadOnlyProperty.class);
assertThat(sqlGenerator.getUpdate()).isEqualToIgnoringCase( //
"UPDATE entity_with_read_only_property " //
+ "SET x_name = :x_name " //
+ "WHERE x_id = :x_id" //
);
}
@Test // DATAJDBC-324
public void readOnlyPropertyExcludedFromQuery_when_generateInsertSql() {
final SqlGenerator sqlGenerator = createSqlGenerator(EntityWithReadOnlyProperty.class);
assertThat(sqlGenerator.getInsert(emptySet())).isEqualToIgnoringCase( //
"INSERT INTO entity_with_read_only_property (x_name) " //
+ "VALUES (:x_name)" //
);
}
@Test // DATAJDBC-324
public void readOnlyPropertyIncludedIntoQuery_when_generateFindAllSql() {
final SqlGenerator sqlGenerator = createSqlGenerator(EntityWithReadOnlyProperty.class);
assertThat(sqlGenerator.getFindAll()).isEqualToIgnoringCase("SELECT "
+ "entity_with_read_only_property.x_id AS x_id, " + "entity_with_read_only_property.x_name AS x_name, "
+ "entity_with_read_only_property.x_read_only_value AS x_read_only_value "
+ "FROM entity_with_read_only_property");
}
@Test // DATAJDBC-324
public void readOnlyPropertyIncludedIntoQuery_when_generateFindAllByPropertySql() {
final SqlGenerator sqlGenerator = createSqlGenerator(EntityWithReadOnlyProperty.class);
assertThat(sqlGenerator.getFindAllByProperty("back-ref", "key-column", true)).isEqualToIgnoringCase( //
"SELECT " //
+ "entity_with_read_only_property.x_id AS x_id, " //
+ "entity_with_read_only_property.x_name AS x_name, " //
+ "entity_with_read_only_property.x_read_only_value AS x_read_only_value, " //
+ "entity_with_read_only_property.key-column AS key-column " //
+ "FROM entity_with_read_only_property " //
+ "WHERE back-ref = :back-ref " //
+ "ORDER BY key-column" //
);
}
@Test // DATAJDBC-324
public void readOnlyPropertyIncludedIntoQuery_when_generateFindAllInListSql() {
final SqlGenerator sqlGenerator = createSqlGenerator(EntityWithReadOnlyProperty.class);
assertThat(sqlGenerator.getFindAllInList()).isEqualToIgnoringCase( //
"SELECT " //
+ "entity_with_read_only_property.x_id AS x_id, " //
+ "entity_with_read_only_property.x_name AS x_name, " //
+ "entity_with_read_only_property.x_read_only_value AS x_read_only_value " //
+ "FROM entity_with_read_only_property " //
+ "WHERE entity_with_read_only_property.x_id in(:ids)" //
);
}
@Test // DATAJDBC-324
public void readOnlyPropertyIncludedIntoQuery_when_generateFindOneSql() {
final SqlGenerator sqlGenerator = createSqlGenerator(EntityWithReadOnlyProperty.class);
assertThat(sqlGenerator.getFindOne()).isEqualToIgnoringCase( //
"SELECT " //
+ "entity_with_read_only_property.x_id AS x_id, " //
+ "entity_with_read_only_property.x_name AS x_name, " //
+ "entity_with_read_only_property.x_read_only_value AS x_read_only_value " //
+ "FROM entity_with_read_only_property " //
+ "WHERE entity_with_read_only_property.x_id = :id" //
);
}
private PersistentPropertyPath<RelationalPersistentProperty> getPath(String path, Class<?> base) {
return PersistentPropertyPathTestUtils.getPath(context, path, base);
}
@ -289,4 +372,10 @@ public class SqlGeneratorUnitTests { @@ -289,4 +372,10 @@ public class SqlGeneratorUnitTests {
@Id Long id;
}
static class EntityWithReadOnlyProperty {
@Id Long id;
String name;
@ReadOnlyProperty String readOnlyValue;
}
}

Loading…
Cancel
Save