The back reference generation is now configurable.
The default version is the behavior that existed so far: The back reference is the table name as generated by the `NamingStrategy` without taking `@Table` annotations into account. The new alternative is to take `@Table` into account. The behavior can be configured by setting the `foreignKeyNaming` property on the `RelationalMappingContext`. Closes #1161 Closes #1147 Original pull request: #1324.
This commit is contained in:
committed by
Mark Paluch
parent
15796b88fe
commit
40446f9ca9
@@ -298,10 +298,10 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
|
||||
Assert.notNull(propertyPath, "propertyPath must not be null");
|
||||
|
||||
PersistentPropertyPathExtension path = new PersistentPropertyPathExtension(context, propertyPath);
|
||||
|
||||
Class<?> actualType = path.getActualType();
|
||||
|
||||
String findAllByProperty = sql(actualType) //
|
||||
.getFindAllByProperty(identifier, path.getQualifierColumn(), path.isOrdered());
|
||||
.getFindAllByProperty(identifier, propertyPath);
|
||||
|
||||
RowMapper<?> rowMapper = path.isMap() ? this.getMapEntityRowMapper(path, identifier)
|
||||
: this.getEntityRowMapper(path, identifier);
|
||||
|
||||
@@ -37,7 +37,7 @@ class SqlContext {
|
||||
SqlContext(RelationalPersistentEntity<?> entity) {
|
||||
|
||||
this.entity = entity;
|
||||
this.table = Table.create(entity.getTableName());
|
||||
this.table = Table.create(entity.getFullTableName());
|
||||
}
|
||||
|
||||
Column getIdColumn() {
|
||||
|
||||
@@ -200,6 +200,26 @@ class SqlGenerator {
|
||||
return render(selectBuilder(Collections.emptyList(), pageable.getSort(), pageable).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a query for selecting all simple properties of an entity, including those for one-to-one relationships.
|
||||
* Results are limited to those rows referencing some parent entity. This is used to select values for a complex
|
||||
* property ({@link Set}, {@link Map} ...) based on a referencing entity.
|
||||
*
|
||||
* @param parentIdentifier name of the column of the FK back to the referencing entity.
|
||||
* @param propertyPath used to determine if the property is ordered and if there is a key column.
|
||||
* @return a SQL String.
|
||||
*/
|
||||
String getFindAllByProperty(Identifier parentIdentifier,
|
||||
PersistentPropertyPath<? extends RelationalPersistentProperty> propertyPath) {
|
||||
|
||||
Assert.notNull(parentIdentifier, "identifier must not be null");
|
||||
Assert.notNull(propertyPath, "propertyPath must not be null");
|
||||
|
||||
PersistentPropertyPathExtension path = new PersistentPropertyPathExtension(mappingContext, propertyPath);
|
||||
|
||||
return getFindAllByProperty(parentIdentifier, path.getQualifierColumn(), path.isOrdered());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a query for selecting all simple properties of an entity, including those for one-to-one relationships.
|
||||
* Results are limited to those rows referencing some other entity using the column specified by
|
||||
@@ -915,7 +935,7 @@ class SqlGenerator {
|
||||
private SelectBuilder.SelectOrdered applyQueryOnSelect(Query query, MapSqlParameterSource parameterSource,
|
||||
SelectBuilder.SelectWhere selectBuilder) {
|
||||
|
||||
Table table = Table.create(this.entity.getTableName());
|
||||
Table table = Table.create(this.entity.getFullTableName());
|
||||
|
||||
SelectBuilder.SelectOrdered selectOrdered = query //
|
||||
.getCriteria() //
|
||||
|
||||
@@ -38,7 +38,7 @@ class SqlContext {
|
||||
SqlContext(RelationalPersistentEntity<?> entity) {
|
||||
|
||||
this.entity = entity;
|
||||
this.table = Table.create(entity.getTableName());
|
||||
this.table = Table.create(entity.getFullTableName());
|
||||
}
|
||||
|
||||
Column getIdColumn() {
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.data.jdbc.core.convert;
|
||||
import static java.util.Collections.*;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.assertj.core.api.SoftAssertions.*;
|
||||
import static org.springframework.data.relational.core.mapping.ForeignKeyNaming.*;
|
||||
import static org.springframework.data.relational.core.sql.SqlIdentifier.*;
|
||||
|
||||
import java.util.Map;
|
||||
@@ -41,6 +42,7 @@ import org.springframework.data.relational.core.dialect.Dialect;
|
||||
import org.springframework.data.relational.core.dialect.PostgresDialect;
|
||||
import org.springframework.data.relational.core.dialect.SqlServerDialect;
|
||||
import org.springframework.data.relational.core.mapping.Column;
|
||||
import org.springframework.data.relational.core.mapping.DefaultNamingStrategy;
|
||||
import org.springframework.data.relational.core.mapping.NamingStrategy;
|
||||
import org.springframework.data.relational.core.mapping.PersistentPropertyPathExtension;
|
||||
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
|
||||
@@ -763,7 +765,7 @@ class SqlGeneratorUnitTests {
|
||||
@Test // GH-1192
|
||||
void selectByQueryValidTest() {
|
||||
|
||||
SqlGenerator sqlGenerator = createSqlGenerator(DummyEntity.class);
|
||||
SqlGenerator sqlGenerator = createSqlGenerator(DummyEntity.class);
|
||||
|
||||
DummyEntity probe = new DummyEntity();
|
||||
probe.name = "Diego";
|
||||
@@ -862,6 +864,50 @@ class SqlGeneratorUnitTests {
|
||||
.containsOnly(entry("x_name", probe.name));
|
||||
}
|
||||
|
||||
@Test // GH-1161
|
||||
void backReferenceShouldConsiderRenamedParent() {
|
||||
|
||||
context.setForeignKeyNaming(APPLY_RENAMING);
|
||||
|
||||
String sql = sqlGenerator.createDeleteInByPath(getPath("ref", RenamedDummy.class));
|
||||
|
||||
assertThat(sql).isEqualTo("DELETE FROM referenced_entity WHERE referenced_entity.renamed IN (:ids)");
|
||||
|
||||
}
|
||||
|
||||
@Test // GH-1161
|
||||
void backReferenceShouldIgnoreRenamedParent() {
|
||||
|
||||
context.setForeignKeyNaming(IGNORE_RENAMING);
|
||||
|
||||
String sql = sqlGenerator.createDeleteInByPath(getPath("ref", RenamedDummy.class));
|
||||
|
||||
assertThat(sql).isEqualTo("DELETE FROM referenced_entity WHERE referenced_entity.renamed_dummy IN (:ids)");
|
||||
}
|
||||
|
||||
@Test // GH-1161
|
||||
void keyColumnShouldConsiderRenamedParent() {
|
||||
|
||||
context.setForeignKeyNaming(APPLY_RENAMING);
|
||||
SqlGenerator sqlGenerator = createSqlGenerator(ReferencedEntity.class);
|
||||
String sql = sqlGenerator.getFindAllByProperty(Identifier.of(unquoted("parentId"), 23, RenamedDummy.class), getPath("ref", RenamedDummy.class));
|
||||
|
||||
assertThat(sql)
|
||||
.contains("referenced_entity.renamed_key AS renamed_key", "WHERE referenced_entity.parentId");
|
||||
}
|
||||
|
||||
@Test // GH-1161
|
||||
void keyColumnShouldIgnoreRenamedParent() {
|
||||
|
||||
context.setForeignKeyNaming(IGNORE_RENAMING);
|
||||
SqlGenerator sqlGenerator = createSqlGenerator(ReferencedEntity.class);
|
||||
String sql = sqlGenerator.getFindAllByProperty(Identifier.of(unquoted("parentId"), 23, RenamedDummy.class), getPath("ref", RenamedDummy.class));
|
||||
|
||||
assertThat(sql)
|
||||
.contains("referenced_entity.renamed_dummy_key AS renamed_dummy_key", "WHERE referenced_entity.parentId");
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private SqlIdentifier getAlias(Object maybeAliased) {
|
||||
|
||||
@@ -885,8 +931,7 @@ class SqlGeneratorUnitTests {
|
||||
@SuppressWarnings("unused")
|
||||
static class DummyEntity {
|
||||
|
||||
@Column("id1")
|
||||
@Id Long id;
|
||||
@Column("id1") @Id Long id;
|
||||
String name;
|
||||
ReferencedEntity ref;
|
||||
Set<Element> elements;
|
||||
@@ -895,6 +940,15 @@ class SqlGeneratorUnitTests {
|
||||
Map<Long, ReferencedEntity> mappedReference;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@org.springframework.data.relational.core.mapping.Table("renamed")
|
||||
static class RenamedDummy {
|
||||
|
||||
@Id Long id;
|
||||
String name;
|
||||
Map<String, ReferencedEntity> ref;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
static class VersionedEntity extends DummyEntity {
|
||||
@Version Integer version;
|
||||
@@ -936,11 +990,11 @@ class SqlGeneratorUnitTests {
|
||||
String name;
|
||||
}
|
||||
|
||||
private static class PrefixingNamingStrategy implements NamingStrategy {
|
||||
private static class PrefixingNamingStrategy extends DefaultNamingStrategy {
|
||||
|
||||
@Override
|
||||
public String getColumnName(RelationalPersistentProperty property) {
|
||||
return "x_" + NamingStrategy.super.getColumnName(property);
|
||||
return "x_" + super.getColumnName(property);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -964,8 +1018,7 @@ class SqlGeneratorUnitTests {
|
||||
|
||||
// these column names behave like single double quote in the name since the get quoted and then doubling the double
|
||||
// quote escapes it.
|
||||
@Id
|
||||
@Column("test\"\"_@id") Long id;
|
||||
@Id @Column("test\"\"_@id") Long id;
|
||||
@Column("test\"\"_@123") String name;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user