Support specification of a schema in Column annotations.

Closes #1099
Original pull request #1108
This commit is contained in:
Mikhail-Polivakha
2021-12-04 12:53:40 +03:00
committed by Jens Schauder
parent cdff3850ae
commit d12146d78c
3 changed files with 86 additions and 14 deletions

View File

@@ -17,6 +17,7 @@ package org.springframework.data.relational.core.mapping;
import java.util.Optional;
import org.jetbrains.annotations.NotNull;
import org.springframework.data.mapping.model.BasicPersistentEntity;
import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.data.util.Lazy;
@@ -29,12 +30,14 @@ import org.springframework.util.StringUtils;
* @author Jens Schauder
* @author Greg Turnquist
* @author Bastian Wilhelm
* @author Mikhail Polivakha
*/
class RelationalPersistentEntityImpl<T> extends BasicPersistentEntity<T, RelationalPersistentProperty>
implements RelationalPersistentEntity<T> {
private final NamingStrategy namingStrategy;
private final Lazy<Optional<SqlIdentifier>> tableName;
private final Lazy<Optional<SqlIdentifier>> schemaName;
private boolean forceQuote = true;
/**
@@ -43,16 +46,20 @@ class RelationalPersistentEntityImpl<T> extends BasicPersistentEntity<T, Relatio
* @param information must not be {@literal null}.
*/
RelationalPersistentEntityImpl(TypeInformation<T> information, NamingStrategy namingStrategy) {
super(information);
final Optional<Table> optionalTableAnnotation = Optional.ofNullable(findAnnotation(Table.class));
this.namingStrategy = namingStrategy;
this.tableName = Lazy.of(() -> Optional.ofNullable( //
findAnnotation(Table.class)) //
.map(Table::value) //
.filter(StringUtils::hasText) //
.map(this::createSqlIdentifier) //
this.tableName = Lazy.of(() -> optionalTableAnnotation
.map(Table::value)
.filter(StringUtils::hasText)
.map(this::createSqlIdentifier)
);
this.schemaName = Lazy.of(() -> optionalTableAnnotation
.map(Table::schema)
.filter(StringUtils::hasText)
.map(this::createSqlIdentifier));
}
private SqlIdentifier createSqlIdentifier(String name) {
@@ -77,14 +84,30 @@ class RelationalPersistentEntityImpl<T> extends BasicPersistentEntity<T, Relatio
*/
@Override
public SqlIdentifier getTableName() {
return tableName.get().orElseGet(() -> {
final Optional<SqlIdentifier> schema = determineCurrentEntitySchema();
final Optional<SqlIdentifier> explicitlySpecifiedTableName = tableName.get();
if (schema.isPresent()) {
return explicitlySpecifiedTableName
.map(sqlIdentifier -> SqlIdentifier.from(schema.get(), sqlIdentifier))
.orElse(SqlIdentifier.from(schema.get(), createDerivedSqlIdentifier(namingStrategy.getTableName(getType()))));
} else {
return explicitlySpecifiedTableName.orElse(createDerivedSqlIdentifier(namingStrategy.getTableName(getType())));
}
}
String schema = namingStrategy.getSchema();
SqlIdentifier tableName = createDerivedSqlIdentifier(namingStrategy.getTableName(getType()));
return StringUtils.hasText(schema) ? SqlIdentifier.from(createDerivedSqlIdentifier(schema), tableName)
: tableName;
});
/**
* @return Optional of {@link SqlIdentifier} representing the current entity schema. If the schema is not specified neither
* explicitly, nor via {@link NamingStrategy}, then return {@link Optional#empty()}
*/
@NotNull
private Optional<SqlIdentifier> determineCurrentEntitySchema() {
final Optional<SqlIdentifier> explicitlySpecifiedSchema = schemaName.get();
if (explicitlySpecifiedSchema.isPresent()) {
return explicitlySpecifiedSchema;
}
return StringUtils.hasText(namingStrategy.getSchema())
? Optional.of(createDerivedSqlIdentifier(namingStrategy.getSchema()))
: Optional.empty();
}
/*

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.data.relational.core.mapping;
import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
@@ -27,6 +29,7 @@ import java.lang.annotation.Target;
*
* @author Kazuki Shimizu
* @author Bastian Wilhelm
* @author Mikhail Polivakha
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@@ -37,5 +40,23 @@ public @interface Table {
/**
* The mapping table name.
*/
@AliasFor("name")
String value() default "";
}
/**
* The mapping table name.
*/
@AliasFor("value")
String name() default "";
/**
* Name of the schema (or user, for example in case of oracle), in which this table resides in
* The behavior is the following: <br/>
* If the {@link Table#schema()} is specified, then it will be
* used as a schema of current table, i.e. as a prefix to the name of the table, which can
* be specified in {@link Table#value()}. <br/>
* If the {@link Table#schema()} is not specified, then spring data will assume the default schema,
* The default schema itself can be provided by the means of {@link NamingStrategy#getSchema()}
*/
String schema() default "";
}

View File

@@ -31,6 +31,7 @@ import org.springframework.data.relational.core.sql.SqlIdentifier;
* @author Kazuki Shimizu
* @author Bastian Wilhelm
* @author Mark Paluch
* @author Mikhail Polivakha
*/
public class RelationalPersistentEntityImplUnitTests {
@@ -72,6 +73,33 @@ public class RelationalPersistentEntityImplUnitTests {
.isEqualTo("\"MY_SCHEMA\".\"DUMMY_ENTITY_WITH_EMPTY_ANNOTATION\"");
}
@Test // DATAJDBC-1099
void testRelationalPersistentEntitySchemaNameChoice() {
mappingContext = new RelationalMappingContext(NamingStrategyWithSchema.INSTANCE);
final RelationalPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(EntityWithExplicitSchema.class);
final SqlIdentifier tableName = persistentEntity.getTableName();
assertThat(tableName).isEqualTo(SqlIdentifier.from(SqlIdentifier.quoted("DART_VADER"), quoted("I_AM_THE_SENATE")));
assertThat(tableName.toString()).isEqualTo("\"DART_VADER\".\"I_AM_THE_SENATE\"");
}
@Test // DATAJDBC-1099
void testRelationalPersistentEntityTableOnlySchemaSpecified() {
final RelationalPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(EntityWithSchemaFromNamingStrategy.class);
final SqlIdentifier tableName = persistentEntity.getTableName();
assertThat(tableName).isEqualTo(SqlIdentifier.from(quoted("ANAKYN_SKYWALKER"), quoted("ENTITY_WITH_SCHEMA_FROM_NAMING_STRATEGY")));
assertThat(tableName.toString()).isEqualTo("\"ANAKYN_SKYWALKER\".\"ENTITY_WITH_SCHEMA_FROM_NAMING_STRATEGY\"");
}
@Table(schema = "ANAKYN_SKYWALKER")
static class EntityWithSchemaFromNamingStrategy {
@Id private Long id;
}
@Table(schema = "DART_VADER", name = "I_AM_THE_SENATE")
static class EntityWithExplicitSchema {
@Id private Long id;
}
@Table("dummy_sub_entity")
static class DummySubEntity {
@Id @Column("renamedId") Long id;