HHH-7913 - Schema replacement in <subselect> / @Subselect
This commit is contained in:
parent
c8a66789d1
commit
21095565bc
|
@ -432,6 +432,12 @@ include::{example-dir-mapping}/basic/SubselectTest.java[tag=mapping-Subselect-en
|
|||
----
|
||||
====
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
The underlying `@Subselect` SQL query supports standard Hibernate placeholders ( see <<chapters/query/native/Native.adoc#sql-global-catalog-schema,Catalog and schema in SQL queries>> ).
|
||||
Global settings can be overridden using the `schema` or `catalog` attributes of the `@Table` annotation.
|
||||
====
|
||||
|
||||
If we add a new `AccountTransaction` entity and refresh the `AccountSummary` entity, the balance is updated accordingly:
|
||||
|
||||
[[mapping-Subselect-refresh-find-example]]
|
||||
|
|
|
@ -40,10 +40,14 @@ public interface SqlStringGenerationContext {
|
|||
Identifier getDefaultCatalog();
|
||||
|
||||
/**
|
||||
* @param explicitCatalogOrNull An explicitly configured catalog, or {@code null}.
|
||||
* @return The given identifier if non-{@code null}, or the default catalog otherwise.
|
||||
* Interpret the incoming catalog, returning the incoming value if it is non-null.
|
||||
* Otherwise, returns the current {@linkplain #getDefaultCatalog() default catalog}.
|
||||
*
|
||||
* @apiNote May return {@code null} if {@linkplain #getDefaultCatalog() default catalog} is {@code null}.
|
||||
*/
|
||||
Identifier catalogWithDefault(Identifier explicitCatalogOrNull);
|
||||
default Identifier catalogWithDefault(Identifier explicitCatalogOrNull) {
|
||||
return explicitCatalogOrNull != null ? explicitCatalogOrNull : getDefaultCatalog();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The default schema, used for table/sequence names that do not explicitly mention a schema.
|
||||
|
@ -54,10 +58,14 @@ public interface SqlStringGenerationContext {
|
|||
Identifier getDefaultSchema();
|
||||
|
||||
/**
|
||||
* @param explicitSchemaOrNull An explicitly configured schema, or {@code null}.
|
||||
* @return The given identifier if non-{@code null}, or the default schema otherwise.
|
||||
* Interpret the incoming schema, returning the incoming value if it is non-null.
|
||||
* Otherwise, returns the current {@linkplain #getDefaultSchema() default schema}.
|
||||
*
|
||||
* @apiNote May return {@code null} if {@linkplain #getDefaultSchema() default schema} is {@code null}.
|
||||
*/
|
||||
Identifier schemaWithDefault(Identifier explicitSchemaOrNull);
|
||||
default Identifier schemaWithDefault(Identifier explicitSchemaOrNull) {
|
||||
return explicitSchemaOrNull != null ? explicitSchemaOrNull : getDefaultSchema();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a formatted a table name
|
||||
|
@ -101,4 +109,49 @@ public interface SqlStringGenerationContext {
|
|||
* @return {@code true} if and only if this is a migration
|
||||
*/
|
||||
boolean isMigration();
|
||||
|
||||
/**
|
||||
* Apply default catalog and schema, if necessary, to the given name. May return a new reference.
|
||||
*/
|
||||
default QualifiedTableName withDefaults(QualifiedTableName name) {
|
||||
if ( name.getCatalogName() == null && getDefaultCatalog() != null
|
||||
|| name.getSchemaName() == null && getDefaultSchema() != null ) {
|
||||
return new QualifiedTableName(
|
||||
catalogWithDefault( name.getCatalogName() ),
|
||||
schemaWithDefault( name.getSchemaName() ),
|
||||
name.getTableName()
|
||||
);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply default catalog and schema, if necessary, to the given name. May return a new reference.
|
||||
*/
|
||||
default QualifiedSequenceName withDefaults(QualifiedSequenceName name) {
|
||||
if ( name.getCatalogName() == null && getDefaultCatalog() != null
|
||||
|| name.getSchemaName() == null && getDefaultSchema() != null ) {
|
||||
return new QualifiedSequenceName(
|
||||
catalogWithDefault( name.getCatalogName() ),
|
||||
schemaWithDefault( name.getSchemaName() ),
|
||||
name.getSequenceName()
|
||||
);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply default catalog and schema, if necessary, to the given name. May return a new reference.
|
||||
*/
|
||||
default QualifiedName withDefaults(QualifiedName name) {
|
||||
if ( name.getCatalogName() == null && getDefaultCatalog() != null
|
||||
|| name.getSchemaName() == null && getDefaultSchema() != null ) {
|
||||
return new QualifiedNameImpl(
|
||||
catalogWithDefault( name.getCatalogName() ),
|
||||
schemaWithDefault( name.getSchemaName() ),
|
||||
name.getObjectName()
|
||||
);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -146,48 +146,11 @@ public class SqlStringGenerationContextImpl
|
|||
return defaultCatalog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier catalogWithDefault(Identifier explicitCatalogOrNull) {
|
||||
return explicitCatalogOrNull != null ? explicitCatalogOrNull : defaultCatalog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getDefaultSchema() {
|
||||
return defaultSchema;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier schemaWithDefault(Identifier explicitSchemaOrNull) {
|
||||
return explicitSchemaOrNull != null ? explicitSchemaOrNull : defaultSchema;
|
||||
}
|
||||
|
||||
private QualifiedTableName withDefaults(QualifiedTableName name) {
|
||||
if ( name.getCatalogName() == null && defaultCatalog != null
|
||||
|| name.getSchemaName() == null && defaultSchema != null ) {
|
||||
return new QualifiedTableName( catalogWithDefault( name.getCatalogName() ),
|
||||
schemaWithDefault( name.getSchemaName() ), name.getTableName() );
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
private QualifiedSequenceName withDefaults(QualifiedSequenceName name) {
|
||||
if ( name.getCatalogName() == null && defaultCatalog != null
|
||||
|| name.getSchemaName() == null && defaultSchema != null ) {
|
||||
return new QualifiedSequenceName( catalogWithDefault( name.getCatalogName() ),
|
||||
schemaWithDefault( name.getSchemaName() ), name.getSequenceName() );
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
private QualifiedName withDefaults(QualifiedName name) {
|
||||
if ( name.getCatalogName() == null && defaultCatalog != null
|
||||
|| name.getSchemaName() == null && defaultSchema != null ) {
|
||||
return new QualifiedSequenceName( catalogWithDefault( name.getCatalogName() ),
|
||||
schemaWithDefault( name.getSchemaName() ), name.getObjectName() );
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String format(QualifiedTableName qualifiedName) {
|
||||
return qualifiedObjectNameFormatter.format( withDefaults( qualifiedName ), dialect );
|
||||
|
|
|
@ -4620,9 +4620,21 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
|
||||
protected String determineTableName(Table table) {
|
||||
return MappingModelCreationHelper.getTableIdentifierExpression( table, factory );
|
||||
if ( table.getSubselect() != null ) {
|
||||
final SQLQueryParser sqlQueryParser = new SQLQueryParser(
|
||||
table.getSubselect(),
|
||||
null,
|
||||
// NOTE : this allows finer control over catalog and schema used for placeholder
|
||||
// handling (`{h-catalog}`, `{h-schema}`, `{h-domain}`)
|
||||
new ExplicitSqlStringGenerationContext( table.getCatalog(), table.getSchema(), factory )
|
||||
);
|
||||
return "( " + sqlQueryParser.process() + " )";
|
||||
}
|
||||
|
||||
return factory.getSqlStringGenerationContext().format( table.getQualifiedTableName() );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public EntityEntryFactory getEntityEntryFactory() {
|
||||
return this.entityEntryFactory;
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
* Copyright Red Hat Inc. and Hibernate Authors
|
||||
*/
|
||||
package org.hibernate.persister.entity;
|
||||
|
||||
import org.hibernate.boot.model.naming.Identifier;
|
||||
import org.hibernate.boot.model.relational.QualifiedName;
|
||||
import org.hibernate.boot.model.relational.QualifiedSequenceName;
|
||||
import org.hibernate.boot.model.relational.QualifiedTableName;
|
||||
import org.hibernate.boot.model.relational.SqlStringGenerationContext;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.engine.jdbc.env.spi.QualifiedObjectNameFormatter;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
||||
/**
|
||||
* SqlStringGenerationContext implementation with support for overriding the
|
||||
* default catalog and schema
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ExplicitSqlStringGenerationContext implements SqlStringGenerationContext {
|
||||
private final SessionFactoryImplementor factory;
|
||||
private final Identifier defaultCatalog;
|
||||
private final Identifier defaultSchema;
|
||||
|
||||
public ExplicitSqlStringGenerationContext(
|
||||
String defaultCatalog,
|
||||
String defaultSchema,
|
||||
SessionFactoryImplementor factory) {
|
||||
this.factory = factory;
|
||||
this.defaultCatalog = defaultCatalog != null
|
||||
? toIdentifier( defaultCatalog )
|
||||
: toIdentifier( factory.getSessionFactoryOptions().getDefaultCatalog() );
|
||||
this.defaultSchema = defaultSchema != null
|
||||
? toIdentifier( defaultSchema )
|
||||
: toIdentifier( factory.getSessionFactoryOptions().getDefaultSchema() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialect getDialect() {
|
||||
return factory.getJdbcServices().getDialect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier toIdentifier(String text) {
|
||||
return factory.getJdbcServices().getJdbcEnvironment().getIdentifierHelper().toIdentifier( text );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getDefaultCatalog() {
|
||||
return defaultCatalog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getDefaultSchema() {
|
||||
return defaultSchema;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String format(QualifiedTableName qualifiedName) {
|
||||
return nameFormater().format( withDefaults( qualifiedName ), getDialect() );
|
||||
}
|
||||
|
||||
private QualifiedObjectNameFormatter nameFormater() {
|
||||
final JdbcEnvironment jdbcEnvironment = factory.getJdbcServices().getJdbcEnvironment();
|
||||
//noinspection deprecation
|
||||
return jdbcEnvironment.getQualifiedObjectNameFormatter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String format(QualifiedSequenceName qualifiedName) {
|
||||
return nameFormater().format( withDefaults( qualifiedName ), getDialect() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String format(QualifiedName qualifiedName) {
|
||||
return nameFormater().format( withDefaults( qualifiedName ), getDialect() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String formatWithoutCatalog(QualifiedSequenceName qualifiedName) {
|
||||
QualifiedSequenceName nameToFormat;
|
||||
if ( qualifiedName.getCatalogName() != null
|
||||
|| qualifiedName.getSchemaName() == null && defaultSchema != null ) {
|
||||
nameToFormat = new QualifiedSequenceName( null,
|
||||
schemaWithDefault( qualifiedName.getSchemaName() ), qualifiedName.getSequenceName() );
|
||||
}
|
||||
else {
|
||||
nameToFormat = qualifiedName;
|
||||
}
|
||||
return nameFormater().format( nameToFormat, getDialect() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMigration() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -4,8 +4,6 @@
|
|||
*/
|
||||
package org.hibernate.query.sql.internal;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.boot.model.naming.Identifier;
|
||||
import org.hibernate.boot.model.relational.SqlStringGenerationContext;
|
||||
|
@ -14,6 +12,8 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
|
|||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Substitutes escape sequences of form {@code {alias}},
|
||||
* {@code {alias.field}}, and {@code {alias.*}} in a
|
||||
|
@ -25,11 +25,11 @@ import org.hibernate.persister.entity.EntityPersister;
|
|||
* @author Paul Benedict
|
||||
*/
|
||||
public class SQLQueryParser {
|
||||
|
||||
private final SessionFactoryImplementor factory;
|
||||
private final String originalQueryString;
|
||||
private final ParserContext context;
|
||||
|
||||
private final SqlStringGenerationContext sqlStringGenerationContext;
|
||||
|
||||
private long aliasesFound;
|
||||
|
||||
public interface ParserContext {
|
||||
|
@ -43,9 +43,16 @@ public class SQLQueryParser {
|
|||
}
|
||||
|
||||
public SQLQueryParser(String queryString, ParserContext context, SessionFactoryImplementor factory) {
|
||||
this( queryString, context, factory.getSqlStringGenerationContext() );
|
||||
}
|
||||
|
||||
public SQLQueryParser(
|
||||
String queryString,
|
||||
ParserContext context,
|
||||
SqlStringGenerationContext sqlStringGenerationContext) {
|
||||
this.originalQueryString = queryString;
|
||||
this.context = context;
|
||||
this.factory = factory;
|
||||
this.sqlStringGenerationContext = sqlStringGenerationContext;
|
||||
}
|
||||
|
||||
public boolean queryHasAliases() {
|
||||
|
@ -169,10 +176,9 @@ public class SQLQueryParser {
|
|||
}
|
||||
|
||||
private void handlePlaceholder(String token, StringBuilder result) {
|
||||
final SqlStringGenerationContext context = factory.getSqlStringGenerationContext();
|
||||
final Identifier defaultCatalog = context.getDefaultCatalog();
|
||||
final Identifier defaultSchema = context.getDefaultSchema();
|
||||
final Dialect dialect = context.getDialect();
|
||||
final Identifier defaultCatalog = sqlStringGenerationContext.getDefaultCatalog();
|
||||
final Identifier defaultSchema = sqlStringGenerationContext.getDefaultSchema();
|
||||
final Dialect dialect = sqlStringGenerationContext.getDialect();
|
||||
switch (token) {
|
||||
case "h-domain":
|
||||
if ( defaultCatalog != null ) {
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
* Copyright Red Hat Inc. and Hibernate Authors
|
||||
*/
|
||||
package org.hibernate.orm.test.sql;
|
||||
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.persister.entity.ExplicitSqlStringGenerationContext;
|
||||
import org.hibernate.query.sql.internal.SQLQueryParser;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.RequiresDialect;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link SQLQueryParser}
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@SuppressWarnings("JUnitMalformedDeclaration")
|
||||
public class SQLQueryParserUnitTests {
|
||||
|
||||
@Test
|
||||
@DomainModel
|
||||
@SessionFactory
|
||||
@RequiresDialect(H2Dialect.class)
|
||||
void testDomainParsing(SessionFactoryScope scope) {
|
||||
final SessionFactoryImplementor sessionFactory = scope.getSessionFactory();
|
||||
final String sqlQuery = "select id, name from {h-domain}the_table";
|
||||
|
||||
final String full = processSqlString( sqlQuery, "my_catalog", "my_schema", sessionFactory );
|
||||
assertThat( full ).endsWith( " my_catalog.my_schema.the_table" );
|
||||
|
||||
final String catalogOnly = processSqlString( sqlQuery, "my_catalog", null, sessionFactory );
|
||||
assertThat( catalogOnly ).endsWith( " my_catalog.the_table" );
|
||||
|
||||
final String schemaOnly = processSqlString( sqlQuery, null, "my_schema", sessionFactory );
|
||||
assertThat( schemaOnly ).endsWith( " my_schema.the_table" );
|
||||
|
||||
final String none = processSqlString( sqlQuery, null, null, sessionFactory );
|
||||
assertThat( none ).endsWith( " the_table" );
|
||||
}
|
||||
|
||||
@Test
|
||||
@DomainModel
|
||||
@SessionFactory
|
||||
@RequiresDialect(H2Dialect.class)
|
||||
void testCatalogParsing(SessionFactoryScope scope) {
|
||||
final SessionFactoryImplementor sessionFactory = scope.getSessionFactory();
|
||||
final String sqlQuery = "select id, name from {h-catalog}the_table";
|
||||
|
||||
final String full = processSqlString( sqlQuery, "my_catalog", "my_schema", sessionFactory );
|
||||
assertThat( full ).endsWith( " my_catalog.the_table" );
|
||||
|
||||
final String catalogOnly = processSqlString( sqlQuery, "my_catalog", null, sessionFactory );
|
||||
assertThat( catalogOnly ).endsWith( " my_catalog.the_table" );
|
||||
|
||||
final String schemaOnly = processSqlString( sqlQuery, null, "my_schema", sessionFactory );
|
||||
assertThat( schemaOnly ).endsWith( " the_table" );
|
||||
|
||||
final String none = processSqlString( sqlQuery, null, null, sessionFactory );
|
||||
assertThat( none ).endsWith( " the_table" );
|
||||
}
|
||||
|
||||
@Test
|
||||
@DomainModel
|
||||
@SessionFactory
|
||||
@RequiresDialect(H2Dialect.class)
|
||||
void testSchemaParsing(SessionFactoryScope scope) {
|
||||
final SessionFactoryImplementor sessionFactory = scope.getSessionFactory();
|
||||
final String sqlQuery = "select id, name from {h-schema}the_table";
|
||||
|
||||
final String full = processSqlString( sqlQuery, "my_catalog", "my_schema", sessionFactory );
|
||||
assertThat( full ).endsWith( " my_schema.the_table" );
|
||||
|
||||
final String catalogOnly = processSqlString( sqlQuery, "my_catalog", null, sessionFactory );
|
||||
assertThat( catalogOnly ).endsWith( " the_table" );
|
||||
|
||||
final String schemaOnly = processSqlString( sqlQuery, null, "my_schema", sessionFactory );
|
||||
assertThat( schemaOnly ).endsWith( " my_schema.the_table" );
|
||||
|
||||
final String none = processSqlString( sqlQuery, null, null, sessionFactory );
|
||||
assertThat( none ).endsWith( " the_table" );
|
||||
}
|
||||
|
||||
private static String processSqlString(
|
||||
String sqlQuery,
|
||||
String catalogName,
|
||||
String schemaName,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
// Use a custom SqlStringGenerationContext to integrate the catalog and schema
|
||||
final ExplicitSqlStringGenerationContext stringGenerationContext
|
||||
= new ExplicitSqlStringGenerationContext( catalogName, schemaName, sessionFactory );
|
||||
return new SQLQueryParser( sqlQuery, null, stringGenerationContext ).process();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
* Copyright Red Hat Inc. and Hibernate Authors
|
||||
*/
|
||||
package org.hibernate.orm.test.subselect;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import org.hibernate.annotations.Subselect;
|
||||
import org.hibernate.cfg.MappingSettings;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
|
||||
import org.hibernate.metamodel.spi.RuntimeMetamodelsImplementor;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.hibernate.testing.orm.junit.Setting;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
/**
|
||||
* Simple tests that catalog/schema placeholders in {@link org.hibernate.annotations.Subselect}
|
||||
* mappings are handled correctly.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@SuppressWarnings("JUnitMalformedDeclaration")
|
||||
public class SubselectWithPlaceholdersUnitTests {
|
||||
@Test
|
||||
@DomainModel(annotatedClasses = {EntityInCatalog.class, EntityInCatalogAndSchema.class, EntityInSchema.class, EntityInLocalCatalog.class})
|
||||
@SessionFactory(exportSchema = false)
|
||||
void testPlaceholdersWithNone(SessionFactoryScope scope) {
|
||||
final RuntimeMetamodelsImplementor runtimeMetamodels = scope.getSessionFactory().getRuntimeMetamodels();
|
||||
final MappingMetamodelImplementor mappingMetamodel = runtimeMetamodels.getMappingMetamodel();
|
||||
|
||||
final EntityPersister entityInCatalogDescriptor = mappingMetamodel.getEntityDescriptor( EntityInCatalog.class );
|
||||
assertThat( entityInCatalogDescriptor.getTableName() ).endsWith( " from table_in_catalog )" );
|
||||
|
||||
final EntityPersister entityInSchemaDescriptor = mappingMetamodel.getEntityDescriptor( EntityInSchema.class );
|
||||
assertThat( entityInSchemaDescriptor.getTableName() ).endsWith( " from table_in_schema )" );
|
||||
|
||||
final EntityPersister entityInCatalogAndSchemaDescriptor = mappingMetamodel.getEntityDescriptor( EntityInCatalogAndSchema.class );
|
||||
assertThat( entityInCatalogAndSchemaDescriptor.getTableName() ).endsWith( " from table_in_both )" );
|
||||
}
|
||||
|
||||
@Test
|
||||
@ServiceRegistry(settings = {
|
||||
@Setting(name= MappingSettings.DEFAULT_CATALOG, value = "the_catalog")
|
||||
})
|
||||
@DomainModel(annotatedClasses = {EntityInCatalog.class, EntityInCatalogAndSchema.class, EntityInSchema.class, EntityInLocalCatalog.class})
|
||||
@SessionFactory(exportSchema = false)
|
||||
void testPlaceholdersWithCatalog(SessionFactoryScope scope) {
|
||||
final SessionFactoryImplementor sessionFactory = scope.getSessionFactory();
|
||||
final RuntimeMetamodelsImplementor runtimeMetamodels = sessionFactory.getRuntimeMetamodels();
|
||||
final MappingMetamodelImplementor mappingMetamodel = runtimeMetamodels.getMappingMetamodel();
|
||||
|
||||
final EntityPersister entityInCatalogDescriptor = mappingMetamodel.getEntityDescriptor( EntityInCatalog.class );
|
||||
assertThat( entityInCatalogDescriptor.getTableName() ).endsWith( " from the_catalog.table_in_catalog )" );
|
||||
|
||||
final EntityPersister entityInSchemaDescriptor = mappingMetamodel.getEntityDescriptor( EntityInSchema.class );
|
||||
assertThat( entityInSchemaDescriptor.getTableName() ).endsWith( " from table_in_schema )" );
|
||||
|
||||
final EntityPersister entityInCatalogAndSchemaDescriptor = mappingMetamodel.getEntityDescriptor( EntityInCatalogAndSchema.class );
|
||||
assertThat( entityInCatalogAndSchemaDescriptor.getTableName() ).endsWith( " from the_catalog.table_in_both )" );
|
||||
|
||||
final EntityPersister entityInLocalCatalogDescriptor = mappingMetamodel.getEntityDescriptor( EntityInLocalCatalog.class );
|
||||
assertThat( entityInLocalCatalogDescriptor.getTableName() ).endsWith( " from local_catalog.table_in_local_catalog )" );
|
||||
}
|
||||
|
||||
@Test
|
||||
@ServiceRegistry(settings = {
|
||||
@Setting(name= MappingSettings.DEFAULT_SCHEMA, value = "the_schema")
|
||||
})
|
||||
@DomainModel(annotatedClasses = {EntityInCatalog.class, EntityInCatalogAndSchema.class, EntityInSchema.class, EntityInLocalCatalog.class})
|
||||
@SessionFactory(exportSchema = false)
|
||||
void testPlaceholdersWithSchema(SessionFactoryScope scope) {
|
||||
final SessionFactoryImplementor sessionFactory = scope.getSessionFactory();
|
||||
final RuntimeMetamodelsImplementor runtimeMetamodels = sessionFactory.getRuntimeMetamodels();
|
||||
final MappingMetamodelImplementor mappingMetamodel = runtimeMetamodels.getMappingMetamodel();
|
||||
|
||||
|
||||
final EntityPersister entityInCatalogDescriptor = mappingMetamodel.getEntityDescriptor( EntityInCatalog.class );
|
||||
assertThat( entityInCatalogDescriptor.getTableName() ).endsWith( " from table_in_catalog )" );
|
||||
|
||||
final EntityPersister entityInSchemaDescriptor = mappingMetamodel.getEntityDescriptor( EntityInSchema.class );
|
||||
assertThat( entityInSchemaDescriptor.getTableName() ).endsWith( " from the_schema.table_in_schema )" );
|
||||
|
||||
final EntityPersister entityInCatalogAndSchemaDescriptor = mappingMetamodel.getEntityDescriptor( EntityInCatalogAndSchema.class );
|
||||
assertThat( entityInCatalogAndSchemaDescriptor.getTableName() ).endsWith( " from the_schema.table_in_both )" );
|
||||
|
||||
final EntityPersister entityInLocalCatalogDescriptor = mappingMetamodel.getEntityDescriptor( EntityInLocalCatalog.class );
|
||||
assertThat( entityInLocalCatalogDescriptor.getTableName() ).endsWith( " from local_catalog.table_in_local_catalog )" );
|
||||
}
|
||||
|
||||
@Test
|
||||
@ServiceRegistry(settings = {
|
||||
@Setting(name= MappingSettings.DEFAULT_CATALOG, value = "the_catalog"),
|
||||
@Setting(name= MappingSettings.DEFAULT_SCHEMA, value = "the_schema")
|
||||
})
|
||||
@DomainModel(annotatedClasses = {EntityInCatalog.class, EntityInCatalogAndSchema.class, EntityInSchema.class, EntityInLocalCatalog.class})
|
||||
@SessionFactory(exportSchema = false)
|
||||
void testPlaceholdersWithCatalogAndSchema(SessionFactoryScope scope) {
|
||||
final SessionFactoryImplementor sessionFactory = scope.getSessionFactory();
|
||||
final RuntimeMetamodelsImplementor runtimeMetamodels = sessionFactory.getRuntimeMetamodels();
|
||||
final MappingMetamodelImplementor mappingMetamodel = runtimeMetamodels.getMappingMetamodel();
|
||||
|
||||
final EntityPersister entityInCatalogDescriptor = mappingMetamodel.getEntityDescriptor( EntityInCatalog.class );
|
||||
assertThat( entityInCatalogDescriptor.getTableName() ).endsWith( " from the_catalog.table_in_catalog )" );
|
||||
|
||||
final EntityPersister entityInSchemaDescriptor = mappingMetamodel.getEntityDescriptor( EntityInSchema.class );
|
||||
assertThat( entityInSchemaDescriptor.getTableName() ).endsWith( " from the_schema.table_in_schema )" );
|
||||
|
||||
final EntityPersister entityInCatalogAndSchemaDescriptor = mappingMetamodel.getEntityDescriptor( EntityInCatalogAndSchema.class );
|
||||
assertThat( entityInCatalogAndSchemaDescriptor.getTableName() ).endsWith( " from the_catalog.the_schema.table_in_both )" );
|
||||
|
||||
final EntityPersister entityInLocalCatalogDescriptor = mappingMetamodel.getEntityDescriptor( EntityInLocalCatalog.class );
|
||||
assertThat( entityInLocalCatalogDescriptor.getTableName() ).endsWith( " from local_catalog.table_in_local_catalog )" );
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Subselect("select id, name from {h-catalog}table_in_catalog")
|
||||
public static class EntityInCatalog {
|
||||
@Id
|
||||
private Integer id;
|
||||
private String name;
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Subselect("select id, name from {h-catalog}table_in_local_catalog")
|
||||
@Table(catalog = "local_catalog")
|
||||
public static class EntityInLocalCatalog {
|
||||
@Id
|
||||
private Integer id;
|
||||
private String name;
|
||||
}
|
||||
|
||||
@Entity(name = "EntityInCatalogAndSchema")
|
||||
@Subselect("select id, name from {h-domain}table_in_both")
|
||||
public static class EntityInCatalogAndSchema {
|
||||
@Id
|
||||
private Integer id;
|
||||
private String name;
|
||||
}
|
||||
|
||||
@Entity(name = "EntityInSchema")
|
||||
@Subselect("select id, name from {h-schema}table_in_schema")
|
||||
public static class EntityInSchema {
|
||||
@Id
|
||||
private Integer id;
|
||||
private String name;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue