mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-26 05:14:57 +00:00
HHH-9724 - More complete "temp table" coverage and allow Dialects to influence which strategy is used
This commit is contained in:
parent
52589379e1
commit
ae43670290
@ -37,8 +37,7 @@
|
||||
import org.hibernate.cache.spi.QueryCacheFactory;
|
||||
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||
import org.hibernate.dialect.function.SQLFunction;
|
||||
import org.hibernate.hql.spi.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.QueryTranslatorFactory;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.loader.BatchFetchStyle;
|
||||
import org.hibernate.proxy.EntityNotFoundDelegate;
|
||||
import org.hibernate.tuple.entity.EntityTuplizer;
|
||||
@ -266,6 +265,8 @@ public SessionFactoryBuilder applyEntityTuplizer(
|
||||
*/
|
||||
public SessionFactoryBuilder applyMultiTableBulkIdStrategy(MultiTableBulkIdStrategy strategy);
|
||||
|
||||
public SessionFactoryBuilder applyTempTableDdlTransactionHandling(TempTableDdlTransactionHandling handling);
|
||||
|
||||
/**
|
||||
* What style of batching should be used?
|
||||
*
|
||||
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.boot;
|
||||
|
||||
/**
|
||||
* Enum describing how creation and dropping of temporary tables should be done in terms of
|
||||
* transaction handling.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public enum TempTableDdlTransactionHandling {
|
||||
/**
|
||||
* No handling of transactions is needed
|
||||
*/
|
||||
NONE,
|
||||
/**
|
||||
* Execution of the DDL must be isolated from any ongoing transaction
|
||||
*/
|
||||
ISOLATE,
|
||||
/**
|
||||
* As with {@link #ISOLATE} the execution of the DDL must be isolated from any ongoing transaction.
|
||||
* However, here the "isolation" will also be transacted. Some databases require that the DDL
|
||||
* happen within a transaction. This value covers such cases.
|
||||
*/
|
||||
ISOLATE_AND_TRANSACT
|
||||
}
|
@ -43,6 +43,7 @@
|
||||
import org.hibernate.SessionFactoryObserver;
|
||||
import org.hibernate.boot.SchemaAutoTooling;
|
||||
import org.hibernate.boot.SessionFactoryBuilder;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.selector.spi.StrategySelector;
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
@ -60,7 +61,7 @@
|
||||
import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.transaction.spi.TransactionFactory;
|
||||
import org.hibernate.hql.spi.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.internal.SessionFactoryImpl;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.loader.BatchFetchStyle;
|
||||
@ -251,6 +252,12 @@ public SessionFactoryBuilder applyMultiTableBulkIdStrategy(MultiTableBulkIdStrat
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionFactoryBuilder applyTempTableDdlTransactionHandling(TempTableDdlTransactionHandling handling) {
|
||||
this.options.tempTableDdlTransactionHandling = handling;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionFactoryBuilder applyBatchFetchStyle(BatchFetchStyle style) {
|
||||
this.options.batchFetchStyle = style;
|
||||
@ -481,6 +488,7 @@ public static class SessionFactoryOptionsStateStandardImpl implements SessionFac
|
||||
private boolean checkNullability;
|
||||
private boolean initializeLazyStateOutsideTransactions;
|
||||
private MultiTableBulkIdStrategy multiTableBulkIdStrategy;
|
||||
private TempTableDdlTransactionHandling tempTableDdlTransactionHandling;
|
||||
private BatchFetchStyle batchFetchStyle;
|
||||
private int defaultBatchFetchSize;
|
||||
private Integer maximumFetchDepth;
|
||||
@ -514,8 +522,6 @@ public static class SessionFactoryOptionsStateStandardImpl implements SessionFac
|
||||
private SchemaAutoTooling schemaAutoTooling;
|
||||
|
||||
// JDBC Handling
|
||||
private boolean dataDefinitionImplicitCommit; // not exposed on builder atm
|
||||
private boolean dataDefinitionInTransactionSupported; // not exposed on builder atm
|
||||
private boolean getGeneratedKeysEnabled;
|
||||
private int jdbcBatchSize;
|
||||
private boolean jdbcBatchVersionedData;
|
||||
@ -641,8 +647,16 @@ public SessionFactoryOptionsStateStandardImpl(StandardServiceRegistry serviceReg
|
||||
|
||||
|
||||
final ExtractedDatabaseMetaData meta = jdbcServices.getExtractedMetaDataSupport();
|
||||
this.dataDefinitionImplicitCommit = meta.doesDataDefinitionCauseTransactionCommit();
|
||||
this.dataDefinitionInTransactionSupported = meta.supportsDataDefinitionInTransaction();
|
||||
|
||||
this.tempTableDdlTransactionHandling = TempTableDdlTransactionHandling.NONE;
|
||||
if ( meta.doesDataDefinitionCauseTransactionCommit() ) {
|
||||
if ( meta.supportsDataDefinitionInTransaction() ) {
|
||||
this.tempTableDdlTransactionHandling = TempTableDdlTransactionHandling.ISOLATE_AND_TRANSACT;
|
||||
}
|
||||
else {
|
||||
this.tempTableDdlTransactionHandling = TempTableDdlTransactionHandling.ISOLATE;
|
||||
}
|
||||
}
|
||||
|
||||
this.jdbcBatchSize = ConfigurationHelper.getInt( STATEMENT_BATCH_SIZE, configurationSettings, 0 );
|
||||
if ( !meta.supportsBatchUpdates() ) {
|
||||
@ -763,6 +777,11 @@ public MultiTableBulkIdStrategy getMultiTableBulkIdStrategy() {
|
||||
return multiTableBulkIdStrategy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TempTableDdlTransactionHandling getTempTableDdlTransactionHandling() {
|
||||
return tempTableDdlTransactionHandling;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BatchFetchStyle getBatchFetchStyle() {
|
||||
return batchFetchStyle;
|
||||
@ -868,16 +887,6 @@ public SchemaAutoTooling getSchemaAutoTooling() {
|
||||
return schemaAutoTooling;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDataDefinitionImplicitCommit() {
|
||||
return dataDefinitionImplicitCommit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDataDefinitionInTransactionSupported() {
|
||||
return dataDefinitionInTransactionSupported;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getJdbcBatchSize() {
|
||||
return jdbcBatchSize;
|
||||
@ -1025,6 +1034,11 @@ public MultiTableBulkIdStrategy getMultiTableBulkIdStrategy() {
|
||||
return options.getMultiTableBulkIdStrategy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TempTableDdlTransactionHandling getTempTableDdlTransactionHandling() {
|
||||
return options.getTempTableDdlTransactionHandling();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BatchFetchStyle getBatchFetchStyle() {
|
||||
return options.getBatchFetchStyle();
|
||||
@ -1130,16 +1144,6 @@ public SchemaAutoTooling getSchemaAutoTooling() {
|
||||
return options.getSchemaAutoTooling();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDataDefinitionImplicitCommit() {
|
||||
return options.isDataDefinitionImplicitCommit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDataDefinitionInTransactionSupported() {
|
||||
return options.isDataDefinitionInTransactionSupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getJdbcBatchSize() {
|
||||
return options.getJdbcBatchSize();
|
||||
|
@ -34,13 +34,14 @@
|
||||
import org.hibernate.NullPrecedence;
|
||||
import org.hibernate.SessionFactoryObserver;
|
||||
import org.hibernate.boot.SchemaAutoTooling;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||
import org.hibernate.cache.spi.QueryCacheFactory;
|
||||
import org.hibernate.cfg.BaselineSessionEventsListenerBuilder;
|
||||
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||
import org.hibernate.dialect.function.SQLFunction;
|
||||
import org.hibernate.hql.spi.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.loader.BatchFetchStyle;
|
||||
import org.hibernate.proxy.EntityNotFoundDelegate;
|
||||
import org.hibernate.tuple.entity.EntityTuplizerFactory;
|
||||
@ -81,6 +82,7 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions {
|
||||
private boolean checkNullability;
|
||||
private final boolean initializeLazyStateOutsideTransactions;
|
||||
private final MultiTableBulkIdStrategy multiTableBulkIdStrategy;
|
||||
private final TempTableDdlTransactionHandling tempTableDdlTransactionHandling;
|
||||
private final BatchFetchStyle batchFetchStyle;
|
||||
private final int defaultBatchFetchSize;
|
||||
private final Integer maximumFetchDepth;
|
||||
@ -114,8 +116,6 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions {
|
||||
private final SchemaAutoTooling schemaAutoTooling;
|
||||
|
||||
// JDBC Handling
|
||||
private final boolean dataDefinitionImplicitCommit; // not exposed on builder atm
|
||||
private final boolean dataDefinitionInTransactionSupported; // not exposed on builder atm
|
||||
private final boolean getGeneratedKeysEnabled;
|
||||
private final int jdbcBatchSize;
|
||||
private final boolean jdbcBatchVersionedData;
|
||||
@ -154,6 +154,7 @@ public SessionFactoryOptionsImpl(SessionFactoryOptionsState state) {
|
||||
this.checkNullability = state.isCheckNullability();
|
||||
this.initializeLazyStateOutsideTransactions = state.isInitializeLazyStateOutsideTransactionsEnabled();
|
||||
this.multiTableBulkIdStrategy = state.getMultiTableBulkIdStrategy();
|
||||
this.tempTableDdlTransactionHandling = state.getTempTableDdlTransactionHandling();
|
||||
this.batchFetchStyle = state.getBatchFetchStyle();
|
||||
this.defaultBatchFetchSize = state.getDefaultBatchFetchSize();
|
||||
this.maximumFetchDepth = state.getMaximumFetchDepth();
|
||||
@ -182,8 +183,6 @@ public SessionFactoryOptionsImpl(SessionFactoryOptionsState state) {
|
||||
this.schemaAutoTooling = state.getSchemaAutoTooling();
|
||||
|
||||
this.connectionReleaseMode = state.getConnectionReleaseMode();
|
||||
this.dataDefinitionImplicitCommit = state.isDataDefinitionImplicitCommit();
|
||||
this.dataDefinitionInTransactionSupported = state.isDataDefinitionInTransactionSupported();
|
||||
this.getGeneratedKeysEnabled = state.isGetGeneratedKeysEnabled();
|
||||
this.jdbcBatchSize = state.getJdbcBatchSize();
|
||||
this.jdbcBatchVersionedData = state.isJdbcBatchVersionedData();
|
||||
@ -279,6 +278,11 @@ public MultiTableBulkIdStrategy getMultiTableBulkIdStrategy() {
|
||||
return multiTableBulkIdStrategy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TempTableDdlTransactionHandling getTempTableDdlTransactionHandling() {
|
||||
return tempTableDdlTransactionHandling;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BatchFetchStyle getBatchFetchStyle() {
|
||||
return batchFetchStyle;
|
||||
@ -383,16 +387,6 @@ public SchemaAutoTooling getSchemaAutoTooling() {
|
||||
return schemaAutoTooling;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDataDefinitionImplicitCommit() {
|
||||
return dataDefinitionImplicitCommit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDataDefinitionInTransactionSupported() {
|
||||
return dataDefinitionInTransactionSupported;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getJdbcBatchSize() {
|
||||
return jdbcBatchSize;
|
||||
|
@ -34,12 +34,13 @@
|
||||
import org.hibernate.NullPrecedence;
|
||||
import org.hibernate.SessionFactoryObserver;
|
||||
import org.hibernate.boot.SchemaAutoTooling;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.cache.spi.QueryCacheFactory;
|
||||
import org.hibernate.cfg.BaselineSessionEventsListenerBuilder;
|
||||
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||
import org.hibernate.dialect.function.SQLFunction;
|
||||
import org.hibernate.hql.spi.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.loader.BatchFetchStyle;
|
||||
import org.hibernate.proxy.EntityNotFoundDelegate;
|
||||
import org.hibernate.tuple.entity.EntityTuplizerFactory;
|
||||
@ -84,6 +85,8 @@ public interface SessionFactoryOptionsState {
|
||||
|
||||
public MultiTableBulkIdStrategy getMultiTableBulkIdStrategy();
|
||||
|
||||
public TempTableDdlTransactionHandling getTempTableDdlTransactionHandling();
|
||||
|
||||
public BatchFetchStyle getBatchFetchStyle();
|
||||
|
||||
public int getDefaultBatchFetchSize();
|
||||
@ -126,10 +129,6 @@ public interface SessionFactoryOptionsState {
|
||||
|
||||
public SchemaAutoTooling getSchemaAutoTooling();
|
||||
|
||||
public boolean isDataDefinitionImplicitCommit();
|
||||
|
||||
public boolean isDataDefinitionInTransactionSupported();
|
||||
|
||||
public int getJdbcBatchSize();
|
||||
|
||||
public boolean isJdbcBatchVersionedData();
|
||||
|
@ -97,11 +97,10 @@
|
||||
import org.hibernate.event.internal.EntityCopyAllowedObserver;
|
||||
import org.hibernate.event.internal.EntityCopyNotAllowedObserver;
|
||||
import org.hibernate.event.spi.EntityCopyObserver;
|
||||
import org.hibernate.hql.spi.GlobalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.LocalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.PersistentTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.TemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.local.LocalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.persistent.PersistentTableBulkIdStrategy;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
@ -383,11 +382,6 @@ private void addMultiTableBulkIdStrategies(StrategySelectorImpl strategySelector
|
||||
LocalTemporaryTableBulkIdStrategy.SHORT_NAME,
|
||||
LocalTemporaryTableBulkIdStrategy.class
|
||||
);
|
||||
strategySelector.registerStrategyImplementor(
|
||||
MultiTableBulkIdStrategy.class,
|
||||
TemporaryTableBulkIdStrategy.SHORT_NAME,
|
||||
TemporaryTableBulkIdStrategy.class
|
||||
);
|
||||
}
|
||||
|
||||
private void addEntityCopyObserverStrategies(StrategySelectorImpl strategySelector) {
|
||||
|
@ -34,12 +34,13 @@
|
||||
import org.hibernate.NullPrecedence;
|
||||
import org.hibernate.SessionFactoryObserver;
|
||||
import org.hibernate.boot.SchemaAutoTooling;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.cache.spi.QueryCacheFactory;
|
||||
import org.hibernate.cfg.BaselineSessionEventsListenerBuilder;
|
||||
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||
import org.hibernate.dialect.function.SQLFunction;
|
||||
import org.hibernate.hql.spi.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.loader.BatchFetchStyle;
|
||||
import org.hibernate.proxy.EntityNotFoundDelegate;
|
||||
import org.hibernate.tuple.entity.EntityTuplizerFactory;
|
||||
@ -108,6 +109,8 @@ public interface SessionFactoryOptions {
|
||||
|
||||
public MultiTableBulkIdStrategy getMultiTableBulkIdStrategy();
|
||||
|
||||
public TempTableDdlTransactionHandling getTempTableDdlTransactionHandling();
|
||||
|
||||
public BatchFetchStyle getBatchFetchStyle();
|
||||
|
||||
public int getDefaultBatchFetchSize();
|
||||
@ -150,10 +153,6 @@ public interface SessionFactoryOptions {
|
||||
|
||||
public SchemaAutoTooling getSchemaAutoTooling();
|
||||
|
||||
public boolean isDataDefinitionImplicitCommit();
|
||||
|
||||
public boolean isDataDefinitionInTransactionSupported();
|
||||
|
||||
public int getJdbcBatchSize();
|
||||
|
||||
public boolean isJdbcBatchVersionedData();
|
||||
|
@ -36,7 +36,7 @@
|
||||
import org.hibernate.cache.spi.QueryCacheFactory;
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
|
||||
import org.hibernate.hql.spi.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.QueryTranslatorFactory;
|
||||
import org.hibernate.loader.BatchFetchStyle;
|
||||
import org.hibernate.tuple.entity.EntityTuplizerFactory;
|
||||
@ -281,14 +281,6 @@ public boolean isAutoValidateSchema() {
|
||||
return sessionFactoryOptions.getSchemaAutoTooling() == SchemaAutoTooling.VALIDATE;
|
||||
}
|
||||
|
||||
public boolean isDataDefinitionImplicitCommit() {
|
||||
return sessionFactoryOptions.isDataDefinitionImplicitCommit();
|
||||
}
|
||||
|
||||
public boolean isDataDefinitionInTransactionSupported() {
|
||||
return sessionFactoryOptions.isDataDefinitionInTransactionSupported();
|
||||
}
|
||||
|
||||
public int getJdbcBatchSize() {
|
||||
return sessionFactoryOptions.getJdbcBatchSize();
|
||||
}
|
||||
|
@ -53,6 +53,11 @@
|
||||
import org.hibernate.exception.LockTimeoutException;
|
||||
import org.hibernate.exception.SQLGrammarException;
|
||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||
import org.hibernate.hql.spi.id.IdTableSupport;
|
||||
import org.hibernate.hql.spi.id.IdTableSupportStandardImpl;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.local.AfterUseAction;
|
||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
@ -413,8 +418,16 @@ public String getCreateSequenceString(final String sequenceName) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateTemporaryTableString() {
|
||||
return "create global temporary table";
|
||||
public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() {
|
||||
return new GlobalTemporaryTableBulkIdStrategy(
|
||||
new IdTableSupportStandardImpl() {
|
||||
@Override
|
||||
public String getCreateIdTableCommand() {
|
||||
return "create global temporary table";
|
||||
}
|
||||
},
|
||||
AfterUseAction.CLEAN
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -647,11 +660,6 @@ public boolean supportsTableCheck() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTemporaryTables() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTupleDistinctCounts() {
|
||||
return false;
|
||||
|
@ -32,12 +32,17 @@
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.function.CharIndexFunction;
|
||||
import org.hibernate.dialect.function.NoArgSQLFunction;
|
||||
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
||||
import org.hibernate.hql.spi.id.IdTableSupportStandardImpl;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.local.AfterUseAction;
|
||||
import org.hibernate.hql.spi.id.local.LocalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
||||
/**
|
||||
@ -250,19 +255,18 @@ public String getCurrentTimestampSelectString() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTemporaryTables() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateTemporaryTableName(String baseTableName) {
|
||||
return "#" + baseTableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dropTemporaryTableAfterUse() {
|
||||
// sql-server, at least needed this dropped after use; strange!
|
||||
return true;
|
||||
public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() {
|
||||
return new LocalTemporaryTableBulkIdStrategy(
|
||||
new IdTableSupportStandardImpl() {
|
||||
@Override
|
||||
public String generateIdTableName(String baseName) {
|
||||
return "#" + baseName;
|
||||
}
|
||||
},
|
||||
// sql-server, at least needed this dropped after use; strange!
|
||||
AfterUseAction.DROP,
|
||||
TempTableDdlTransactionHandling.NONE
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -53,6 +53,10 @@
|
||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
||||
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
||||
import org.hibernate.hql.spi.id.IdTableSupportStandardImpl;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.local.AfterUseAction;
|
||||
import org.hibernate.id.IdentityGenerator;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.persister.entity.Lockable;
|
||||
@ -458,38 +462,23 @@ public boolean hasSelfReferentialForeignKeyBug() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// temporary table support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@Override
|
||||
public boolean supportsTemporaryTables() {
|
||||
return true;
|
||||
}
|
||||
public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() {
|
||||
return new GlobalTemporaryTableBulkIdStrategy(
|
||||
new IdTableSupportStandardImpl() {
|
||||
@Override
|
||||
public String generateIdTableName(String baseName) {
|
||||
final String name = super.generateIdTableName( baseName );
|
||||
return name.length() > 25 ? name.substring( 1, 25 ) : name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateTemporaryTableName(String baseTableName) {
|
||||
final String name = super.generateTemporaryTableName( baseTableName );
|
||||
return name.length() > 25 ? name.substring( 1, 25 ) : name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateTemporaryTableString() {
|
||||
return "create global temporary table";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean performTemporaryTableDDLInIsolation() {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateTemporaryTablePostfix() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dropTemporaryTableAfterUse() {
|
||||
return true;
|
||||
@Override
|
||||
public String getCreateIdTableCommand() {
|
||||
return "create global temporary table";
|
||||
}
|
||||
},
|
||||
AfterUseAction.DROP
|
||||
);
|
||||
}
|
||||
|
||||
// IDENTITY support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -45,6 +45,10 @@
|
||||
import org.hibernate.engine.spi.RowSelection;
|
||||
import org.hibernate.exception.LockTimeoutException;
|
||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||
import org.hibernate.hql.spi.id.IdTableSupportStandardImpl;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.local.AfterUseAction;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||
@ -403,23 +407,26 @@ public boolean supportsCommentOn() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTemporaryTables() {
|
||||
return true;
|
||||
}
|
||||
public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() {
|
||||
return new GlobalTemporaryTableBulkIdStrategy(
|
||||
new IdTableSupportStandardImpl() {
|
||||
@Override
|
||||
public String generateIdTableName(String baseName) {
|
||||
return "session." + super.generateIdTableName( baseName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateTemporaryTableString() {
|
||||
return "declare global temporary table";
|
||||
}
|
||||
@Override
|
||||
public String getCreateIdTableCommand() {
|
||||
return "declare global temporary table";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateTemporaryTablePostfix() {
|
||||
return "not logged";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateTemporaryTableName(String baseTableName) {
|
||||
return "session." + super.generateTemporaryTableName( baseTableName );
|
||||
@Override
|
||||
public String getCreateIdTableStatementOptions() {
|
||||
return "not logged";
|
||||
}
|
||||
},
|
||||
AfterUseAction.CLEAN
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -23,6 +23,24 @@
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.sql.Blob;
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.Clob;
|
||||
import java.sql.NClob;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
@ -58,9 +76,8 @@
|
||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||
import org.hibernate.exception.spi.SQLExceptionConverter;
|
||||
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
||||
import org.hibernate.hql.spi.LocalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.PersistentTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.persistent.PersistentTableBulkIdStrategy;
|
||||
import org.hibernate.id.IdentityGenerator;
|
||||
import org.hibernate.id.SequenceGenerator;
|
||||
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
||||
@ -92,30 +109,12 @@
|
||||
import org.hibernate.tool.schema.internal.StandardSequenceExporter;
|
||||
import org.hibernate.tool.schema.internal.StandardTableExporter;
|
||||
import org.hibernate.tool.schema.internal.StandardUniqueKeyExporter;
|
||||
import org.hibernate.tool.schema.internal.TemporaryTableExporter;
|
||||
import org.hibernate.tool.schema.spi.Exporter;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.descriptor.sql.ClobTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.sql.Blob;
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.Clob;
|
||||
import java.sql.NClob;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* Represents a dialect of SQL implemented by a particular RDBMS. Subclasses implement Hibernate compatibility
|
||||
@ -1516,100 +1515,10 @@ public String getCreateMultisetTableString() {
|
||||
return getCreateTableString();
|
||||
}
|
||||
|
||||
|
||||
// temporary table support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() {
|
||||
// mimic the old behavior for now...
|
||||
return supportsTemporaryTables()
|
||||
? LocalTemporaryTableBulkIdStrategy.INSTANCE
|
||||
: new PersistentTableBulkIdStrategy();
|
||||
return new PersistentTableBulkIdStrategy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this dialect support temporary tables?
|
||||
*
|
||||
* @return True if temp tables are supported; false otherwise.
|
||||
*/
|
||||
public boolean supportsTemporaryTables() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a temporary table name given the base table.
|
||||
*
|
||||
* @param baseTableName The table name from which to base the temp table name.
|
||||
* @return The generated temp table name.
|
||||
*/
|
||||
public String generateTemporaryTableName(String baseTableName) {
|
||||
return "HT_" + baseTableName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Command used to create a temporary table.
|
||||
*
|
||||
* @return The command used to create a temporary table.
|
||||
*/
|
||||
public String getCreateTemporaryTableString() {
|
||||
return "create table";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any fragments needing to be postfixed to the command for
|
||||
* temporary table creation.
|
||||
*
|
||||
* @return Any required postfix.
|
||||
*/
|
||||
public String getCreateTemporaryTablePostfix() {
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Command used to drop a temporary table.
|
||||
*
|
||||
* @return The command used to drop a temporary table.
|
||||
*/
|
||||
public String getDropTemporaryTableString() {
|
||||
return "drop table";
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the dialect require that temporary table DDL statements occur in
|
||||
* isolation from other statements? This would be the case if the creation
|
||||
* would cause any current transaction to get committed implicitly.
|
||||
* <p/>
|
||||
* JDBC defines a standard way to query for this information via the
|
||||
* {@link java.sql.DatabaseMetaData#dataDefinitionCausesTransactionCommit()}
|
||||
* method. However, that does not distinguish between temporary table
|
||||
* DDL and other forms of DDL; MySQL, for example, reports DDL causing a
|
||||
* transaction commit via its driver, even though that is not the case for
|
||||
* temporary table DDL.
|
||||
* <p/>
|
||||
* Possible return values and their meanings:<ul>
|
||||
* <li>{@link Boolean#TRUE} - Unequivocally, perform the temporary table DDL
|
||||
* in isolation.</li>
|
||||
* <li>{@link Boolean#FALSE} - Unequivocally, do <b>not</b> perform the
|
||||
* temporary table DDL in isolation.</li>
|
||||
* <li><i>null</i> - defer to the JDBC driver response in regards to
|
||||
* {@link java.sql.DatabaseMetaData#dataDefinitionCausesTransactionCommit()}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @return see the result matrix above.
|
||||
*/
|
||||
public Boolean performTemporaryTableDDLInIsolation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do we need to drop the temporary table after use?
|
||||
*
|
||||
* @return True if the table should be dropped.
|
||||
*/
|
||||
public boolean dropTemporaryTableAfterUse() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// callable statement support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
/**
|
||||
@ -2007,16 +1916,11 @@ public final String quote(String name) {
|
||||
private StandardForeignKeyExporter foreignKeyExporter = new StandardForeignKeyExporter( this );
|
||||
private StandardUniqueKeyExporter uniqueKeyExporter = new StandardUniqueKeyExporter( this );
|
||||
private StandardAuxiliaryDatabaseObjectExporter auxiliaryObjectExporter = new StandardAuxiliaryDatabaseObjectExporter( this );
|
||||
private TemporaryTableExporter temporaryTableExporter = new TemporaryTableExporter( this );
|
||||
|
||||
public Exporter<Table> getTableExporter() {
|
||||
return tableExporter;
|
||||
}
|
||||
|
||||
public Exporter<Table> getTemporaryTableExporter() {
|
||||
return temporaryTableExporter;
|
||||
}
|
||||
|
||||
public Exporter<Sequence> getSequenceExporter() {
|
||||
return sequenceExporter;
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
import org.hibernate.JDBCException;
|
||||
import org.hibernate.PessimisticLockException;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.dialect.function.AvgWithArgumentCastFunction;
|
||||
import org.hibernate.dialect.function.NoArgSQLFunction;
|
||||
@ -42,6 +43,10 @@
|
||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
||||
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
||||
import org.hibernate.hql.spi.id.IdTableSupportStandardImpl;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.local.AfterUseAction;
|
||||
import org.hibernate.hql.spi.id.local.LocalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
@ -395,32 +400,24 @@ public JDBCException convert(SQLException sqlException, String message, String s
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTemporaryTables() {
|
||||
return true;
|
||||
}
|
||||
public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() {
|
||||
return new LocalTemporaryTableBulkIdStrategy(
|
||||
new IdTableSupportStandardImpl() {
|
||||
@Override
|
||||
public String getCreateIdTableCommand() {
|
||||
return "create cached local temporary table if not exists";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateTemporaryTableString() {
|
||||
return "create cached local temporary table if not exists";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateTemporaryTablePostfix() {
|
||||
// actually 2 different options are specified here:
|
||||
// 1) [on commit drop] - says to drop the table on transaction commit
|
||||
// 2) [transactional] - says to not perform an implicit commit of any current transaction
|
||||
return "on commit drop transactional";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean performTemporaryTableDDLInIsolation() {
|
||||
// explicitly create the table using the same connection and transaction
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dropTemporaryTableAfterUse() {
|
||||
return false;
|
||||
@Override
|
||||
public String getCreateIdTableStatementOptions() {
|
||||
// actually 2 different options are specified here:
|
||||
// 1) [on commit drop] - says to drop the table on transaction commit
|
||||
// 2) [transactional] - says to not perform an implicit commit of any current transaction
|
||||
return "on commit drop transactional"; }
|
||||
},
|
||||
AfterUseAction.CLEAN,
|
||||
TempTableDdlTransactionHandling.NONE
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -32,6 +32,7 @@
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.StaleObjectStateException;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.function.AvgWithArgumentCastFunction;
|
||||
import org.hibernate.dialect.function.NoArgSQLFunction;
|
||||
@ -52,6 +53,11 @@
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
||||
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
||||
import org.hibernate.hql.spi.id.IdTableSupportStandardImpl;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.local.AfterUseAction;
|
||||
import org.hibernate.hql.spi.id.local.LocalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
@ -516,73 +522,54 @@ public boolean supportsUnionAll() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// temporary table support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
// Hibernate uses this information for temporary tables that it uses for its own operations
|
||||
// therefore the appropriate strategy is taken with different versions of HSQLDB
|
||||
|
||||
// All versions of HSQLDB support GLOBAL TEMPORARY tables where the table
|
||||
// definition is shared by all users but data is private to the session
|
||||
// HSQLDB 2.0 also supports session-based LOCAL TEMPORARY tables where
|
||||
// the definition and data is private to the session and table declaration
|
||||
// can happen in the middle of a transaction
|
||||
|
||||
@Override
|
||||
public boolean supportsTemporaryTables() {
|
||||
return true;
|
||||
}
|
||||
public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() {
|
||||
// Hibernate uses this information for temporary tables that it uses for its own operations
|
||||
// therefore the appropriate strategy is taken with different versions of HSQLDB
|
||||
|
||||
// All versions of HSQLDB support GLOBAL TEMPORARY tables where the table
|
||||
// definition is shared by all users but data is private to the session
|
||||
// HSQLDB 2.0 also supports session-based LOCAL TEMPORARY tables where
|
||||
// the definition and data is private to the session and table declaration
|
||||
// can happen in the middle of a transaction
|
||||
|
||||
@Override
|
||||
public String generateTemporaryTableName(String baseTableName) {
|
||||
if ( hsqldbVersion < 20 ) {
|
||||
return "HT_" + baseTableName;
|
||||
return new GlobalTemporaryTableBulkIdStrategy(
|
||||
new IdTableSupportStandardImpl() {
|
||||
@Override
|
||||
public String generateIdTableName(String baseName) {
|
||||
return "HT_" + baseName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateIdTableCommand() {
|
||||
return "create global temporary table";
|
||||
}
|
||||
},
|
||||
// Version 1.8 GLOBAL TEMPORARY table definitions persist beyond the end
|
||||
// of the session (by default, data is cleared at commit).
|
||||
AfterUseAction.CLEAN
|
||||
);
|
||||
}
|
||||
else {
|
||||
// With HSQLDB 2.0, the table name is qualified with MODULE to assist the drop
|
||||
// statement (in-case there is a global name beginning with HT_)
|
||||
return "MODULE.HT_" + baseTableName;
|
||||
}
|
||||
}
|
||||
return new LocalTemporaryTableBulkIdStrategy(
|
||||
new IdTableSupportStandardImpl() {
|
||||
@Override
|
||||
public String generateIdTableName(String baseName) {
|
||||
// With HSQLDB 2.0, the table name is qualified with MODULE to assist the drop
|
||||
// statement (in-case there is a global name beginning with HT_)
|
||||
return "MODULE.HT_" + baseName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateTemporaryTableString() {
|
||||
if ( hsqldbVersion < 20 ) {
|
||||
return "create global temporary table";
|
||||
@Override
|
||||
public String getCreateIdTableCommand() {
|
||||
return "declare local temporary table";
|
||||
}
|
||||
},
|
||||
AfterUseAction.DROP,
|
||||
TempTableDdlTransactionHandling.NONE
|
||||
);
|
||||
}
|
||||
else {
|
||||
return "declare local temporary table";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateTemporaryTablePostfix() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDropTemporaryTableString() {
|
||||
return "drop table";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean performTemporaryTableDDLInIsolation() {
|
||||
// Different behavior for GLOBAL TEMPORARY (1.8) and LOCAL TEMPORARY (2.0)
|
||||
if ( hsqldbVersion < 20 ) {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
else {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dropTemporaryTableAfterUse() {
|
||||
// Version 1.8 GLOBAL TEMPORARY table definitions persist beyond the end
|
||||
// of the session (by default, data is cleared at commit).<p>
|
||||
//
|
||||
// Version 2.x LOCAL TEMPORARY table definitions do not persist beyond
|
||||
// the end of the session (by default, data is cleared at commit).
|
||||
return true;
|
||||
}
|
||||
|
||||
// current timestamp support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -28,6 +28,7 @@
|
||||
import java.util.Locale;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
||||
import org.hibernate.dialect.pagination.FirstLimitHandler;
|
||||
import org.hibernate.dialect.pagination.LimitHandler;
|
||||
@ -35,6 +36,10 @@
|
||||
import org.hibernate.dialect.unique.UniqueDelegate;
|
||||
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
||||
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
||||
import org.hibernate.hql.spi.id.IdTableSupportStandardImpl;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.local.AfterUseAction;
|
||||
import org.hibernate.hql.spi.id.local.LocalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
@ -287,18 +292,22 @@ public String getCurrentTimestampSelectString() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTemporaryTables() {
|
||||
return true;
|
||||
}
|
||||
public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() {
|
||||
return new LocalTemporaryTableBulkIdStrategy(
|
||||
new IdTableSupportStandardImpl() {
|
||||
@Override
|
||||
public String getCreateIdTableCommand() {
|
||||
return "create temp table";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateTemporaryTableString() {
|
||||
return "create temp table";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateTemporaryTablePostfix() {
|
||||
return "with no log";
|
||||
@Override
|
||||
public String getCreateIdTableStatementOptions() {
|
||||
return "with no log";
|
||||
}
|
||||
},
|
||||
AfterUseAction.CLEAN,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -32,6 +32,10 @@
|
||||
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
||||
import org.hibernate.dialect.pagination.FirstLimitHandler;
|
||||
import org.hibernate.dialect.pagination.LimitHandler;
|
||||
import org.hibernate.hql.spi.id.IdTableSupportStandardImpl;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.local.AfterUseAction;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
||||
/**
|
||||
@ -268,24 +272,28 @@ public boolean useMaxForLimit() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTemporaryTables() {
|
||||
return true;
|
||||
public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() {
|
||||
return new GlobalTemporaryTableBulkIdStrategy(
|
||||
new IdTableSupportStandardImpl() {
|
||||
@Override
|
||||
public String generateIdTableName(String baseName) {
|
||||
return "session." + super.generateIdTableName( baseName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateIdTableCommand() {
|
||||
return "declare global temporary table";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateIdTableStatementOptions() {
|
||||
return "on commit preserve rows with norecovery";
|
||||
}
|
||||
},
|
||||
AfterUseAction.CLEAN
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateTemporaryTableString() {
|
||||
return "declare global temporary table";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateTemporaryTablePostfix() {
|
||||
return "on commit preserve rows with norecovery";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateTemporaryTableName(String baseTableName) {
|
||||
return "session." + super.generateTemporaryTableName( baseTableName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurrentTimestampSQLFunctionName() {
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
import org.hibernate.JDBCException;
|
||||
import org.hibernate.NullPrecedence;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.function.NoArgSQLFunction;
|
||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||
@ -40,6 +41,11 @@
|
||||
import org.hibernate.exception.LockAcquisitionException;
|
||||
import org.hibernate.exception.LockTimeoutException;
|
||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||
import org.hibernate.hql.spi.id.IdTableSupport;
|
||||
import org.hibernate.hql.spi.id.IdTableSupportStandardImpl;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.local.AfterUseAction;
|
||||
import org.hibernate.hql.spi.id.local.LocalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
@ -314,25 +320,22 @@ public String getColumnComment(String comment) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTemporaryTables() {
|
||||
return true;
|
||||
}
|
||||
public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() {
|
||||
return new LocalTemporaryTableBulkIdStrategy(
|
||||
new IdTableSupportStandardImpl() {
|
||||
@Override
|
||||
public String getCreateIdTableCommand() {
|
||||
return "create temporary table if not exists";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateTemporaryTableString() {
|
||||
return "create temporary table if not exists";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDropTemporaryTableString() {
|
||||
return "drop temporary table";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean performTemporaryTableDDLInIsolation() {
|
||||
// because we [drop *temporary* table...] we do not
|
||||
// have to doAfterTransactionCompletion these in isolation.
|
||||
return Boolean.FALSE;
|
||||
@Override
|
||||
public String getDropIdTableCommand() {
|
||||
return "drop temporary table";
|
||||
}
|
||||
},
|
||||
AfterUseAction.DROP,
|
||||
TempTableDdlTransactionHandling.NONE
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -49,8 +49,10 @@
|
||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
||||
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
||||
import org.hibernate.hql.spi.GlobalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.IdTableSupportStandardImpl;
|
||||
import org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.local.AfterUseAction;
|
||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||
import org.hibernate.procedure.internal.StandardCallableStatementSupport;
|
||||
import org.hibernate.procedure.spi.CallableStatementSupport;
|
||||
@ -586,33 +588,26 @@ public boolean supportsCommentOn() {
|
||||
|
||||
@Override
|
||||
public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() {
|
||||
return new GlobalTemporaryTableBulkIdStrategy();
|
||||
}
|
||||
return new GlobalTemporaryTableBulkIdStrategy(
|
||||
new IdTableSupportStandardImpl() {
|
||||
@Override
|
||||
public String generateIdTableName(String baseName) {
|
||||
final String name = super.generateIdTableName( baseName );
|
||||
return name.length() > 30 ? name.substring( 0, 30 ) : name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTemporaryTables() {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public String getCreateIdTableCommand() {
|
||||
return "create global temporary table";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateTemporaryTableName(String baseTableName) {
|
||||
final String name = super.generateTemporaryTableName( baseTableName );
|
||||
return name.length() > 30 ? name.substring( 0, 30 ) : name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateTemporaryTableString() {
|
||||
return "create global temporary table";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateTemporaryTablePostfix() {
|
||||
return "on commit delete rows";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dropTemporaryTableAfterUse() {
|
||||
return false;
|
||||
@Override
|
||||
public String getCreateIdTableStatementOptions() {
|
||||
return "on commit delete rows";
|
||||
}
|
||||
},
|
||||
AfterUseAction.CLEAN
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -37,8 +37,10 @@
|
||||
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
||||
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
||||
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
||||
import org.hibernate.hql.spi.GlobalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.IdTableSupportStandardImpl;
|
||||
import org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.local.AfterUseAction;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
@ -355,33 +357,26 @@ public boolean supportsCommentOn() {
|
||||
|
||||
@Override
|
||||
public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() {
|
||||
return new GlobalTemporaryTableBulkIdStrategy();
|
||||
}
|
||||
return new GlobalTemporaryTableBulkIdStrategy(
|
||||
new IdTableSupportStandardImpl() {
|
||||
@Override
|
||||
public String generateIdTableName(String baseName) {
|
||||
final String name = super.generateIdTableName( baseName );
|
||||
return name.length() > 30 ? name.substring( 0, 30 ) : name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTemporaryTables() {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public String getCreateIdTableCommand() {
|
||||
return "create global temporary table";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateTemporaryTableName(String baseTableName) {
|
||||
final String name = super.generateTemporaryTableName( baseTableName );
|
||||
return name.length() > 30 ? name.substring( 1, 30 ) : name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateTemporaryTableString() {
|
||||
return "create global temporary table";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateTemporaryTablePostfix() {
|
||||
return "on commit delete rows";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dropTemporaryTableAfterUse() {
|
||||
return false;
|
||||
@Override
|
||||
public String getCreateIdTableStatementOptions() {
|
||||
return "on commit delete rows";
|
||||
}
|
||||
},
|
||||
AfterUseAction.CLEAN
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -31,6 +31,7 @@
|
||||
import org.hibernate.JDBCException;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.PessimisticLockException;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.function.NoArgSQLFunction;
|
||||
import org.hibernate.dialect.function.PositionSubstringFunction;
|
||||
@ -45,6 +46,10 @@
|
||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
||||
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
||||
import org.hibernate.hql.spi.id.IdTableSupportStandardImpl;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.local.AfterUseAction;
|
||||
import org.hibernate.hql.spi.id.local.LocalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.id.SequenceGenerator;
|
||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||
import org.hibernate.procedure.internal.PostgresCallableStatementSupport;
|
||||
@ -366,18 +371,22 @@ public boolean supportsCommentOn() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTemporaryTables() {
|
||||
return true;
|
||||
}
|
||||
public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() {
|
||||
return new LocalTemporaryTableBulkIdStrategy(
|
||||
new IdTableSupportStandardImpl() {
|
||||
@Override
|
||||
public String getCreateIdTableCommand() {
|
||||
return "create temporary table";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateTemporaryTableString() {
|
||||
return "create temporary table";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateTemporaryTablePostfix() {
|
||||
return "on commit drop";
|
||||
@Override
|
||||
public String getCreateIdTableStatementOptions() {
|
||||
return "on commit drop";
|
||||
}
|
||||
},
|
||||
AfterUseAction.CLEAN,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -30,6 +30,11 @@
|
||||
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
||||
import org.hibernate.hql.spi.id.IdTableSupportStandardImpl;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.local.AfterUseAction;
|
||||
import org.hibernate.hql.spi.id.local.LocalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.sql.CaseFragment;
|
||||
import org.hibernate.sql.DecodeCaseFragment;
|
||||
@ -220,18 +225,21 @@ public CaseFragment createCaseFragment() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTemporaryTables() {
|
||||
return true;
|
||||
}
|
||||
public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() {
|
||||
return new LocalTemporaryTableBulkIdStrategy(
|
||||
new IdTableSupportStandardImpl() {
|
||||
@Override
|
||||
public String generateIdTableName(String baseName) {
|
||||
return "temp." + super.generateIdTableName( baseName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateTemporaryTablePostfix() {
|
||||
return "ignore rollback";
|
||||
@Override
|
||||
public String getCreateIdTableStatementOptions() {
|
||||
return "ignore rollback";
|
||||
}
|
||||
},
|
||||
AfterUseAction.DROP,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateTemporaryTableName(String baseTableName) {
|
||||
return "temp." + super.generateTemporaryTableName( baseTableName );
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -108,11 +108,6 @@ public String getIdentityInsertString() {
|
||||
return "null";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDropTemporaryTableString() {
|
||||
return "drop temporary table";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsExpectedLobUsagePattern() {
|
||||
return true;
|
||||
|
@ -28,6 +28,11 @@
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
||||
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
||||
import org.hibernate.hql.spi.id.IdTableSupport;
|
||||
import org.hibernate.hql.spi.id.IdTableSupportStandardImpl;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.local.AfterUseAction;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
||||
/**
|
||||
@ -36,7 +41,7 @@
|
||||
*
|
||||
* @author Jay Nance
|
||||
*/
|
||||
public class TeradataDialect extends Dialect {
|
||||
public class TeradataDialect extends Dialect implements IdTableSupport {
|
||||
|
||||
private static final int PARAM_LIST_SIZE_LIMIT = 1024;
|
||||
|
||||
@ -133,24 +138,29 @@ public String getAddColumnString() {
|
||||
return "Add Column";
|
||||
}
|
||||
|
||||
public boolean supportsTemporaryTables() {
|
||||
return true;
|
||||
@Override
|
||||
public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() {
|
||||
return new GlobalTemporaryTableBulkIdStrategy( this, AfterUseAction.CLEAN );
|
||||
}
|
||||
|
||||
public String getCreateTemporaryTableString() {
|
||||
@Override
|
||||
public String generateIdTableName(String baseName) {
|
||||
return IdTableSupportStandardImpl.INSTANCE.generateIdTableName( baseName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateIdTableCommand() {
|
||||
return "create global temporary table";
|
||||
}
|
||||
|
||||
public String getCreateTemporaryTablePostfix() {
|
||||
@Override
|
||||
public String getCreateIdTableStatementOptions() {
|
||||
return " on commit preserve rows";
|
||||
}
|
||||
|
||||
public Boolean performTemporaryTableDDLInIsolation() {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
public boolean dropTemporaryTableAfterUse() {
|
||||
return false;
|
||||
@Override
|
||||
public String getDropIdTableCommand() {
|
||||
return "drop table";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -39,6 +39,11 @@
|
||||
import org.hibernate.dialect.lock.UpdateLockingStrategy;
|
||||
import org.hibernate.dialect.pagination.FirstLimitHandler;
|
||||
import org.hibernate.dialect.pagination.LimitHandler;
|
||||
import org.hibernate.hql.spi.id.IdTableSupportStandardImpl;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.local.AfterUseAction;
|
||||
import org.hibernate.hql.spi.id.local.LocalTemporaryTableBulkIdStrategy;
|
||||
import org.hibernate.persister.entity.Lockable;
|
||||
import org.hibernate.sql.JoinFragment;
|
||||
import org.hibernate.sql.OracleJoinFragment;
|
||||
@ -222,24 +227,27 @@ public boolean isCurrentTimestampSelectStringCallable() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTemporaryTables() {
|
||||
return true;
|
||||
}
|
||||
public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() {
|
||||
return new GlobalTemporaryTableBulkIdStrategy(
|
||||
new IdTableSupportStandardImpl() {
|
||||
@Override
|
||||
public String generateIdTableName(String baseName) {
|
||||
final String name = super.generateIdTableName( baseName );
|
||||
return name.length() > 30 ? name.substring( 1, 30 ) : name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateTemporaryTableName(String baseTableName) {
|
||||
final String name = super.generateTemporaryTableName( baseTableName );
|
||||
return name.length() > 30 ? name.substring( 1, 30 ) : name;
|
||||
}
|
||||
@Override
|
||||
public String getCreateIdTableCommand() {
|
||||
return "create global temporary table";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateTemporaryTableString() {
|
||||
return "create global temporary table";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateTemporaryTablePostfix() {
|
||||
return "on commit delete rows";
|
||||
@Override
|
||||
public String getCreateIdTableStatementOptions() {
|
||||
return "on commit delete rows";
|
||||
}
|
||||
},
|
||||
AfterUseAction.CLEAN
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -29,7 +29,7 @@
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.event.spi.EventSource;
|
||||
import org.hibernate.hql.internal.ast.HqlSqlWalker;
|
||||
import org.hibernate.hql.spi.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
|
||||
/**
|
||||
* Implementation of MultiTableDeleteExecutor.
|
||||
|
@ -30,7 +30,7 @@
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.event.spi.EventSource;
|
||||
import org.hibernate.hql.internal.ast.HqlSqlWalker;
|
||||
import org.hibernate.hql.spi.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
|
||||
/**
|
||||
* Implementation of MultiTableUpdateExecutor.
|
||||
|
@ -1,165 +0,0 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
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.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.hql.internal.ast.HqlSqlWalker;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.persister.entity.Queryable;
|
||||
|
||||
/**
|
||||
* Strategy based on ANSI SQL's definition of a "global temporary table".
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class GlobalTemporaryTableBulkIdStrategy implements MultiTableBulkIdStrategy {
|
||||
public static final String CLEAN_UP_ID_TABLES = "hibernate.hql.bulk_id_strategy.global_temporary.clean_up";
|
||||
|
||||
public static final String SHORT_NAME = "global_temporary";
|
||||
|
||||
private boolean cleanUpTables;
|
||||
private List<String> tableCleanUpDdl;
|
||||
|
||||
@Override
|
||||
public void prepare(
|
||||
JdbcServices jdbcServices,
|
||||
JdbcConnectionAccess connectionAccess,
|
||||
MetadataImplementor metadata) {
|
||||
final ConfigurationService configService = metadata.getMetadataBuildingOptions()
|
||||
.getServiceRegistry()
|
||||
.getService( ConfigurationService.class );
|
||||
this.cleanUpTables = configService.getSetting(
|
||||
CLEAN_UP_ID_TABLES,
|
||||
StandardConverters.BOOLEAN,
|
||||
false
|
||||
);
|
||||
|
||||
final List<Table> idTableDefinitions = new ArrayList<Table>();
|
||||
|
||||
for ( PersistentClass entityBinding : metadata.getEntityBindings() ) {
|
||||
if ( !MultiTableBulkIdHelper.INSTANCE.needsIdTable( entityBinding ) ) {
|
||||
continue;
|
||||
}
|
||||
final Table idTableDefinition = generateIdTableDefinition( entityBinding, metadata );
|
||||
idTableDefinitions.add( idTableDefinition );
|
||||
|
||||
if ( cleanUpTables ) {
|
||||
if ( tableCleanUpDdl == null ) {
|
||||
tableCleanUpDdl = new ArrayList<String>();
|
||||
}
|
||||
tableCleanUpDdl.add( idTableDefinition.sqlDropString( jdbcServices.getDialect(), null, null ) );
|
||||
}
|
||||
}
|
||||
|
||||
// we export them all at once to better reuse JDBC resources
|
||||
exportTableDefinitions( idTableDefinitions, jdbcServices, connectionAccess, metadata );
|
||||
}
|
||||
|
||||
protected Table generateIdTableDefinition(PersistentClass entityMapping, MetadataImplementor metadata) {
|
||||
return MultiTableBulkIdHelper.INSTANCE.generateIdTableDefinition(
|
||||
entityMapping,
|
||||
null,
|
||||
null,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
protected void exportTableDefinitions(
|
||||
List<Table> idTableDefinitions,
|
||||
JdbcServices jdbcServices,
|
||||
JdbcConnectionAccess connectionAccess,
|
||||
MetadataImplementor metadata) {
|
||||
MultiTableBulkIdHelper.INSTANCE.exportTableDefinitions(
|
||||
idTableDefinitions,
|
||||
jdbcServices,
|
||||
connectionAccess,
|
||||
metadata
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release(
|
||||
JdbcServices jdbcServices,
|
||||
JdbcConnectionAccess connectionAccess) {
|
||||
if ( ! cleanUpTables ) {
|
||||
return;
|
||||
}
|
||||
|
||||
MultiTableBulkIdHelper.INSTANCE.cleanupTableDefinitions( jdbcServices, connectionAccess, tableCleanUpDdl );
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateHandler buildUpdateHandler(
|
||||
SessionFactoryImplementor factory, HqlSqlWalker walker) {
|
||||
return new TableBasedUpdateHandlerImpl( factory, walker ) {
|
||||
@Override
|
||||
protected void releaseFromUse(Queryable persister, SessionImplementor session) {
|
||||
// clean up our id-table rows
|
||||
cleanUpRows( determineIdTableName( persister ), session );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void cleanUpRows(String tableName, SessionImplementor session) {
|
||||
final String sql = "delete from " + tableName;
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
ps = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql, false );
|
||||
session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( ps );
|
||||
}
|
||||
finally {
|
||||
if ( ps != null ) {
|
||||
try {
|
||||
session.getTransactionCoordinator().getJdbcCoordinator().release( ps );
|
||||
}
|
||||
catch( Throwable ignore ) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeleteHandler buildDeleteHandler(
|
||||
SessionFactoryImplementor factory, HqlSqlWalker walker) {
|
||||
return new TableBasedDeleteHandlerImpl( factory, walker ) {
|
||||
@Override
|
||||
protected void releaseFromUse(Queryable persister, SessionImplementor session) {
|
||||
// clean up our id-table rows
|
||||
cleanUpRows( determineIdTableName( persister ), session );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,259 +0,0 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.JDBCException;
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
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.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.hql.internal.ast.HqlSqlWalker;
|
||||
import org.hibernate.internal.AbstractSessionImpl;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.persister.entity.Queryable;
|
||||
import org.hibernate.sql.SelectValues;
|
||||
import org.hibernate.type.UUIDCharType;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* This is a strategy that mimics temporary tables for databases which do not support
|
||||
* temporary tables. It follows a pattern similar to the ANSI SQL definition of global
|
||||
* temporary table using a "session id" column to segment rows from the various sessions.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class PersistentTableBulkIdStrategy implements MultiTableBulkIdStrategy {
|
||||
private static final CoreMessageLogger log = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class,
|
||||
PersistentTableBulkIdStrategy.class.getName()
|
||||
);
|
||||
|
||||
public static final String SHORT_NAME = "persistent";
|
||||
|
||||
public static final String CLEAN_UP_ID_TABLES = "hibernate.hql.bulk_id_strategy.persistent.clean_up";
|
||||
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 String catalog;
|
||||
private String schema;
|
||||
private boolean cleanUpTables;
|
||||
private List<String> tableCleanUpDdl;
|
||||
|
||||
/**
|
||||
* Creates the tables for all the entities that might need it
|
||||
*
|
||||
* @param jdbcServices The JdbcService object
|
||||
* @param connectionAccess Access to the JDBC Connection
|
||||
* @param metadata Access to the O/RM mapping information
|
||||
*/
|
||||
@Override
|
||||
public void prepare(
|
||||
JdbcServices jdbcServices,
|
||||
JdbcConnectionAccess connectionAccess,
|
||||
MetadataImplementor metadata) {
|
||||
final ConfigurationService configService = metadata.getMetadataBuildingOptions()
|
||||
.getServiceRegistry()
|
||||
.getService( ConfigurationService.class );
|
||||
this.catalog = configService.getSetting(
|
||||
CATALOG,
|
||||
StandardConverters.STRING,
|
||||
configService.getSetting( AvailableSettings.DEFAULT_CATALOG, StandardConverters.STRING )
|
||||
);
|
||||
this.schema = configService.getSetting(
|
||||
SCHEMA,
|
||||
StandardConverters.STRING,
|
||||
configService.getSetting( AvailableSettings.DEFAULT_SCHEMA, StandardConverters.STRING )
|
||||
);
|
||||
this.cleanUpTables = configService.getSetting(
|
||||
CLEAN_UP_ID_TABLES,
|
||||
StandardConverters.BOOLEAN,
|
||||
false
|
||||
);
|
||||
|
||||
final List<Table> idTableDefinitions = new ArrayList<Table>();
|
||||
|
||||
for ( PersistentClass entityBinding : metadata.getEntityBindings() ) {
|
||||
if ( !MultiTableBulkIdHelper.INSTANCE.needsIdTable( entityBinding ) ) {
|
||||
continue;
|
||||
}
|
||||
final Table idTableDefinition = generateIdTableDefinition( entityBinding, metadata );
|
||||
idTableDefinitions.add( idTableDefinition );
|
||||
|
||||
if ( cleanUpTables ) {
|
||||
if ( tableCleanUpDdl == null ) {
|
||||
tableCleanUpDdl = new ArrayList<String>();
|
||||
}
|
||||
tableCleanUpDdl.add( idTableDefinition.sqlDropString( jdbcServices.getDialect(), null, null ) );
|
||||
}
|
||||
}
|
||||
|
||||
// we export them all at once to better reuse JDBC resources
|
||||
exportTableDefinitions( idTableDefinitions, jdbcServices, connectionAccess, metadata );
|
||||
}
|
||||
|
||||
protected Table generateIdTableDefinition(PersistentClass entityMapping, MetadataImplementor metadata) {
|
||||
return MultiTableBulkIdHelper.INSTANCE.generateIdTableDefinition(
|
||||
entityMapping,
|
||||
catalog,
|
||||
schema,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
protected void exportTableDefinitions(
|
||||
List<Table> idTableDefinitions,
|
||||
JdbcServices jdbcServices,
|
||||
JdbcConnectionAccess connectionAccess,
|
||||
MetadataImplementor metadata) {
|
||||
MultiTableBulkIdHelper.INSTANCE.exportTableDefinitions(
|
||||
idTableDefinitions,
|
||||
jdbcServices,
|
||||
connectionAccess,
|
||||
metadata
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release(JdbcServices jdbcServices, JdbcConnectionAccess connectionAccess) {
|
||||
if ( ! cleanUpTables ) {
|
||||
return;
|
||||
}
|
||||
|
||||
MultiTableBulkIdHelper.INSTANCE.cleanupTableDefinitions( jdbcServices, connectionAccess, tableCleanUpDdl );
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateHandler buildUpdateHandler(SessionFactoryImplementor factory, HqlSqlWalker walker) {
|
||||
return new TableBasedUpdateHandlerImpl( factory, walker, catalog, schema ) {
|
||||
@Override
|
||||
protected void addAnyExtraIdSelectValues(SelectValues selectClause) {
|
||||
selectClause.addParameter( Types.CHAR, 36 );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String generateIdSubselect(Queryable persister) {
|
||||
return super.generateIdSubselect( persister ) + " where hib_sess_id=?";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int handlePrependedParametersOnIdSelection(PreparedStatement ps, SessionImplementor session, int pos) throws SQLException {
|
||||
bindSessionIdentifier( ps, session, pos );
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleAddedParametersOnUpdate(PreparedStatement ps, SessionImplementor session, int position) throws SQLException {
|
||||
bindSessionIdentifier( ps, session, position );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void releaseFromUse(Queryable persister, SessionImplementor session) {
|
||||
// clean up our id-table rows
|
||||
cleanUpRows( determineIdTableName( persister ), session );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void bindSessionIdentifier(PreparedStatement ps, SessionImplementor session, int position) throws SQLException {
|
||||
if ( ! AbstractSessionImpl.class.isInstance( session ) ) {
|
||||
throw new HibernateException( "Only available on SessionImpl instances" );
|
||||
}
|
||||
UUIDCharType.INSTANCE.set( ps, ( (AbstractSessionImpl) session ).getSessionIdentifier(), position, session );
|
||||
}
|
||||
|
||||
private void cleanUpRows(String tableName, SessionImplementor session) {
|
||||
final String sql = "delete from " + tableName + " where hib_sess_id=?";
|
||||
try {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
ps = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql, false );
|
||||
bindSessionIdentifier( ps, session, 1 );
|
||||
session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( ps );
|
||||
}
|
||||
finally {
|
||||
if ( ps != null ) {
|
||||
try {
|
||||
session.getTransactionCoordinator().getJdbcCoordinator().release( ps );
|
||||
}
|
||||
catch( Throwable ignore ) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw convert( session.getFactory(), e, "Unable to clean up id table [" + tableName + "]", sql );
|
||||
}
|
||||
}
|
||||
|
||||
protected JDBCException convert(SessionFactoryImplementor factory, SQLException e, String message, String sql) {
|
||||
throw factory.getSQLExceptionHelper().convert( e, message, sql );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeleteHandler buildDeleteHandler(SessionFactoryImplementor factory, HqlSqlWalker walker) {
|
||||
return new TableBasedDeleteHandlerImpl( factory, walker, catalog, schema ) {
|
||||
@Override
|
||||
protected void addAnyExtraIdSelectValues(SelectValues selectClause) {
|
||||
selectClause.addParameter( Types.CHAR, 36 );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String generateIdSubselect(Queryable persister) {
|
||||
return super.generateIdSubselect( persister ) + " where hib_sess_id=?";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int handlePrependedParametersOnIdSelection(PreparedStatement ps, SessionImplementor session, int pos) throws SQLException {
|
||||
bindSessionIdentifier( ps, session, pos );
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleAddedParametersOnDelete(PreparedStatement ps, SessionImplementor session) throws SQLException {
|
||||
bindSessionIdentifier( ps, session, 1 );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void releaseFromUse(Queryable persister, SessionImplementor session) {
|
||||
// clean up our id-table rows
|
||||
cleanUpRows( determineIdTableName( persister ), session );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi;
|
||||
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.hql.internal.ast.HqlSqlWalker;
|
||||
import org.hibernate.internal.log.DeprecationLogger;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*
|
||||
* @deprecated Use the more specific {@link org.hibernate.hql.spi.LocalTemporaryTableBulkIdStrategy} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public class TemporaryTableBulkIdStrategy extends LocalTemporaryTableBulkIdStrategy {
|
||||
public static final TemporaryTableBulkIdStrategy INSTANCE = new TemporaryTableBulkIdStrategy();
|
||||
|
||||
public static final String SHORT_NAME = "temporary";
|
||||
|
||||
@Override
|
||||
public void prepare(JdbcServices jdbcServices, JdbcConnectionAccess connectionAccess, MetadataImplementor metadata) {
|
||||
DeprecationLogger.DEPRECATION_LOGGER.logDeprecationOfTemporaryTableBulkIdStrategy();
|
||||
super.prepare( jdbcServices, connectionAccess, metadata );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release(JdbcServices jdbcServices, JdbcConnectionAccess connectionAccess) {
|
||||
super.release( jdbcServices, connectionAccess );
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateHandler buildUpdateHandler(SessionFactoryImplementor factory, HqlSqlWalker walker) {
|
||||
return super.buildUpdateHandler( factory, walker );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeleteHandler buildDeleteHandler(SessionFactoryImplementor factory, HqlSqlWalker walker) {
|
||||
return super.buildDeleteHandler( factory, walker );
|
||||
}
|
||||
}
|
@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi.id;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.boot.model.relational.QualifiedTableName;
|
||||
import org.hibernate.boot.spi.MetadataBuildingOptions;
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.persister.entity.Queryable;
|
||||
|
||||
/**
|
||||
* Convenience base class for MultiTableBulkIdStrategy implementations.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractMultiTableBulkIdStrategyImpl<TT extends IdTableInfo, CT extends AbstractMultiTableBulkIdStrategyImpl.PreparationContext>
|
||||
implements MultiTableBulkIdStrategy {
|
||||
|
||||
private final IdTableSupport idTableSupport;
|
||||
private Map<String,TT> idTableInfoMap = new HashMap<String, TT>();
|
||||
|
||||
public AbstractMultiTableBulkIdStrategyImpl(IdTableSupport idTableSupport) {
|
||||
this.idTableSupport = idTableSupport;
|
||||
}
|
||||
|
||||
public IdTableSupport getIdTableSupport() {
|
||||
return idTableSupport;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void prepare(
|
||||
JdbcServices jdbcServices,
|
||||
JdbcConnectionAccess connectionAccess,
|
||||
MetadataImplementor metadata,
|
||||
SessionFactoryOptions sessionFactoryOptions) {
|
||||
// build/get Table representation of the bulk-id tables - subclasses need hooks
|
||||
// for each:
|
||||
// handle DDL
|
||||
// build insert-select
|
||||
// build id-subselect
|
||||
|
||||
final CT context = buildPreparationContext();
|
||||
|
||||
initialize( metadata.getMetadataBuildingOptions(), sessionFactoryOptions );
|
||||
|
||||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
|
||||
for ( PersistentClass entityBinding : metadata.getEntityBindings() ) {
|
||||
if ( !IdTableHelper.INSTANCE.needsIdTable( entityBinding ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final String idTableName = jdbcEnvironment.getQualifiedObjectNameFormatter().format(
|
||||
determineIdTableName( jdbcEnvironment, entityBinding ),
|
||||
jdbcEnvironment.getDialect()
|
||||
);
|
||||
final Table idTable = new Table();
|
||||
idTable.setName( idTableName );
|
||||
idTable.setComment( "Used to hold id values for the " + entityBinding.getEntityName() + " entity" );
|
||||
|
||||
Iterator itr = entityBinding.getTable().getPrimaryKey().getColumnIterator();
|
||||
while( itr.hasNext() ) {
|
||||
Column column = (Column) itr.next();
|
||||
idTable.addColumn( column.clone() );
|
||||
}
|
||||
augmentIdTableDefinition( idTable );
|
||||
|
||||
final TT idTableInfo = buildIdTableInfo( entityBinding, idTable, jdbcServices, metadata, context );
|
||||
idTableInfoMap.put( entityBinding.getEntityName(), idTableInfo );
|
||||
}
|
||||
|
||||
finishPreparation( jdbcServices, connectionAccess, metadata, context );
|
||||
}
|
||||
|
||||
protected CT buildPreparationContext() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configure ourselves. By default, nothing to do; here totally for subclass hook-in
|
||||
*
|
||||
* @param buildingOptions Access to user-defined Metadata building options
|
||||
* @param sessionFactoryOptions
|
||||
*/
|
||||
protected void initialize(MetadataBuildingOptions buildingOptions, SessionFactoryOptions sessionFactoryOptions) {
|
||||
// by default nothing to do
|
||||
}
|
||||
|
||||
protected QualifiedTableName determineIdTableName(JdbcEnvironment jdbcEnvironment, PersistentClass entityBinding) {
|
||||
final String entityPrimaryTableName = entityBinding.getTable().getName();
|
||||
final String idTableName = getIdTableSupport().generateIdTableName( entityPrimaryTableName );
|
||||
|
||||
// by default no explicit catalog/schema
|
||||
return new QualifiedTableName(
|
||||
null,
|
||||
null,
|
||||
jdbcEnvironment.getIdentifierHelper().toIdentifier( idTableName )
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
protected void augmentIdTableDefinition(Table idTable) {
|
||||
// by default nothing to do
|
||||
}
|
||||
|
||||
protected abstract TT buildIdTableInfo(
|
||||
PersistentClass entityBinding,
|
||||
Table idTable,
|
||||
JdbcServices jdbcServices,
|
||||
MetadataImplementor metadata,
|
||||
CT context);
|
||||
|
||||
|
||||
protected String buildIdTableCreateStatement(Table idTable, JdbcServices jdbcServices, MetadataImplementor metadata) {
|
||||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
final Dialect dialect = jdbcEnvironment.getDialect();
|
||||
|
||||
StringBuilder buffer = new StringBuilder( getIdTableSupport().getCreateIdTableCommand() )
|
||||
.append( ' ' )
|
||||
.append( jdbcEnvironment.getQualifiedObjectNameFormatter().format( idTable.getQualifiedTableName(), dialect ) )
|
||||
.append( " (" );
|
||||
|
||||
Iterator itr = idTable.getColumnIterator();
|
||||
while ( itr.hasNext() ) {
|
||||
final Column column = (Column) itr.next();
|
||||
buffer.append( column.getQuotedName( dialect ) ).append( ' ' );
|
||||
buffer.append( column.getSqlType( dialect, metadata ) );
|
||||
if ( column.isNullable() ) {
|
||||
buffer.append( dialect.getNullColumnString() );
|
||||
}
|
||||
else {
|
||||
buffer.append( " not null" );
|
||||
}
|
||||
if ( itr.hasNext() ) {
|
||||
buffer.append( ", " );
|
||||
}
|
||||
}
|
||||
|
||||
buffer.append( ") " );
|
||||
if ( getIdTableSupport().getCreateIdTableStatementOptions() != null ) {
|
||||
buffer.append( getIdTableSupport().getCreateIdTableStatementOptions() );
|
||||
}
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
protected String buildIdTableDropStatement(Table idTable, JdbcServices jdbcServices) {
|
||||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
final Dialect dialect = jdbcEnvironment.getDialect();
|
||||
|
||||
return getIdTableSupport().getDropIdTableCommand() + " "
|
||||
+ jdbcEnvironment.getQualifiedObjectNameFormatter().format( idTable.getQualifiedTableName(), dialect );
|
||||
}
|
||||
|
||||
protected void finishPreparation(
|
||||
JdbcServices jdbcServices,
|
||||
JdbcConnectionAccess connectionAccess,
|
||||
MetadataImplementor metadata,
|
||||
CT context) {
|
||||
}
|
||||
|
||||
protected TT getIdTableInfo(Queryable targetedPersister) {
|
||||
return getIdTableInfo( targetedPersister.getEntityName() );
|
||||
}
|
||||
|
||||
protected TT getIdTableInfo(String entityName) {
|
||||
TT tableInfo = idTableInfoMap.get( entityName );
|
||||
if ( tableInfo == null ) {
|
||||
throw new QueryException( "Entity does not have an id table for multi-table handling : " + entityName );
|
||||
}
|
||||
return tableInfo;
|
||||
}
|
||||
|
||||
public static interface PreparationContext {
|
||||
}
|
||||
|
||||
}
|
@ -21,7 +21,7 @@
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi;
|
||||
package org.hibernate.hql.spi.id;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collections;
|
||||
@ -34,7 +34,6 @@
|
||||
import org.hibernate.hql.internal.ast.HqlSqlWalker;
|
||||
import org.hibernate.hql.internal.ast.SqlGenerator;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.param.ParameterSpecification;
|
||||
import org.hibernate.persister.entity.Queryable;
|
||||
import org.hibernate.sql.InsertSelect;
|
||||
@ -45,24 +44,27 @@
|
||||
import antlr.collections.AST;
|
||||
|
||||
/**
|
||||
* Convenience base class for {@link MultiTableBulkIdStrategy.UpdateHandler}
|
||||
* and {@link MultiTableBulkIdStrategy.DeleteHandler} implementations through
|
||||
* {@link TableBasedUpdateHandlerImpl} and {@link TableBasedDeleteHandlerImpl} respectively.
|
||||
* <p/>
|
||||
* Mainly supports common activities like:<ul>
|
||||
* <li>processing the original {@code WHERE} clause (if one) - {@link #processWhereClause}</li>
|
||||
* <li>generating the proper {@code SELECT} clause for the id-table insert - {@link #generateIdInsertSelect}</li>
|
||||
* <li>generating the sub-select from the id-table - {@link #generateIdSubselect}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractTableBasedBulkIdHandler {
|
||||
private final SessionFactoryImplementor sessionFactory;
|
||||
private final HqlSqlWalker walker;
|
||||
|
||||
private final String catalog;
|
||||
private final String schema;
|
||||
|
||||
public AbstractTableBasedBulkIdHandler(
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
HqlSqlWalker walker,
|
||||
String catalog,
|
||||
String schema) {
|
||||
HqlSqlWalker walker) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
this.walker = walker;
|
||||
this.catalog = catalog;
|
||||
this.schema = schema;
|
||||
}
|
||||
|
||||
protected SessionFactoryImplementor factory() {
|
||||
@ -73,6 +75,8 @@ protected HqlSqlWalker walker() {
|
||||
return walker;
|
||||
}
|
||||
|
||||
public abstract Queryable getTargetedQueryable();
|
||||
|
||||
protected JDBCException convert(SQLException e, String message, String sql) {
|
||||
throw factory().getSQLExceptionHelper().convert( e, message, sql );
|
||||
}
|
||||
@ -101,11 +105,18 @@ public List<ParameterSpecification> getIdSelectParameterSpecifications() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interprets the {@code WHERE} clause from the user-defined update/delete query
|
||||
*
|
||||
* @param whereClause The user-defined {@code WHERE} clause
|
||||
*
|
||||
* @return The bulk-id-ready {@code WHERE} clause representation
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected ProcessedWhereClause processWhereClause(AST whereClause) {
|
||||
if ( whereClause.getNumberOfChildren() != 0 ) {
|
||||
// If a where clause was specified in the update/delete query, use it to limit the
|
||||
// returned ids here...
|
||||
// ids that will be returned and inserted into the id table...
|
||||
try {
|
||||
SqlGenerator sqlGenerator = new SqlGenerator( sessionFactory );
|
||||
sqlGenerator.whereClause( whereClause );
|
||||
@ -123,16 +134,33 @@ protected ProcessedWhereClause processWhereClause(AST whereClause) {
|
||||
}
|
||||
}
|
||||
|
||||
protected String generateIdInsertSelect(Queryable persister, String tableAlias, ProcessedWhereClause whereClause) {
|
||||
/**
|
||||
* Generate the {@code INSERT}-{@code SELECT} statement for holding matching ids. This is the
|
||||
* {@code INSERT} used to populate the bulk-id table with ids matching the restrictions defined in the
|
||||
* original {@code WHERE} clause
|
||||
*
|
||||
* @param tableAlias The table alias to use for the entity
|
||||
* @param whereClause The processed representation for the user-defined {@code WHERE} clause.
|
||||
*
|
||||
* @return The {@code INSERT}-{@code SELECT} for populating the bulk-id table.
|
||||
*/
|
||||
protected String generateIdInsertSelect(
|
||||
String tableAlias,
|
||||
IdTableInfo idTableInfo,
|
||||
ProcessedWhereClause whereClause) {
|
||||
|
||||
Select select = new Select( sessionFactory.getDialect() );
|
||||
SelectValues selectClause = new SelectValues( sessionFactory.getDialect() )
|
||||
.addColumns( tableAlias, persister.getIdentifierColumnNames(), persister.getIdentifierColumnNames() );
|
||||
SelectValues selectClause = new SelectValues( sessionFactory.getDialect() ).addColumns(
|
||||
tableAlias,
|
||||
getTargetedQueryable().getIdentifierColumnNames(),
|
||||
getTargetedQueryable().getIdentifierColumnNames()
|
||||
);
|
||||
addAnyExtraIdSelectValues( selectClause );
|
||||
select.setSelectClause( selectClause.render() );
|
||||
|
||||
String rootTableName = persister.getTableName();
|
||||
String fromJoinFragment = persister.fromJoinFragment( tableAlias, true, false );
|
||||
String whereJoinFragment = persister.whereJoinFragment( tableAlias, true, false );
|
||||
String rootTableName = getTargetedQueryable().getTableName();
|
||||
String fromJoinFragment = getTargetedQueryable().fromJoinFragment( tableAlias, true, false );
|
||||
String whereJoinFragment = getTargetedQueryable().whereJoinFragment( tableAlias, true, false );
|
||||
|
||||
select.setFromClause( rootTableName + ' ' + tableAlias + fromJoinFragment );
|
||||
|
||||
@ -155,24 +183,26 @@ protected String generateIdInsertSelect(Queryable persister, String tableAlias,
|
||||
|
||||
InsertSelect insert = new InsertSelect( sessionFactory.getDialect() );
|
||||
if ( sessionFactory.getSettings().isCommentsEnabled() ) {
|
||||
insert.setComment( "insert-select for " + persister.getEntityName() + " ids" );
|
||||
insert.setComment( "insert-select for " + getTargetedQueryable().getEntityName() + " ids" );
|
||||
}
|
||||
insert.setTableName( determineIdTableName( persister ) );
|
||||
insert.setTableName( idTableInfo.getQualifiedIdTableName() );
|
||||
insert.setSelect( select );
|
||||
return insert.toStatementString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used from {@link #generateIdInsertSelect} to allow subclasses to define any extra
|
||||
* values to be selected (and therefore stored into the bulk-id table). Used to store
|
||||
* session identifier, e.g.
|
||||
*
|
||||
* @param selectClause The SelectValues that defines the select clause of the insert statement.
|
||||
*/
|
||||
protected void addAnyExtraIdSelectValues(SelectValues selectClause) {
|
||||
}
|
||||
|
||||
protected String determineIdTableName(Queryable persister) {
|
||||
// todo : use the identifier/name qualifier service once we pull that over to master
|
||||
return Table.qualify( catalog, schema, persister.getTemporaryIdTableName() );
|
||||
}
|
||||
|
||||
protected String generateIdSubselect(Queryable persister) {
|
||||
protected String generateIdSubselect(Queryable persister, IdTableInfo idTableInfo) {
|
||||
return "select " + StringHelper.join( ", ", persister.getIdentifierColumnNames() ) +
|
||||
" from " + determineIdTableName( persister );
|
||||
" from " + idTableInfo.getQualifiedIdTableName();
|
||||
}
|
||||
|
||||
protected void prepareForUse(Queryable persister, SessionImplementor session) {
|
@ -21,7 +21,7 @@
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi;
|
||||
package org.hibernate.hql.spi.id;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
@ -29,15 +29,12 @@
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.JoinedSubclass;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.RootClass;
|
||||
import org.hibernate.mapping.Subclass;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.mapping.UnionSubclass;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
@ -45,15 +42,15 @@
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class MultiTableBulkIdHelper {
|
||||
private static final Logger log = Logger.getLogger( MultiTableBulkIdHelper.class );
|
||||
public class IdTableHelper {
|
||||
private static final Logger log = Logger.getLogger( IdTableHelper.class );
|
||||
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final MultiTableBulkIdHelper INSTANCE = new MultiTableBulkIdHelper();
|
||||
public static final IdTableHelper INSTANCE = new IdTableHelper();
|
||||
|
||||
private MultiTableBulkIdHelper() {
|
||||
private IdTableHelper() {
|
||||
}
|
||||
|
||||
public boolean needsIdTable(PersistentClass entityBinding) {
|
||||
@ -77,43 +74,10 @@ public boolean needsIdTable(PersistentClass entityBinding) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public Table generateIdTableDefinition(
|
||||
PersistentClass entityMapping,
|
||||
String catalog,
|
||||
String schema,
|
||||
boolean generateSessionIdColumn) {
|
||||
Table idTable = new Table( entityMapping.getTemporaryIdTableName() );
|
||||
idTable.setComment( "Used to hold id values for the " + entityMapping.getEntityName() + " class" );
|
||||
|
||||
if ( catalog != null ) {
|
||||
idTable.setCatalog( catalog );
|
||||
}
|
||||
if ( schema != null ) {
|
||||
idTable.setSchema( schema );
|
||||
}
|
||||
|
||||
Iterator itr = entityMapping.getTable().getPrimaryKey().getColumnIterator();
|
||||
while( itr.hasNext() ) {
|
||||
Column column = (Column) itr.next();
|
||||
idTable.addColumn( column.clone() );
|
||||
}
|
||||
|
||||
if ( generateSessionIdColumn ) {
|
||||
Column sessionIdColumn = new Column( "hib_sess_id" );
|
||||
sessionIdColumn.setSqlType( "CHAR(36)" );
|
||||
sessionIdColumn.setComment( "Used to hold the Hibernate Session identifier" );
|
||||
idTable.addColumn( sessionIdColumn );
|
||||
}
|
||||
|
||||
return idTable;
|
||||
}
|
||||
|
||||
protected void exportTableDefinitions(
|
||||
List<Table> idTableDefinitions,
|
||||
public void executeIdTableCreationStatements(
|
||||
List<String> creationStatements,
|
||||
JdbcServices jdbcServices,
|
||||
JdbcConnectionAccess connectionAccess,
|
||||
MetadataImplementor metadata) {
|
||||
JdbcConnectionAccess connectionAccess) {
|
||||
try {
|
||||
Connection connection;
|
||||
try {
|
||||
@ -128,15 +92,14 @@ protected void exportTableDefinitions(
|
||||
try {
|
||||
// TODO: session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().createStatement();
|
||||
Statement statement = connection.createStatement();
|
||||
for ( Table idTableDefinition : idTableDefinitions ) {
|
||||
for ( String creationStatement : creationStatements ) {
|
||||
try {
|
||||
final String sql = idTableDefinition.sqlCreateString( jdbcServices.getDialect(), metadata, null, null );
|
||||
jdbcServices.getSqlStatementLogger().logStatement( sql );
|
||||
jdbcServices.getSqlStatementLogger().logStatement( creationStatement );
|
||||
// TODO: ResultSetExtractor
|
||||
statement.execute( sql );
|
||||
statement.execute( creationStatement );
|
||||
}
|
||||
catch (SQLException e) {
|
||||
log.debugf( "Error attempting to export id-table [%s] : %s", idTableDefinition.getName(), e.getMessage() );
|
||||
log.debugf( "Error attempting to export id-table [%s] : %s", creationStatement, e.getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,11 +123,11 @@ protected void exportTableDefinitions(
|
||||
}
|
||||
}
|
||||
|
||||
public void cleanupTableDefinitions(
|
||||
public void executeIdTableDropStatements(
|
||||
String[] dropStatements,
|
||||
JdbcServices jdbcServices,
|
||||
JdbcConnectionAccess connectionAccess,
|
||||
List<String> tableCleanUpDdl) {
|
||||
if ( tableCleanUpDdl == null ) {
|
||||
JdbcConnectionAccess connectionAccess) {
|
||||
if ( dropStatements == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -175,10 +138,10 @@ public void cleanupTableDefinitions(
|
||||
// TODO: session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().createStatement();
|
||||
Statement statement = connection.createStatement();
|
||||
|
||||
for ( String cleanupDdl : tableCleanUpDdl ) {
|
||||
for ( String dropStatement : dropStatements ) {
|
||||
try {
|
||||
jdbcServices.getSqlStatementLogger().logStatement( cleanupDdl );
|
||||
statement.execute( cleanupDdl );
|
||||
jdbcServices.getSqlStatementLogger().logStatement( dropStatement );
|
||||
statement.execute( dropStatement );
|
||||
}
|
||||
catch (SQLException e) {
|
||||
log.debugf( "Error attempting to cleanup id-table : [%s]", e.getMessage() );
|
||||
@ -204,4 +167,5 @@ public void cleanupTableDefinitions(
|
||||
log.error( "Unable obtain JDBC Connection", e );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi.id;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface IdTableInfo {
|
||||
String getQualifiedIdTableName();
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi.id;
|
||||
|
||||
import org.hibernate.hql.spi.id.local.AfterUseAction;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface IdTableSupport {
|
||||
public String generateIdTableName(String baseName);
|
||||
public String getCreateIdTableCommand();
|
||||
public String getCreateIdTableStatementOptions();
|
||||
public String getDropIdTableCommand();
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi.id;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class IdTableSupportStandardImpl implements IdTableSupport {
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final IdTableSupportStandardImpl INSTANCE = new IdTableSupportStandardImpl();
|
||||
|
||||
@Override
|
||||
public String generateIdTableName(String baseName) {
|
||||
return "HT_" + baseName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateIdTableCommand() {
|
||||
return "create table";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateIdTableStatementOptions() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDropIdTableCommand() {
|
||||
return "drop table";
|
||||
}
|
||||
}
|
@ -21,9 +21,10 @@
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi;
|
||||
package org.hibernate.hql.spi.id;
|
||||
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.spi.QueryParameters;
|
||||
@ -43,12 +44,16 @@ public interface MultiTableBulkIdStrategy {
|
||||
* <li>Adding tables to the passed Mappings, to be picked by by "schema management tools"</li>
|
||||
* <li>Manually creating the tables immediately through the passed JDBC Connection access</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param jdbcServices The JdbcService object
|
||||
* @param jdbcServices The JdbcService object
|
||||
* @param connectionAccess Access to the JDBC Connection
|
||||
* @param metadata Access to the O/RM mapping information
|
||||
* @param sessionFactoryOptions
|
||||
*/
|
||||
public void prepare(JdbcServices jdbcServices, JdbcConnectionAccess connectionAccess, MetadataImplementor metadata);
|
||||
public void prepare(
|
||||
JdbcServices jdbcServices,
|
||||
JdbcConnectionAccess connectionAccess,
|
||||
MetadataImplementor metadata,
|
||||
SessionFactoryOptions sessionFactoryOptions);
|
||||
|
||||
/**
|
||||
* Release the strategy. Called as the SessionFactory is being shut down.
|
@ -21,7 +21,7 @@
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi;
|
||||
package org.hibernate.hql.spi.id;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
@ -58,16 +58,11 @@ public class TableBasedDeleteHandlerImpl
|
||||
private final List<ParameterSpecification> idSelectParameterSpecifications;
|
||||
private final List<String> deletes;
|
||||
|
||||
public TableBasedDeleteHandlerImpl(SessionFactoryImplementor factory, HqlSqlWalker walker) {
|
||||
this( factory, walker, null, null );
|
||||
}
|
||||
|
||||
public TableBasedDeleteHandlerImpl(
|
||||
SessionFactoryImplementor factory,
|
||||
HqlSqlWalker walker,
|
||||
String catalog,
|
||||
String schema) {
|
||||
super( factory, walker, catalog, schema );
|
||||
IdTableInfo idTableInfo) {
|
||||
super( factory, walker );
|
||||
|
||||
DeleteStatement deleteStatement = ( DeleteStatement ) walker.getAST();
|
||||
FromElement fromElement = deleteStatement.getFromClause().getFromElement();
|
||||
@ -77,10 +72,10 @@ public TableBasedDeleteHandlerImpl(
|
||||
|
||||
final ProcessedWhereClause processedWhereClause = processWhereClause( deleteStatement.getWhereClause() );
|
||||
this.idSelectParameterSpecifications = processedWhereClause.getIdSelectParameterSpecifications();
|
||||
this.idInsertSelect = generateIdInsertSelect( targetedPersister, bulkTargetAlias, processedWhereClause );
|
||||
this.idInsertSelect = generateIdInsertSelect( bulkTargetAlias, idTableInfo, processedWhereClause );
|
||||
log.tracev( "Generated ID-INSERT-SELECT SQL (multi-table delete) : {0}", idInsertSelect );
|
||||
|
||||
final String idSubselect = generateIdSubselect( targetedPersister );
|
||||
final String idSubselect = generateIdSubselect( targetedPersister, idTableInfo );
|
||||
deletes = new ArrayList<String>();
|
||||
|
||||
// If many-to-many, delete the FK row in the collection table.
|
@ -21,11 +21,12 @@
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi;
|
||||
package org.hibernate.hql.spi.id;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.spi.QueryParameters;
|
||||
@ -60,31 +61,27 @@ public class TableBasedUpdateHandlerImpl
|
||||
private final ParameterSpecification[][] assignmentParameterSpecifications;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public TableBasedUpdateHandlerImpl(SessionFactoryImplementor factory, HqlSqlWalker walker) {
|
||||
this( factory, walker, null, null );
|
||||
}
|
||||
|
||||
public TableBasedUpdateHandlerImpl(
|
||||
SessionFactoryImplementor factory,
|
||||
HqlSqlWalker walker,
|
||||
String catalog,
|
||||
String schema) {
|
||||
super( factory, walker, catalog, schema );
|
||||
IdTableInfo idTableInfo) {
|
||||
super( factory, walker );
|
||||
|
||||
UpdateStatement updateStatement = ( UpdateStatement ) walker.getAST();
|
||||
FromElement fromElement = updateStatement.getFromClause().getFromElement();
|
||||
|
||||
this.targetedPersister = fromElement.getQueryable();
|
||||
|
||||
final String bulkTargetAlias = fromElement.getTableAlias();
|
||||
|
||||
final ProcessedWhereClause processedWhereClause = processWhereClause( updateStatement.getWhereClause() );
|
||||
this.idSelectParameterSpecifications = processedWhereClause.getIdSelectParameterSpecifications();
|
||||
this.idInsertSelect = generateIdInsertSelect( targetedPersister, bulkTargetAlias, processedWhereClause );
|
||||
this.idInsertSelect = generateIdInsertSelect( bulkTargetAlias, idTableInfo, processedWhereClause );
|
||||
log.tracev( "Generated ID-INSERT-SELECT SQL (multi-table update) : {0}", idInsertSelect );
|
||||
|
||||
String[] tableNames = targetedPersister.getConstraintOrderedTableNameClosure();
|
||||
String[][] columnNames = targetedPersister.getContraintOrderedTableKeyColumnClosure();
|
||||
String idSubselect = generateIdSubselect( targetedPersister );
|
||||
String idSubselect = generateIdSubselect( targetedPersister, idTableInfo );
|
||||
|
||||
updates = new String[tableNames.length];
|
||||
assignmentParameterSpecifications = new ParameterSpecification[tableNames.length][];
|
||||
@ -103,9 +100,7 @@ public TableBasedUpdateHandlerImpl(
|
||||
affected = true;
|
||||
update.appendAssignmentFragment( assignmentSpecification.getSqlAssignmentFragment() );
|
||||
if ( assignmentSpecification.getParameters() != null ) {
|
||||
for ( int paramIndex = 0; paramIndex < assignmentSpecification.getParameters().length; paramIndex++ ) {
|
||||
parameterList.add( assignmentSpecification.getParameters()[paramIndex] );
|
||||
}
|
||||
Collections.addAll( parameterList, assignmentSpecification.getParameters() );
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi.id.global;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.spi.MetadataBuildingOptions;
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||
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.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.hql.internal.ast.HqlSqlWalker;
|
||||
import org.hibernate.hql.internal.ast.tree.DeleteStatement;
|
||||
import org.hibernate.hql.internal.ast.tree.FromElement;
|
||||
import org.hibernate.hql.internal.ast.tree.UpdateStatement;
|
||||
import org.hibernate.hql.spi.id.AbstractMultiTableBulkIdStrategyImpl;
|
||||
import org.hibernate.hql.spi.id.IdTableHelper;
|
||||
import org.hibernate.hql.spi.id.IdTableInfo;
|
||||
import org.hibernate.hql.spi.id.IdTableSupport;
|
||||
import org.hibernate.hql.spi.id.IdTableSupportStandardImpl;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.TableBasedDeleteHandlerImpl;
|
||||
import org.hibernate.hql.spi.id.TableBasedUpdateHandlerImpl;
|
||||
import org.hibernate.hql.spi.id.local.AfterUseAction;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.persister.entity.Queryable;
|
||||
|
||||
/**
|
||||
* Strategy based on ANSI SQL's definition of a "global temporary table".
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class GlobalTemporaryTableBulkIdStrategy
|
||||
extends AbstractMultiTableBulkIdStrategyImpl<IdTableInfoImpl,PreparationContextImpl>
|
||||
implements MultiTableBulkIdStrategy {
|
||||
public static final String DROP_ID_TABLES = "hibernate.hql.bulk_id_strategy.global_temporary.drop_tables";
|
||||
|
||||
public static final String SHORT_NAME = "global_temporary";
|
||||
|
||||
private final AfterUseAction afterUseAction;
|
||||
|
||||
private boolean dropIdTables;
|
||||
private String[] dropTableStatements;
|
||||
|
||||
public GlobalTemporaryTableBulkIdStrategy() {
|
||||
this( AfterUseAction.CLEAN );
|
||||
}
|
||||
|
||||
public GlobalTemporaryTableBulkIdStrategy(AfterUseAction afterUseAction) {
|
||||
this(
|
||||
new IdTableSupportStandardImpl() {
|
||||
@Override
|
||||
public String getCreateIdTableCommand() {
|
||||
return "create global temporary table";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDropIdTableCommand() {
|
||||
return super.getDropIdTableCommand();
|
||||
}
|
||||
},
|
||||
afterUseAction
|
||||
);
|
||||
}
|
||||
|
||||
public GlobalTemporaryTableBulkIdStrategy(IdTableSupport idTableSupport, AfterUseAction afterUseAction) {
|
||||
super( idTableSupport );
|
||||
this.afterUseAction = afterUseAction;
|
||||
if ( afterUseAction == AfterUseAction.DROP ) {
|
||||
throw new IllegalArgumentException( "DROP not supported as a after-use action for global temp table strategy" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PreparationContextImpl buildPreparationContext() {
|
||||
return new PreparationContextImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize(MetadataBuildingOptions buildingOptions, SessionFactoryOptions sessionFactoryOptions) {
|
||||
final StandardServiceRegistry serviceRegistry = buildingOptions.getServiceRegistry();
|
||||
final ConfigurationService configService = serviceRegistry.getService( ConfigurationService.class );
|
||||
this.dropIdTables = configService.getSetting(
|
||||
DROP_ID_TABLES,
|
||||
StandardConverters.BOOLEAN,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IdTableInfoImpl buildIdTableInfo(
|
||||
PersistentClass entityBinding,
|
||||
Table idTable,
|
||||
JdbcServices jdbcServices,
|
||||
MetadataImplementor metadata,
|
||||
PreparationContextImpl context) {
|
||||
context.creationStatements.add( buildIdTableCreateStatement( idTable, jdbcServices, metadata ) );
|
||||
if ( dropIdTables ) {
|
||||
context.dropStatements.add( buildIdTableDropStatement( idTable, jdbcServices ) );
|
||||
}
|
||||
|
||||
final String renderedName = jdbcServices.getJdbcEnvironment().getQualifiedObjectNameFormatter().format(
|
||||
idTable.getQualifiedTableName(),
|
||||
jdbcServices.getJdbcEnvironment().getDialect()
|
||||
);
|
||||
|
||||
return new IdTableInfoImpl( renderedName );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finishPreparation(
|
||||
JdbcServices jdbcServices,
|
||||
JdbcConnectionAccess connectionAccess,
|
||||
MetadataImplementor metadata,
|
||||
PreparationContextImpl context) {
|
||||
IdTableHelper.INSTANCE.executeIdTableCreationStatements(
|
||||
context.creationStatements,
|
||||
jdbcServices,
|
||||
connectionAccess
|
||||
);
|
||||
|
||||
this.dropTableStatements = dropIdTables
|
||||
? context.dropStatements.toArray( new String[ context.dropStatements.size() ] )
|
||||
: null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release(
|
||||
JdbcServices jdbcServices,
|
||||
JdbcConnectionAccess connectionAccess) {
|
||||
if ( ! dropIdTables ) {
|
||||
return;
|
||||
}
|
||||
|
||||
IdTableHelper.INSTANCE.executeIdTableDropStatements( dropTableStatements, jdbcServices, connectionAccess );
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateHandler buildUpdateHandler(SessionFactoryImplementor factory, HqlSqlWalker walker) {
|
||||
final UpdateStatement updateStatement = (UpdateStatement) walker.getAST();
|
||||
|
||||
final FromElement fromElement = updateStatement.getFromClause().getFromElement();
|
||||
final Queryable targetedPersister = fromElement.getQueryable();
|
||||
|
||||
return new TableBasedUpdateHandlerImpl( factory, walker, getIdTableInfo( targetedPersister ) ) {
|
||||
@Override
|
||||
protected void releaseFromUse(Queryable persister, SessionImplementor session) {
|
||||
if ( afterUseAction == AfterUseAction.NONE ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// clean up our id-table rows
|
||||
cleanUpRows( getIdTableInfo( persister ).getQualifiedIdTableName(), session );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void cleanUpRows(String tableName, SessionImplementor session) {
|
||||
final String sql = "delete from " + tableName;
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
ps = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql, false );
|
||||
session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( ps );
|
||||
}
|
||||
finally {
|
||||
if ( ps != null ) {
|
||||
try {
|
||||
session.getTransactionCoordinator().getJdbcCoordinator().release( ps );
|
||||
}
|
||||
catch( Throwable ignore ) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeleteHandler buildDeleteHandler(SessionFactoryImplementor factory, HqlSqlWalker walker) {
|
||||
final DeleteStatement updateStatement = (DeleteStatement) walker.getAST();
|
||||
|
||||
final FromElement fromElement = updateStatement.getFromClause().getFromElement();
|
||||
final Queryable targetedPersister = fromElement.getQueryable();
|
||||
|
||||
return new TableBasedDeleteHandlerImpl( factory, walker, getIdTableInfo( targetedPersister ) ) {
|
||||
@Override
|
||||
protected void releaseFromUse(Queryable persister, SessionImplementor session) {
|
||||
if ( afterUseAction == AfterUseAction.NONE ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// clean up our id-table rows
|
||||
cleanUpRows( getIdTableInfo( persister ).getQualifiedIdTableName(), session );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi.id.global;
|
||||
|
||||
import org.hibernate.hql.spi.id.IdTableInfo;
|
||||
|
||||
/**
|
||||
* IdTableInfo implementation specific to PersistentTableBulkIdStrategy
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
class IdTableInfoImpl implements IdTableInfo {
|
||||
private final String idTableName;
|
||||
|
||||
public IdTableInfoImpl(String idTableName) {
|
||||
this.idTableName = idTableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQualifiedIdTableName() {
|
||||
return idTableName;
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi.id.global;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.hql.spi.id.AbstractMultiTableBulkIdStrategyImpl;
|
||||
|
||||
/**
|
||||
* PreparationContext implementation for GlobalTemporaryTableBulkIdStrategy. Used to collect
|
||||
* create and drop statements
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
class PreparationContextImpl implements AbstractMultiTableBulkIdStrategyImpl.PreparationContext {
|
||||
List<String> creationStatements = new ArrayList<String>();
|
||||
List<String> dropStatements = new ArrayList<String>();
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi.id.local;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public enum AfterUseAction {
|
||||
CLEAN,
|
||||
DROP,
|
||||
NONE
|
||||
}
|
@ -21,129 +21,151 @@
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi;
|
||||
package org.hibernate.hql.spi.id.local;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLWarning;
|
||||
import java.sql.Statement;
|
||||
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.hql.internal.ast.HqlSqlWalker;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.jdbc.AbstractWork;
|
||||
import org.hibernate.persister.entity.Queryable;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* Strategy based on ANSI SQL's definition of a "local temporary table" (local to each db session).
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class LocalTemporaryTableBulkIdStrategy implements MultiTableBulkIdStrategy {
|
||||
public static final LocalTemporaryTableBulkIdStrategy INSTANCE = new LocalTemporaryTableBulkIdStrategy();
|
||||
public class Helper {
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final Helper INSTANCE = new Helper();
|
||||
|
||||
public static final String SHORT_NAME = "temporary";
|
||||
private static final CoreMessageLogger log = CoreLogging.messageLogger( Helper.class );
|
||||
|
||||
private static final CoreMessageLogger log = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class,
|
||||
LocalTemporaryTableBulkIdStrategy.class.getName()
|
||||
);
|
||||
|
||||
@Override
|
||||
public void prepare(JdbcServices jdbcServices, JdbcConnectionAccess connectionAccess, MetadataImplementor metadata) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release(JdbcServices jdbcServices, JdbcConnectionAccess connectionAccess) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateHandler buildUpdateHandler(SessionFactoryImplementor factory, HqlSqlWalker walker) {
|
||||
return new TableBasedUpdateHandlerImpl( factory, walker ) {
|
||||
@Override
|
||||
protected void prepareForUse(Queryable persister, SessionImplementor session) {
|
||||
createTempTable( persister, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void releaseFromUse(Queryable persister, SessionImplementor session) {
|
||||
releaseTempTable( persister, session );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeleteHandler buildDeleteHandler(SessionFactoryImplementor factory, HqlSqlWalker walker) {
|
||||
return new TableBasedDeleteHandlerImpl( factory, walker ) {
|
||||
@Override
|
||||
protected void prepareForUse(Queryable persister, SessionImplementor session) {
|
||||
createTempTable( persister, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void releaseFromUse(Queryable persister, SessionImplementor session) {
|
||||
releaseTempTable( persister, session );
|
||||
}
|
||||
};
|
||||
private Helper() {
|
||||
}
|
||||
|
||||
|
||||
protected void createTempTable(Queryable persister, SessionImplementor session) {
|
||||
public void createTempTable(
|
||||
IdTableInfoImpl idTableInfo,
|
||||
TempTableDdlTransactionHandling ddlTransactionHandling,
|
||||
SessionImplementor session) {
|
||||
// Don't really know all the codes required to adequately decipher returned jdbc exceptions here.
|
||||
// simply allow the failure to be eaten and the subsequent insert-selects/deletes should fail
|
||||
TemporaryTableCreationWork work = new TemporaryTableCreationWork( persister );
|
||||
if ( shouldIsolateTemporaryTableDDL( session ) ) {
|
||||
session.getTransactionCoordinator()
|
||||
.getTransaction()
|
||||
.createIsolationDelegate()
|
||||
.delegateWork( work, shouldTransactIsolatedTemporaryTableDDL( session ) );
|
||||
}
|
||||
else {
|
||||
TemporaryTableCreationWork work = new TemporaryTableCreationWork( idTableInfo, session.getFactory() );
|
||||
|
||||
if ( ddlTransactionHandling == TempTableDdlTransactionHandling.NONE ) {
|
||||
final Connection connection = session.getTransactionCoordinator()
|
||||
.getJdbcCoordinator()
|
||||
.getLogicalConnection()
|
||||
.getConnection();
|
||||
|
||||
work.execute( connection );
|
||||
|
||||
session.getTransactionCoordinator()
|
||||
.getJdbcCoordinator()
|
||||
.afterStatementExecution();
|
||||
}
|
||||
else {
|
||||
session.getTransactionCoordinator()
|
||||
.getTransaction()
|
||||
.createIsolationDelegate()
|
||||
.delegateWork( work, ddlTransactionHandling == TempTableDdlTransactionHandling.ISOLATE_AND_TRANSACT );
|
||||
}
|
||||
}
|
||||
|
||||
protected void releaseTempTable(Queryable persister, SessionImplementor session) {
|
||||
if ( session.getFactory().getDialect().dropTemporaryTableAfterUse() ) {
|
||||
TemporaryTableDropWork work = new TemporaryTableDropWork( persister, session );
|
||||
if ( shouldIsolateTemporaryTableDDL( session ) ) {
|
||||
session.getTransactionCoordinator()
|
||||
.getTransaction()
|
||||
.createIsolationDelegate()
|
||||
.delegateWork( work, shouldTransactIsolatedTemporaryTableDDL( session ) );
|
||||
private static class TemporaryTableCreationWork extends AbstractWork {
|
||||
private final IdTableInfoImpl idTableInfo;
|
||||
private final SessionFactoryImplementor factory;
|
||||
|
||||
private TemporaryTableCreationWork(IdTableInfoImpl idTableInfo, SessionFactoryImplementor factory) {
|
||||
this.idTableInfo = idTableInfo;
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Connection connection) {
|
||||
try {
|
||||
Statement statement = connection.createStatement();
|
||||
try {
|
||||
statement.executeUpdate( idTableInfo.getIdTableCreationStatement() );
|
||||
factory.getServiceRegistry()
|
||||
.getService( JdbcServices.class )
|
||||
.getSqlExceptionHelper()
|
||||
.handleAndClearWarnings( statement, WARNING_HANDLER );
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
statement.close();
|
||||
}
|
||||
catch( Throwable ignore ) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
catch( Exception e ) {
|
||||
log.debug( "unable to create temporary id table [" + e.getMessage() + "]" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static SqlExceptionHelper.WarningHandler WARNING_HANDLER = new SqlExceptionHelper.WarningHandlerLoggingSupport() {
|
||||
public boolean doProcess() {
|
||||
return log.isDebugEnabled();
|
||||
}
|
||||
|
||||
public void prepare(SQLWarning warning) {
|
||||
log.warningsCreatingTempTable( warning );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void logWarning(String description, String message) {
|
||||
log.debug( description );
|
||||
log.debug( message );
|
||||
}
|
||||
};
|
||||
|
||||
protected void releaseTempTable(
|
||||
IdTableInfoImpl idTableInfo,
|
||||
AfterUseAction afterUseAction,
|
||||
TempTableDdlTransactionHandling ddlTransactionHandling,
|
||||
SessionImplementor session) {
|
||||
if ( afterUseAction == AfterUseAction.NONE ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( afterUseAction == AfterUseAction.DROP ) {
|
||||
TemporaryTableDropWork work = new TemporaryTableDropWork( idTableInfo, session.getFactory() );
|
||||
if ( ddlTransactionHandling == TempTableDdlTransactionHandling.NONE ) {
|
||||
final Connection connection = session.getTransactionCoordinator()
|
||||
.getJdbcCoordinator()
|
||||
.getLogicalConnection()
|
||||
.getConnection();
|
||||
|
||||
work.execute( connection );
|
||||
|
||||
session.getTransactionCoordinator()
|
||||
.getJdbcCoordinator()
|
||||
.afterStatementExecution();
|
||||
}
|
||||
else {
|
||||
session.getTransactionCoordinator()
|
||||
.getTransaction()
|
||||
.createIsolationDelegate()
|
||||
.delegateWork( work, ddlTransactionHandling == TempTableDdlTransactionHandling.ISOLATE_AND_TRANSACT );
|
||||
}
|
||||
}
|
||||
else {
|
||||
// at the very least cleanup the data :)
|
||||
|
||||
if ( afterUseAction == AfterUseAction.CLEAN ) {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
final String sql = "delete from " + persister.getTemporaryIdTableName();
|
||||
final String sql = "delete from " + idTableInfo.getQualifiedIdTableName();
|
||||
ps = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql, false );
|
||||
session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( ps );
|
||||
}
|
||||
@ -163,25 +185,13 @@ protected void releaseTempTable(Queryable persister, SessionImplementor session)
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean shouldIsolateTemporaryTableDDL(SessionImplementor session) {
|
||||
Boolean dialectVote = session.getFactory().getDialect().performTemporaryTableDDLInIsolation();
|
||||
if ( dialectVote != null ) {
|
||||
return dialectVote;
|
||||
}
|
||||
return session.getFactory().getSettings().isDataDefinitionImplicitCommit();
|
||||
}
|
||||
private static class TemporaryTableDropWork extends AbstractWork {
|
||||
private final IdTableInfoImpl idTableInfo;
|
||||
private final SessionFactoryImplementor factory;
|
||||
|
||||
protected boolean shouldTransactIsolatedTemporaryTableDDL(SessionImplementor session) {
|
||||
// is there ever a time when it makes sense to do this?
|
||||
// return session.getFactory().getSettings().isDataDefinitionInTransactionSupported();
|
||||
return false;
|
||||
}
|
||||
|
||||
private static class TemporaryTableCreationWork extends AbstractWork {
|
||||
private final Queryable persister;
|
||||
|
||||
private TemporaryTableCreationWork(Queryable persister) {
|
||||
this.persister = persister;
|
||||
private TemporaryTableDropWork(IdTableInfoImpl idTableInfo, SessionFactoryImplementor factory) {
|
||||
this.idTableInfo = idTableInfo;
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -189,61 +199,11 @@ public void execute(Connection connection) {
|
||||
try {
|
||||
Statement statement = connection.createStatement();
|
||||
try {
|
||||
statement.executeUpdate( persister.getTemporaryIdTableDDL() );
|
||||
persister.getFactory()
|
||||
.getServiceRegistry()
|
||||
statement.executeUpdate( idTableInfo.getIdTableDropStatement() );
|
||||
factory.getServiceRegistry()
|
||||
.getService( JdbcServices.class )
|
||||
.getSqlExceptionHelper()
|
||||
.handleAndClearWarnings( statement, CREATION_WARNING_HANDLER );
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
statement.close();
|
||||
}
|
||||
catch( Throwable ignore ) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( Exception e ) {
|
||||
log.debug( "unable to create temporary id table [" + e.getMessage() + "]" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static SqlExceptionHelper.WarningHandler CREATION_WARNING_HANDLER = new SqlExceptionHelper.WarningHandlerLoggingSupport() {
|
||||
public boolean doProcess() {
|
||||
return log.isDebugEnabled();
|
||||
}
|
||||
|
||||
public void prepare(SQLWarning warning) {
|
||||
log.warningsCreatingTempTable( warning );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void logWarning(String description, String message) {
|
||||
log.debug( description );
|
||||
log.debug( message );
|
||||
}
|
||||
};
|
||||
|
||||
private static class TemporaryTableDropWork extends AbstractWork {
|
||||
private final Queryable persister;
|
||||
private final SessionImplementor session;
|
||||
|
||||
private TemporaryTableDropWork(Queryable persister, SessionImplementor session) {
|
||||
this.persister = persister;
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Connection connection) {
|
||||
final String command = session.getFactory().getDialect().getDropTemporaryTableString()
|
||||
+ ' ' + persister.getTemporaryIdTableName();
|
||||
try {
|
||||
Statement statement = connection.createStatement();
|
||||
try {
|
||||
statement.executeUpdate( command );
|
||||
.handleAndClearWarnings( statement, WARNING_HANDLER );
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
@ -259,5 +219,4 @@ public void execute(Connection connection) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi.id.local;
|
||||
|
||||
import org.hibernate.hql.spi.id.IdTableInfo;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class IdTableInfoImpl implements IdTableInfo {
|
||||
private final String idTableName;
|
||||
|
||||
private final String creationStatement;
|
||||
private final String dropStatement;
|
||||
|
||||
public IdTableInfoImpl(
|
||||
String idTableName,
|
||||
String creationStatement,
|
||||
String dropStatement) {
|
||||
this.idTableName = idTableName;
|
||||
this.creationStatement = creationStatement;
|
||||
this.dropStatement = dropStatement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQualifiedIdTableName() {
|
||||
return idTableName;
|
||||
}
|
||||
|
||||
public String getIdTableCreationStatement() {
|
||||
return creationStatement;
|
||||
}
|
||||
|
||||
public String getIdTableDropStatement() {
|
||||
return dropStatement;
|
||||
}
|
||||
}
|
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi.id.local;
|
||||
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.boot.spi.MetadataBuildingOptions;
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.hql.internal.ast.HqlSqlWalker;
|
||||
import org.hibernate.hql.internal.ast.tree.DeleteStatement;
|
||||
import org.hibernate.hql.internal.ast.tree.FromElement;
|
||||
import org.hibernate.hql.internal.ast.tree.UpdateStatement;
|
||||
import org.hibernate.hql.spi.id.AbstractMultiTableBulkIdStrategyImpl;
|
||||
import org.hibernate.hql.spi.id.AbstractMultiTableBulkIdStrategyImpl.PreparationContext;
|
||||
import org.hibernate.hql.spi.id.IdTableSupport;
|
||||
import org.hibernate.hql.spi.id.IdTableSupportStandardImpl;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.hql.spi.id.TableBasedDeleteHandlerImpl;
|
||||
import org.hibernate.hql.spi.id.TableBasedUpdateHandlerImpl;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.persister.entity.Queryable;
|
||||
|
||||
/**
|
||||
* Strategy based on ANSI SQL's definition of a "local temporary table" (local to each db session).
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class LocalTemporaryTableBulkIdStrategy
|
||||
extends AbstractMultiTableBulkIdStrategyImpl<IdTableInfoImpl, PreparationContext>
|
||||
implements MultiTableBulkIdStrategy {
|
||||
|
||||
public static final String SHORT_NAME = "local_temporary";
|
||||
|
||||
private final AfterUseAction afterUseAction;
|
||||
private TempTableDdlTransactionHandling ddlTransactionHandling;
|
||||
|
||||
public LocalTemporaryTableBulkIdStrategy() {
|
||||
this(
|
||||
new IdTableSupportStandardImpl() {
|
||||
@Override
|
||||
public String getCreateIdTableCommand() {
|
||||
return "create local temporary table";
|
||||
}
|
||||
},
|
||||
AfterUseAction.DROP,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
public LocalTemporaryTableBulkIdStrategy(
|
||||
IdTableSupport idTableSupport,
|
||||
AfterUseAction afterUseAction,
|
||||
TempTableDdlTransactionHandling ddlTransactionHandling) {
|
||||
super( idTableSupport );
|
||||
this.afterUseAction = afterUseAction;
|
||||
this.ddlTransactionHandling = ddlTransactionHandling;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize(MetadataBuildingOptions buildingOptions, SessionFactoryOptions sessionFactoryOptions) {
|
||||
if ( ddlTransactionHandling == null ) {
|
||||
ddlTransactionHandling = sessionFactoryOptions.getTempTableDdlTransactionHandling();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IdTableInfoImpl buildIdTableInfo(
|
||||
PersistentClass entityBinding,
|
||||
Table idTable,
|
||||
JdbcServices jdbcServices,
|
||||
MetadataImplementor metadata,
|
||||
PreparationContext context) {
|
||||
return new IdTableInfoImpl(
|
||||
jdbcServices.getJdbcEnvironment().getQualifiedObjectNameFormatter().format(
|
||||
idTable.getQualifiedTableName(),
|
||||
jdbcServices.getJdbcEnvironment().getDialect()
|
||||
),
|
||||
buildIdTableCreateStatement( idTable, jdbcServices, metadata ),
|
||||
buildIdTableDropStatement( idTable, jdbcServices )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release(JdbcServices jdbcServices, JdbcConnectionAccess connectionAccess) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateHandler buildUpdateHandler(SessionFactoryImplementor factory, HqlSqlWalker walker) {
|
||||
final UpdateStatement updateStatement = (UpdateStatement) walker.getAST();
|
||||
|
||||
final FromElement fromElement = updateStatement.getFromClause().getFromElement();
|
||||
final Queryable targetedPersister = fromElement.getQueryable();
|
||||
|
||||
final IdTableInfoImpl tableInfo = getIdTableInfo( targetedPersister );
|
||||
|
||||
return new TableBasedUpdateHandlerImpl( factory, walker, tableInfo ) {
|
||||
@Override
|
||||
protected void prepareForUse(Queryable persister, SessionImplementor session) {
|
||||
Helper.INSTANCE.createTempTable(
|
||||
tableInfo,
|
||||
ddlTransactionHandling,
|
||||
session
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void releaseFromUse(Queryable persister, SessionImplementor session) {
|
||||
Helper.INSTANCE.releaseTempTable(
|
||||
tableInfo,
|
||||
afterUseAction,
|
||||
ddlTransactionHandling,
|
||||
session
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeleteHandler buildDeleteHandler(SessionFactoryImplementor factory, HqlSqlWalker walker) {
|
||||
final DeleteStatement updateStatement = (DeleteStatement) walker.getAST();
|
||||
|
||||
final FromElement fromElement = updateStatement.getFromClause().getFromElement();
|
||||
final Queryable targetedPersister = fromElement.getQueryable();
|
||||
|
||||
final IdTableInfoImpl tableInfo = getIdTableInfo( targetedPersister );
|
||||
|
||||
return new TableBasedDeleteHandlerImpl( factory, walker, tableInfo ) {
|
||||
@Override
|
||||
protected void prepareForUse(Queryable persister, SessionImplementor session) {
|
||||
Helper.INSTANCE.createTempTable(
|
||||
tableInfo,
|
||||
ddlTransactionHandling,
|
||||
session
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void releaseFromUse(Queryable persister, SessionImplementor session) {
|
||||
Helper.INSTANCE.releaseTempTable(
|
||||
tableInfo,
|
||||
afterUseAction,
|
||||
ddlTransactionHandling,
|
||||
session
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* Support for multi-table update and delete statements via id-tables.
|
||||
*/
|
||||
package org.hibernate.hql.spi.id;
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi.id.persistent;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.hql.internal.ast.HqlSqlWalker;
|
||||
import org.hibernate.hql.spi.id.IdTableInfo;
|
||||
import org.hibernate.hql.spi.id.TableBasedDeleteHandlerImpl;
|
||||
import org.hibernate.persister.entity.Queryable;
|
||||
import org.hibernate.sql.SelectValues;
|
||||
|
||||
import static org.hibernate.hql.spi.id.persistent.Helper.SESSION_ID_COLUMN_NAME;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DeleteHandlerImpl extends TableBasedDeleteHandlerImpl {
|
||||
private final IdTableInfo idTableInfo;
|
||||
|
||||
public DeleteHandlerImpl(
|
||||
SessionFactoryImplementor factory,
|
||||
HqlSqlWalker walker,
|
||||
IdTableInfo idTableInfo) {
|
||||
super( factory, walker, idTableInfo );
|
||||
this.idTableInfo = idTableInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addAnyExtraIdSelectValues(SelectValues selectClause) {
|
||||
selectClause.addParameter( Types.CHAR, 36 );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String generateIdSubselect(Queryable persister, IdTableInfo idTableInfo) {
|
||||
return super.generateIdSubselect( persister, idTableInfo ) + " where " + SESSION_ID_COLUMN_NAME + "=?";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int handlePrependedParametersOnIdSelection(PreparedStatement ps, SessionImplementor session, int pos) throws SQLException {
|
||||
Helper.INSTANCE.bindSessionIdentifier( ps, session, pos );
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleAddedParametersOnDelete(PreparedStatement ps, SessionImplementor session) throws SQLException {
|
||||
Helper.INSTANCE.bindSessionIdentifier( ps, session, 1 );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void releaseFromUse(Queryable persister, SessionImplementor session) {
|
||||
// clean up our id-table rows
|
||||
Helper.INSTANCE.cleanUpRows( idTableInfo.getQualifiedIdTableName(), session );
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi.id.persistent;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.JDBCException;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.internal.AbstractSessionImpl;
|
||||
import org.hibernate.type.UUIDCharType;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class Helper {
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final Helper INSTANCE = new Helper();
|
||||
|
||||
public static final String SESSION_ID_COLUMN_NAME = "hib_sess_id";
|
||||
|
||||
private Helper() {
|
||||
}
|
||||
|
||||
|
||||
public void bindSessionIdentifier(PreparedStatement ps, SessionImplementor session, int position) throws SQLException {
|
||||
if ( ! AbstractSessionImpl.class.isInstance( session ) ) {
|
||||
throw new HibernateException( "Only available on SessionImpl instances" );
|
||||
}
|
||||
UUIDCharType.INSTANCE.set( ps, ( (AbstractSessionImpl) session ).getSessionIdentifier(), position, session );
|
||||
}
|
||||
|
||||
public void cleanUpRows(String tableName, SessionImplementor session) {
|
||||
final String sql = "delete from " + tableName + " where " + SESSION_ID_COLUMN_NAME + "=?";
|
||||
try {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
ps = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql, false );
|
||||
bindSessionIdentifier( ps, session, 1 );
|
||||
session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( ps );
|
||||
}
|
||||
finally {
|
||||
if ( ps != null ) {
|
||||
try {
|
||||
session.getTransactionCoordinator().getJdbcCoordinator().release( ps );
|
||||
}
|
||||
catch( Throwable ignore ) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw convert( session.getFactory(), e, "Unable to clean up id table [" + tableName + "]", sql );
|
||||
}
|
||||
}
|
||||
|
||||
public JDBCException convert(SessionFactoryImplementor factory, SQLException e, String message, String sql) {
|
||||
throw factory.getSQLExceptionHelper().convert( e, message, sql );
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi.id.persistent;
|
||||
|
||||
import org.hibernate.hql.spi.id.IdTableInfo;
|
||||
|
||||
/**
|
||||
* IdTableInfo implementation specific to PersistentTableBulkIdStrategy
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
class IdTableInfoImpl implements IdTableInfo {
|
||||
private final String idTableName;
|
||||
|
||||
public IdTableInfoImpl(String idTableName) {
|
||||
this.idTableName = idTableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQualifiedIdTableName() {
|
||||
return idTableName;
|
||||
}
|
||||
}
|
@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi.id.persistent;
|
||||
|
||||
import org.hibernate.boot.model.naming.Identifier;
|
||||
import org.hibernate.boot.model.relational.QualifiedTableName;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.spi.MetadataBuildingOptions;
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
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.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.hql.internal.ast.HqlSqlWalker;
|
||||
import org.hibernate.hql.internal.ast.tree.DeleteStatement;
|
||||
import org.hibernate.hql.internal.ast.tree.FromElement;
|
||||
import org.hibernate.hql.internal.ast.tree.UpdateStatement;
|
||||
import org.hibernate.hql.spi.id.AbstractMultiTableBulkIdStrategyImpl;
|
||||
import org.hibernate.hql.spi.id.IdTableHelper;
|
||||
import org.hibernate.hql.spi.id.IdTableSupport;
|
||||
import org.hibernate.hql.spi.id.IdTableSupportStandardImpl;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.persister.entity.Queryable;
|
||||
|
||||
/**
|
||||
* This is a strategy that mimics temporary tables for databases which do not support
|
||||
* temporary tables. It follows a pattern similar to the ANSI SQL definition of global
|
||||
* temporary table using a "session id" column to segment rows from the various sessions.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class PersistentTableBulkIdStrategy
|
||||
extends AbstractMultiTableBulkIdStrategyImpl<IdTableInfoImpl,PreparationContextImpl>
|
||||
implements MultiTableBulkIdStrategy {
|
||||
|
||||
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";
|
||||
|
||||
private Identifier catalog;
|
||||
private Identifier schema;
|
||||
|
||||
private boolean dropIdTables;
|
||||
private String[] dropTableStatements;
|
||||
|
||||
public PersistentTableBulkIdStrategy() {
|
||||
this( IdTableSupportStandardImpl.INSTANCE );
|
||||
}
|
||||
|
||||
public PersistentTableBulkIdStrategy(IdTableSupport idTableSupport) {
|
||||
super( idTableSupport );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PreparationContextImpl buildPreparationContext() {
|
||||
return new PreparationContextImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize(MetadataBuildingOptions buildingOptions, SessionFactoryOptions sessionFactoryOptions) {
|
||||
final StandardServiceRegistry serviceRegistry = buildingOptions.getServiceRegistry();
|
||||
final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
|
||||
final ConfigurationService configService = serviceRegistry.getService( ConfigurationService.class );
|
||||
|
||||
final String catalogName = configService.getSetting(
|
||||
CATALOG,
|
||||
StandardConverters.STRING,
|
||||
configService.getSetting( AvailableSettings.DEFAULT_CATALOG, StandardConverters.STRING )
|
||||
);
|
||||
final String schemaName = configService.getSetting(
|
||||
SCHEMA,
|
||||
StandardConverters.STRING,
|
||||
configService.getSetting( AvailableSettings.DEFAULT_SCHEMA, StandardConverters.STRING )
|
||||
);
|
||||
|
||||
this.catalog = jdbcEnvironment.getIdentifierHelper().toIdentifier( catalogName );
|
||||
this.schema = jdbcEnvironment.getIdentifierHelper().toIdentifier( schemaName );
|
||||
|
||||
this.dropIdTables = configService.getSetting(
|
||||
DROP_ID_TABLES,
|
||||
StandardConverters.BOOLEAN,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected QualifiedTableName determineIdTableName(
|
||||
JdbcEnvironment jdbcEnvironment,
|
||||
PersistentClass entityBinding) {
|
||||
return new QualifiedTableName(
|
||||
catalog,
|
||||
schema,
|
||||
super.determineIdTableName( jdbcEnvironment, entityBinding ).getTableName()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void augmentIdTableDefinition(Table idTable) {
|
||||
Column sessionIdColumn = new Column( Helper.SESSION_ID_COLUMN_NAME );
|
||||
sessionIdColumn.setSqlType( "CHAR(36)" );
|
||||
sessionIdColumn.setComment( "Used to hold the Hibernate Session identifier" );
|
||||
idTable.addColumn( sessionIdColumn );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IdTableInfoImpl buildIdTableInfo(
|
||||
PersistentClass entityBinding,
|
||||
Table idTable,
|
||||
JdbcServices jdbcServices,
|
||||
MetadataImplementor metadata,
|
||||
PreparationContextImpl context) {
|
||||
final String renderedName = jdbcServices.getJdbcEnvironment().getQualifiedObjectNameFormatter().format(
|
||||
idTable.getQualifiedTableName(),
|
||||
jdbcServices.getJdbcEnvironment().getDialect()
|
||||
);
|
||||
|
||||
context.creationStatements.add( buildIdTableCreateStatement( idTable, jdbcServices, metadata ) );
|
||||
if ( dropIdTables ) {
|
||||
context.dropStatements.add( buildIdTableDropStatement( idTable, jdbcServices ) );
|
||||
}
|
||||
|
||||
return new IdTableInfoImpl( renderedName );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finishPreparation(
|
||||
JdbcServices jdbcServices,
|
||||
JdbcConnectionAccess connectionAccess,
|
||||
MetadataImplementor metadata,
|
||||
PreparationContextImpl context) {
|
||||
IdTableHelper.INSTANCE.executeIdTableCreationStatements(
|
||||
context.creationStatements,
|
||||
jdbcServices,
|
||||
connectionAccess
|
||||
);
|
||||
|
||||
this.dropTableStatements = dropIdTables
|
||||
? context.dropStatements.toArray( new String[ context.dropStatements.size() ] )
|
||||
: null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateHandler buildUpdateHandler(SessionFactoryImplementor factory, HqlSqlWalker walker) {
|
||||
final UpdateStatement updateStatement = (UpdateStatement) walker.getAST();
|
||||
|
||||
final FromElement fromElement = updateStatement.getFromClause().getFromElement();
|
||||
final Queryable targetedPersister = fromElement.getQueryable();
|
||||
|
||||
return new UpdateHandlerImpl(
|
||||
factory,
|
||||
walker,
|
||||
getIdTableInfo( targetedPersister )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeleteHandler buildDeleteHandler(SessionFactoryImplementor factory, HqlSqlWalker walker) {
|
||||
final DeleteStatement updateStatement = (DeleteStatement) walker.getAST();
|
||||
|
||||
final FromElement fromElement = updateStatement.getFromClause().getFromElement();
|
||||
final Queryable targetedPersister = fromElement.getQueryable();
|
||||
|
||||
return new DeleteHandlerImpl(
|
||||
factory,
|
||||
walker,
|
||||
getIdTableInfo( targetedPersister )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release(JdbcServices jdbcServices, JdbcConnectionAccess connectionAccess) {
|
||||
if ( ! dropIdTables ) {
|
||||
return;
|
||||
}
|
||||
|
||||
IdTableHelper.INSTANCE.executeIdTableDropStatements( dropTableStatements, jdbcServices, connectionAccess );
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi.id.persistent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.hql.spi.id.AbstractMultiTableBulkIdStrategyImpl;
|
||||
|
||||
/**
|
||||
* PreparationContext implementation for PersistentTableBulkIdStrategy
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
class PreparationContextImpl implements AbstractMultiTableBulkIdStrategyImpl.PreparationContext {
|
||||
List<String> creationStatements = new ArrayList<String>();
|
||||
List<String> dropStatements = new ArrayList<String>();
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.hql.spi.id.persistent;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.hql.internal.ast.HqlSqlWalker;
|
||||
import org.hibernate.hql.spi.id.IdTableInfo;
|
||||
import org.hibernate.hql.spi.id.TableBasedUpdateHandlerImpl;
|
||||
import org.hibernate.persister.entity.Queryable;
|
||||
import org.hibernate.sql.SelectValues;
|
||||
|
||||
import static org.hibernate.hql.spi.id.persistent.Helper.SESSION_ID_COLUMN_NAME;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class UpdateHandlerImpl extends TableBasedUpdateHandlerImpl {
|
||||
private final IdTableInfo idTableInfo;
|
||||
|
||||
public UpdateHandlerImpl(
|
||||
SessionFactoryImplementor factory,
|
||||
HqlSqlWalker walker,
|
||||
IdTableInfo idTableInfo) {
|
||||
super( factory, walker, idTableInfo );
|
||||
this.idTableInfo = idTableInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addAnyExtraIdSelectValues(SelectValues selectClause) {
|
||||
selectClause.addParameter( Types.CHAR, 36 );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String generateIdSubselect(Queryable persister, IdTableInfo idTableInfo) {
|
||||
return super.generateIdSubselect( persister, idTableInfo ) + " where " + SESSION_ID_COLUMN_NAME + "=?";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int handlePrependedParametersOnIdSelection(PreparedStatement ps, SessionImplementor session, int pos) throws SQLException {
|
||||
Helper.INSTANCE.bindSessionIdentifier( ps, session, pos );
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleAddedParametersOnUpdate(PreparedStatement ps, SessionImplementor session, int position) throws SQLException {
|
||||
Helper.INSTANCE.bindSessionIdentifier( ps, session, position );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void releaseFromUse(Queryable persister, SessionImplementor session) {
|
||||
// clean up our id-table rows
|
||||
Helper.INSTANCE.cleanUpRows( idTableInfo.getQualifiedIdTableName(), session );
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* Package contains an implementation of MultiTableBulkIdStrategy based on the use
|
||||
* of a persistent (ANSI SQL term) table to hold id values. It also holds a "session identifier"
|
||||
* column which Hibernate manages in order to isolate rows from different sessions.
|
||||
*/
|
||||
package org.hibernate.hql.spi.id.persistent;
|
@ -337,7 +337,6 @@ public MetadataImplementor getMetadata() {
|
||||
Map cacheAccessStrategiesMap = new HashMap();
|
||||
Map<String,ClassMetadata> inFlightClassMetadataMap = new HashMap<String,ClassMetadata>();
|
||||
for ( final PersistentClass model : metadata.getEntityBindings() ) {
|
||||
model.prepareTemporaryTables( metadata, getDialect() );
|
||||
final String cacheRegionName = cacheRegionPrefix + model.getRootClass().getCacheRegionName();
|
||||
// cache region is defined by the root-class in the hierarchy...
|
||||
final EntityRegionAccessStrategy accessStrategy = determineEntityRegionAccessStrategy(
|
||||
@ -445,7 +444,8 @@ public MetadataImplementor getMetadata() {
|
||||
settings.getMultiTableBulkIdStrategy().prepare(
|
||||
jdbcServices,
|
||||
buildLocalConnectionAccess(),
|
||||
metadata
|
||||
metadata,
|
||||
sessionFactoryOptions
|
||||
);
|
||||
|
||||
|
||||
|
@ -156,7 +156,7 @@ public interface DeprecationLogger {
|
||||
@LogMessage(level = WARN)
|
||||
@Message(
|
||||
value = "org.hibernate.hql.spi.TemporaryTableBulkIdStrategy (temporary) has been deprecated in favor of the" +
|
||||
" more specific org.hibernate.hql.spi.LocalTemporaryTableBulkIdStrategy (local_temporary).",
|
||||
" more specific org.hibernate.hql.spi.id.local.LocalTemporaryTableBulkIdStrategy (local_temporary).",
|
||||
id = 90000011
|
||||
)
|
||||
void logDeprecationOfTemporaryTableBulkIdStrategy();
|
||||
|
@ -100,9 +100,6 @@ public abstract class PersistentClass implements AttributeContainer, Serializabl
|
||||
private boolean customDeleteCallable;
|
||||
private ExecuteUpdateResultCheckStyle deleteCheckStyle;
|
||||
|
||||
private String temporaryIdTableName;
|
||||
private String temporaryIdTableDDL;
|
||||
|
||||
private java.util.Map tuplizerImpls;
|
||||
|
||||
private MappedSuperclass superMappedSuperclass;
|
||||
@ -798,28 +795,6 @@ public void setSubselectLoadableCollections(boolean hasSubselectCollections) {
|
||||
this.hasSubselectLoadableCollections = hasSubselectCollections;
|
||||
}
|
||||
|
||||
public void prepareTemporaryTables(Mapping mapping, Dialect dialect) {
|
||||
temporaryIdTableName = dialect.generateTemporaryTableName( getTable().getName() );
|
||||
if ( dialect.supportsTemporaryTables() ) {
|
||||
Table table = new Table();
|
||||
table.setName( temporaryIdTableName );
|
||||
Iterator itr = getTable().getPrimaryKey().getColumnIterator();
|
||||
while( itr.hasNext() ) {
|
||||
Column column = (Column) itr.next();
|
||||
table.addColumn( column.clone() );
|
||||
}
|
||||
temporaryIdTableDDL = table.sqlTemporaryTableCreateString( dialect, mapping );
|
||||
}
|
||||
}
|
||||
|
||||
public String getTemporaryIdTableName() {
|
||||
return temporaryIdTableName;
|
||||
}
|
||||
|
||||
public String getTemporaryIdTableDDL() {
|
||||
return temporaryIdTableDDL;
|
||||
}
|
||||
|
||||
public Component getIdentifierMapper() {
|
||||
return identifierMapper;
|
||||
}
|
||||
|
@ -41,7 +41,6 @@
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.tool.hbm2ddl.ColumnMetadata;
|
||||
import org.hibernate.tool.hbm2ddl.TableMetadata;
|
||||
import org.hibernate.tool.schema.extract.spi.ColumnInformation;
|
||||
@ -497,31 +496,6 @@ public boolean hasPrimaryKey() {
|
||||
return getPrimaryKey() != null;
|
||||
}
|
||||
|
||||
public String sqlTemporaryTableCreateString(Dialect dialect, Mapping mapping) throws HibernateException {
|
||||
StringBuilder buffer = new StringBuilder( dialect.getCreateTemporaryTableString() )
|
||||
.append( ' ' )
|
||||
.append( name )
|
||||
.append( " (" );
|
||||
Iterator itr = getColumnIterator();
|
||||
while ( itr.hasNext() ) {
|
||||
final Column column = (Column) itr.next();
|
||||
buffer.append( column.getQuotedName( dialect ) ).append( ' ' );
|
||||
buffer.append( column.getSqlType( dialect, mapping ) );
|
||||
if ( column.isNullable() ) {
|
||||
buffer.append( dialect.getNullColumnString() );
|
||||
}
|
||||
else {
|
||||
buffer.append( " not null" );
|
||||
}
|
||||
if ( itr.hasNext() ) {
|
||||
buffer.append( ", " );
|
||||
}
|
||||
}
|
||||
buffer.append( ") " );
|
||||
buffer.append( dialect.getCreateTemporaryTablePostfix() );
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public String sqlCreateString(Dialect dialect, Mapping p, String defaultCatalog, String defaultSchema) {
|
||||
StringBuilder buf = new StringBuilder( hasPrimaryKey() ? dialect.getCreateTableString() : dialect.getCreateMultisetTableString() )
|
||||
.append( ' ' )
|
||||
|
@ -272,9 +272,6 @@ public abstract class AbstractEntityPersister
|
||||
|
||||
private UniqueEntityLoader queryLoader;
|
||||
|
||||
private final String temporaryIdTableName;
|
||||
private final String temporaryIdTableDDL;
|
||||
|
||||
private final Map subclassPropertyAliases = new HashMap();
|
||||
private final Map subclassPropertyColumnNames = new HashMap();
|
||||
|
||||
@ -791,10 +788,6 @@ public AbstractEntityPersister(
|
||||
// Handle any filters applied to the class level
|
||||
filterHelper = new FilterHelper( persistentClass.getFilters(), factory );
|
||||
|
||||
temporaryIdTableName = persistentClass.getTemporaryIdTableName();
|
||||
temporaryIdTableDDL = persistentClass.getTemporaryIdTableDDL();
|
||||
|
||||
|
||||
// Check if we can use Reference Cached entities in 2lc
|
||||
// todo : should really validate that the cache access type is read-only
|
||||
boolean refCacheEntries = true;
|
||||
@ -4409,14 +4402,6 @@ public boolean isMultiTable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getTemporaryIdTableName() {
|
||||
return temporaryIdTableName;
|
||||
}
|
||||
|
||||
public String getTemporaryIdTableDDL() {
|
||||
return temporaryIdTableDDL;
|
||||
}
|
||||
|
||||
protected int getPropertySpan() {
|
||||
return entityMetamodel.getPropertySpan();
|
||||
}
|
||||
|
@ -96,22 +96,6 @@ public interface Queryable extends Loadable, PropertyMapping, Joinable {
|
||||
*/
|
||||
public String[][] getContraintOrderedTableKeyColumnClosure();
|
||||
|
||||
/**
|
||||
* Get the name of the temporary table to be used to (potentially) store id values
|
||||
* when performing bulk update/deletes.
|
||||
*
|
||||
* @return The appropriate temporary table name.
|
||||
*/
|
||||
public String getTemporaryIdTableName();
|
||||
|
||||
/**
|
||||
* Get the appropriate DDL command for generating the temporary table to
|
||||
* be used to (potentially) store id values when performing bulk update/deletes.
|
||||
*
|
||||
* @return The appropriate temporary table creation command.
|
||||
*/
|
||||
public String getTemporaryIdTableDDL();
|
||||
|
||||
/**
|
||||
* Given a property name, determine the number of the table which contains the column
|
||||
* to which this property is mapped.
|
||||
|
@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.tool.schema.internal;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.boot.Metadata;
|
||||
import org.hibernate.boot.model.naming.Identifier;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.Table;
|
||||
|
||||
/**
|
||||
* @author Strong Liu <stliu@hibernate.org>
|
||||
*/
|
||||
public class TemporaryTableExporter extends StandardTableExporter {
|
||||
public TemporaryTableExporter(Dialect dialect) {
|
||||
super(dialect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSqlCreateStrings(Table exportable, Metadata metadata) {
|
||||
if ( dialect.supportsTemporaryTables() ) {
|
||||
final String temporaryTableName = generateTableName( dialect, exportable );
|
||||
Table temporaryTable = new Table(
|
||||
Identifier.toIdentifier( exportable.getQuotedCatalog() ),
|
||||
Identifier.toIdentifier( exportable.getQuotedSchema() ),
|
||||
Identifier.toIdentifier( temporaryTableName ),
|
||||
false
|
||||
);
|
||||
//noinspection unchecked
|
||||
for ( Column column : ( (List<Column>) exportable.getPrimaryKey().getColumns() ) ) {
|
||||
final Column clone = column.clone();
|
||||
temporaryTable.addColumn( clone );
|
||||
}
|
||||
return super.getSqlCreateStrings( temporaryTable, metadata );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String generateTableName(final Dialect dialect, final Table primaryTable) {
|
||||
return dialect.generateTemporaryTableName( primaryTable.getName() );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String tableCreateString(boolean hasPrimaryKey) {
|
||||
return dialect.getCreateTemporaryTableString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyTableCheck(Table table, StringBuilder buf) {
|
||||
// N/A
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyComments(Table table, List<String> sqlStrings) {
|
||||
// N/A
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyTableTypeString(StringBuilder buf) {
|
||||
buf.append( " " ).append( dialect.getCreateTemporaryTablePostfix() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSqlDropStrings(Table exportable, Metadata metadata) {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -23,6 +23,8 @@
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import org.hibernate.hql.spi.id.AbstractMultiTableBulkIdStrategyImpl;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
@ -35,7 +37,9 @@ public class Oracle8iDialectTestCase extends BaseUnitTestCase {
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-9290")
|
||||
public void testTemporaryTableNameTruncation() throws Exception {
|
||||
String temporaryTableName = new Oracle8iDialect().generateTemporaryTableName(
|
||||
final AbstractMultiTableBulkIdStrategyImpl strategy = (AbstractMultiTableBulkIdStrategyImpl) new Oracle8iDialect().getDefaultMultiTableBulkIdStrategy();
|
||||
|
||||
String temporaryTableName = strategy.getIdTableSupport().generateIdTableName(
|
||||
"TABLE_NAME_THAT_EXCEEDS_30_CHARACTERS"
|
||||
);
|
||||
|
||||
|
@ -25,7 +25,8 @@ Working list of changes for 5.0
|
||||
with `org.hibernate.type.descriptor.sql.SqlTypeDescriptorRegistry`. Applications using custom SqlTypeDescriptor
|
||||
implementations extending the built-in ones and relying on that behavior should be updated to call
|
||||
`SqlTypeDescriptorRegistry#addDescriptor` themselves.
|
||||
|
||||
* Moving `org.hibernate.hql.spi.MultiTableBulkIdStrategy` and friends to new `org.hibernate.hql.spi.id` package
|
||||
and sub-packages
|
||||
|
||||
TODOs
|
||||
=====
|
||||
|
Loading…
x
Reference in New Issue
Block a user