HHH-15550 New global and persistent temporary `create_tables` params
This commit is contained in:
parent
a12a108f59
commit
caaaa71ffd
|
@ -565,11 +565,20 @@ therefore reusing its execution plan.
|
|||
`*hibernate.query.mutation_strategy*` (e.g. A fully-qualified class name, an instance, or a `Class` object reference)::
|
||||
Provide a custom https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/query/sqm/mutation/spi/SqmMultiTableMutationStrategy.html[`org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy`] implementation for handling multi-table bulk HQL operations.
|
||||
|
||||
`*hibernate.hql.bulk_id_strategy.global_temporary.create_tables*` (e.g. `true` (default value) or `false`)::
|
||||
For databases that don't support local tables, but just global ones, this configuration property allows you to control whether to CREATE the global tables used for multi-table bulk HQL operations at `SessionFactory` or the `EntityManagerFactory` startup.
|
||||
|
||||
`*hibernate.hql.bulk_id_strategy.global_temporary.drop_tables*` (e.g. `true` or `false` (default value))::
|
||||
For databases that don't support local tables, but just global ones, this configuration property allows you to DROP the global tables used for multi-table bulk HQL operations when the `SessionFactory` or the `EntityManagerFactory` is closed.
|
||||
|
||||
`*hibernate.hql.bulk_id_strategy.local_temporary.drop_tables*` (e.g. `true` or `false` (default value))::
|
||||
This configuration property allows you to DROP the local temporary tables used for multi-table bulk HQL operations when the `SessionFactory` or the `EntityManagerFactory` is closed. This is useful when testing with a single connection pool against different schemas.
|
||||
This configuration property allows you to DROP the local temporary tables used for multi-table bulk HQL operations when the `SessionFactory` or `EntityManagerFactory` is closed. This is useful when testing with a single connection pool against different schemas.
|
||||
|
||||
`*hibernate.hql.bulk_id_strategy.persistent.create_tables*` (e.g. `true` (default value) or `false`)::
|
||||
This configuration property is used by the https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/hql/spi/id/persistent/PersistentTableBulkIdStrategy.html[`PersistentTableBulkIdStrategy`], that mimics temporary tables for databases which do not support temporary tables.
|
||||
It follows a pattern similar to the ANSI SQL definition of the global temporary table using a "session id" column to segment rows from the various sessions.
|
||||
+
|
||||
This configuration property allows you to control whether to CREATE the tables used for multi-table bulk HQL operations at `SessionFactory` or `EntityManagerFactory` startup.
|
||||
|
||||
`*hibernate.hql.bulk_id_strategy.persistent.drop_tables*` (e.g. `true` or `false` (default value))::
|
||||
This configuration property is used by the https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/hql/spi/id/persistent/PersistentTableBulkIdStrategy.html[`PersistentTableBulkIdStrategy`], that mimics temporary tables for databases which do not support temporary tables.
|
||||
|
|
|
@ -28,6 +28,9 @@ public class GlobalTemporaryTableStrategy {
|
|||
private static final Logger log = Logger.getLogger( GlobalTemporaryTableStrategy.class );
|
||||
|
||||
public static final String SHORT_NAME = "global_temporary";
|
||||
|
||||
public static final String CREATE_ID_TABLES = "hibernate.hql.bulk_id_strategy.global_temporary.create_tables";
|
||||
|
||||
public static final String DROP_ID_TABLES = "hibernate.hql.bulk_id_strategy.global_temporary.drop_tables";
|
||||
|
||||
private final TemporaryTable temporaryTable;
|
||||
|
@ -35,6 +38,7 @@ public class GlobalTemporaryTableStrategy {
|
|||
private final SessionFactoryImplementor sessionFactory;
|
||||
|
||||
private boolean prepared;
|
||||
|
||||
private boolean dropIdTables;
|
||||
|
||||
public GlobalTemporaryTableStrategy(
|
||||
|
@ -55,6 +59,19 @@ public class GlobalTemporaryTableStrategy {
|
|||
return;
|
||||
}
|
||||
|
||||
final ConfigurationService configService = mappingModelCreationProcess.getCreationContext()
|
||||
.getBootstrapContext()
|
||||
.getServiceRegistry().getService( ConfigurationService.class );
|
||||
boolean createIdTables = configService.getSetting(
|
||||
CREATE_ID_TABLES,
|
||||
StandardConverters.BOOLEAN,
|
||||
true
|
||||
);
|
||||
|
||||
if ( !createIdTables ) {
|
||||
return;
|
||||
}
|
||||
|
||||
prepared = true;
|
||||
|
||||
log.debugf( "Creating global-temp ID table : %s", getTemporaryTable().getTableExpression() );
|
||||
|
@ -79,9 +96,6 @@ public class GlobalTemporaryTableStrategy {
|
|||
|
||||
try {
|
||||
temporaryTableCreationWork.execute( connection );
|
||||
final ConfigurationService configService = mappingModelCreationProcess.getCreationContext()
|
||||
.getBootstrapContext()
|
||||
.getServiceRegistry().getService( ConfigurationService.class );
|
||||
this.dropIdTables = configService.getSetting(
|
||||
DROP_ID_TABLES,
|
||||
StandardConverters.BOOLEAN,
|
||||
|
|
|
@ -22,13 +22,6 @@ import org.hibernate.query.sqm.tree.insert.SqmInsertStatement;
|
|||
*/
|
||||
public class PersistentTableInsertStrategy extends PersistentTableStrategy implements SqmMultiTableInsertStrategy {
|
||||
|
||||
public static final String SHORT_NAME = "persistent";
|
||||
|
||||
public static final String DROP_ID_TABLES = "hibernate.hql.bulk_id_strategy.persistent.drop_tables";
|
||||
|
||||
public static final String SCHEMA = "hibernate.hql.bulk_id_strategy.persistent.schema";
|
||||
public static final String CATALOG = "hibernate.hql.bulk_id_strategy.persistent.catalog";
|
||||
|
||||
public PersistentTableInsertStrategy(
|
||||
TemporaryTable entityTable,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
|
|
|
@ -11,6 +11,8 @@ import java.sql.SQLException;
|
|||
|
||||
import org.hibernate.dialect.temptable.TemporaryTable;
|
||||
import org.hibernate.dialect.temptable.TemporaryTableHelper;
|
||||
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||
import org.hibernate.engine.config.spi.StandardConverters;
|
||||
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
|
||||
|
@ -29,9 +31,12 @@ public abstract class PersistentTableStrategy {
|
|||
|
||||
public static final String SHORT_NAME = "persistent";
|
||||
|
||||
public static final String CREATE_ID_TABLES = "hibernate.hql.bulk_id_strategy.persistent.create_tables";
|
||||
|
||||
public static final String DROP_ID_TABLES = "hibernate.hql.bulk_id_strategy.persistent.drop_tables";
|
||||
|
||||
public static final String SCHEMA = "hibernate.hql.bulk_id_strategy.persistent.schema";
|
||||
|
||||
public static final String CATALOG = "hibernate.hql.bulk_id_strategy.persistent.catalog";
|
||||
|
||||
private final TemporaryTable temporaryTable;
|
||||
|
@ -39,8 +44,8 @@ public abstract class PersistentTableStrategy {
|
|||
private final SessionFactoryImplementor sessionFactory;
|
||||
|
||||
private boolean prepared;
|
||||
private boolean created;
|
||||
private boolean released;
|
||||
|
||||
private boolean dropIdTables;
|
||||
|
||||
public PersistentTableStrategy(
|
||||
TemporaryTable temporaryTable,
|
||||
|
@ -60,6 +65,19 @@ public abstract class PersistentTableStrategy {
|
|||
return;
|
||||
}
|
||||
|
||||
final ConfigurationService configService = mappingModelCreationProcess.getCreationContext()
|
||||
.getBootstrapContext()
|
||||
.getServiceRegistry().getService( ConfigurationService.class );
|
||||
boolean createIdTables = configService.getSetting(
|
||||
CREATE_ID_TABLES,
|
||||
StandardConverters.BOOLEAN,
|
||||
true
|
||||
);
|
||||
|
||||
if (!createIdTables ) {
|
||||
return;
|
||||
}
|
||||
|
||||
prepared = true;
|
||||
|
||||
log.debugf( "Creating persistent ID table : %s", getTemporaryTable().getTableExpression() );
|
||||
|
@ -84,7 +102,11 @@ public abstract class PersistentTableStrategy {
|
|||
|
||||
try {
|
||||
temporaryTableCreationWork.execute( connection );
|
||||
created = true;
|
||||
this.dropIdTables = configService.getSetting(
|
||||
DROP_ID_TABLES,
|
||||
StandardConverters.BOOLEAN,
|
||||
false
|
||||
);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
|
@ -93,24 +115,16 @@ public abstract class PersistentTableStrategy {
|
|||
catch (SQLException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
if ( created ) {
|
||||
// todo (6.0) : register strategy for dropping of the table if requested - DROP_ID_TABLES
|
||||
}
|
||||
}
|
||||
|
||||
public void release(
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
JdbcConnectionAccess connectionAccess) {
|
||||
if ( released ) {
|
||||
if ( !dropIdTables ) {
|
||||
return;
|
||||
}
|
||||
|
||||
released = true;
|
||||
|
||||
if ( !created ) {
|
||||
return;
|
||||
}
|
||||
dropIdTables = false;
|
||||
|
||||
final TemporaryTable temporaryTable = getTemporaryTable();
|
||||
log.debugf( "Dropping persistent ID table : %s", temporaryTable.getTableExpression() );
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.orm.test.persister.entity;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.dialect.OracleDialect;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.query.sqm.mutation.internal.temptable.GlobalTemporaryTableStrategy;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.logger.LoggerInspectionRule;
|
||||
import org.hibernate.testing.logger.Triggerable;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.RequiresDialect;
|
||||
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.Rule;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.SecondaryTable;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
||||
/**
|
||||
* @author Marco Belladelli
|
||||
*/
|
||||
@ServiceRegistry(settings = {
|
||||
@Setting(name = GlobalTemporaryTableStrategy.CREATE_ID_TABLES, value = "false")
|
||||
})
|
||||
@DomainModel(annotatedClasses = {
|
||||
TemporaryTableStrategyTest.Bar.class
|
||||
})
|
||||
@SessionFactory
|
||||
@RequiresDialect(OracleDialect.class)
|
||||
public class TemporaryTableStrategyTest {
|
||||
|
||||
@Rule
|
||||
public LoggerInspectionRule logInspection = new LoggerInspectionRule(
|
||||
Logger.getMessageLogger( CoreMessageLogger.class, GlobalTemporaryTableStrategy.class.getName() )
|
||||
);
|
||||
|
||||
private final Triggerable triggerable = logInspection.watchForLogMessages( Set.of(
|
||||
"Creating global-temp ID table",
|
||||
"Dropping global-temp ID table"
|
||||
) );
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-15550")
|
||||
public void testGlobalTemporaryTableStrategy(SessionFactoryScope scope) {
|
||||
scope.inTransaction( s -> {
|
||||
Bar bar = new Bar();
|
||||
bar.id = 1;
|
||||
bar.name = "Noble";
|
||||
bar.name2 = "Experiment";
|
||||
|
||||
s.persist( bar );
|
||||
|
||||
assertFalse( triggerable.wasTriggered(), "Message was triggered" );
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity(name = "BAR")
|
||||
@Table(name = "BAR")
|
||||
@SecondaryTable(name = "BAR2")
|
||||
public static class Bar {
|
||||
@Id
|
||||
@Column(name = "ID")
|
||||
public Integer id;
|
||||
|
||||
@Column(name = "name")
|
||||
public String name;
|
||||
|
||||
@Column(name = "name2", table = "BAR2")
|
||||
public String name2;
|
||||
}
|
||||
}
|
|
@ -104,6 +104,8 @@ logger.entity-action.name=org.hibernate.action.internal.EntityAction
|
|||
logger.cascade.name=org.hibernate.engine.internal.Cascade
|
||||
#logger.cascade.level=trace
|
||||
|
||||
logger.global-temp-strategy.name=org.hibernate.query.sqm.mutation.internal.temptable.GlobalTemporaryTableStrategy
|
||||
logger.global-temp-strategy.level=trace
|
||||
|
||||
logger.merged-entity-copies.name=org.hibernate.event.internal.EntityCopyAllowedLoggedObserver
|
||||
### When entity copy merge functionality is enabled using:
|
||||
|
|
Loading…
Reference in New Issue