getSequenceExporter() {
return sequenceExporter;
}
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java
index 0794b26b0e..6c6904336d 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java
@@ -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
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java
index 693fd1591b..257ac8ca50 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java
@@ -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).
- //
- // 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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/InformixDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/InformixDialect.java
index 614d7dc8c2..12bcae35a4 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/InformixDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/InformixDialect.java
@@ -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
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/IngresDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/IngresDialect.java
index 905d9b171a..e5db5930c7 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/IngresDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/IngresDialect.java
@@ -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() {
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java
index 2ed59b0e11..2798700906 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java
@@ -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
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java
index c57be684dd..1484b04aa1 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java
@@ -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
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9Dialect.java
index 51c83a1246..8a8218a897 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9Dialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9Dialect.java
@@ -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
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL81Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL81Dialect.java
index 8bba7e8d40..f4c8e9c43a 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL81Dialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL81Dialect.java
@@ -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
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SAPDBDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SAPDBDialect.java
index 2c6448498b..faa67d3a60 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/SAPDBDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/SAPDBDialect.java
@@ -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 );
- }
-
}
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Teradata14Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Teradata14Dialect.java
index e713cb8b58..54918fdcfc 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/Teradata14Dialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/Teradata14Dialect.java
@@ -108,11 +108,6 @@ public String getIdentityInsertString() {
return "null";
}
- @Override
- public String getDropTemporaryTableString() {
- return "drop temporary table";
- }
-
@Override
public boolean supportsExpectedLobUsagePattern() {
return true;
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/TeradataDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/TeradataDialect.java
index 942057aa64..f9f4b80867 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/TeradataDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/TeradataDialect.java
@@ -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";
}
/**
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/TimesTenDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/TimesTenDialect.java
index 44f1ae4ea2..808305385f 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/TimesTenDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/TimesTenDialect.java
@@ -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
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/exec/MultiTableDeleteExecutor.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/exec/MultiTableDeleteExecutor.java
index 9fb74e5e66..a895992743 100644
--- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/exec/MultiTableDeleteExecutor.java
+++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/exec/MultiTableDeleteExecutor.java
@@ -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.
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/exec/MultiTableUpdateExecutor.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/exec/MultiTableUpdateExecutor.java
index b78afe8f3f..47991563d4 100644
--- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/exec/MultiTableUpdateExecutor.java
+++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/exec/MultiTableUpdateExecutor.java
@@ -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.
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/GlobalTemporaryTableBulkIdStrategy.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/GlobalTemporaryTableBulkIdStrategy.java
deleted file mode 100644
index 04f2390384..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/hql/spi/GlobalTemporaryTableBulkIdStrategy.java
+++ /dev/null
@@ -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 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 idTableDefinitions = new ArrayList();
-
- 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();
- }
- 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 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 );
- }
- };
- }
-}
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/PersistentTableBulkIdStrategy.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/PersistentTableBulkIdStrategy.java
deleted file mode 100644
index 29f24cd4e9..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/hql/spi/PersistentTableBulkIdStrategy.java
+++ /dev/null
@@ -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 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 idTableDefinitions = new ArrayList();
-
- 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();
- }
- 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 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 );
- }
- };
- }
-}
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/TemporaryTableBulkIdStrategy.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/TemporaryTableBulkIdStrategy.java
deleted file mode 100644
index 758b034646..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/hql/spi/TemporaryTableBulkIdStrategy.java
+++ /dev/null
@@ -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 );
- }
-}
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/id/AbstractMultiTableBulkIdStrategyImpl.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/AbstractMultiTableBulkIdStrategyImpl.java
new file mode 100644
index 0000000000..ad06120d7c
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/AbstractMultiTableBulkIdStrategyImpl.java
@@ -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
+ implements MultiTableBulkIdStrategy {
+
+ private final IdTableSupport idTableSupport;
+ private Map idTableInfoMap = new HashMap();
+
+ 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 {
+ }
+
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/AbstractTableBasedBulkIdHandler.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/AbstractTableBasedBulkIdHandler.java
similarity index 66%
rename from hibernate-core/src/main/java/org/hibernate/hql/spi/AbstractTableBasedBulkIdHandler.java
rename to hibernate-core/src/main/java/org/hibernate/hql/spi/id/AbstractTableBasedBulkIdHandler.java
index 4e6e9ff936..c28da9ceaa 100644
--- a/hibernate-core/src/main/java/org/hibernate/hql/spi/AbstractTableBasedBulkIdHandler.java
+++ b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/AbstractTableBasedBulkIdHandler.java
@@ -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.
+ *
+ * Mainly supports common activities like:
+ * - processing the original {@code WHERE} clause (if one) - {@link #processWhereClause}
+ * - generating the proper {@code SELECT} clause for the id-table insert - {@link #generateIdInsertSelect}
+ * - generating the sub-select from the id-table - {@link #generateIdSubselect}
+ *
+ *
* @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 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) {
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/MultiTableBulkIdHelper.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/IdTableHelper.java
similarity index 67%
rename from hibernate-core/src/main/java/org/hibernate/hql/spi/MultiTableBulkIdHelper.java
rename to hibernate-core/src/main/java/org/hibernate/hql/spi/id/IdTableHelper.java
index e8fd8fdb19..3f7f3d7e5d 100644
--- a/hibernate-core/src/main/java/org/hibernate/hql/spi/MultiTableBulkIdHelper.java
+++ b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/IdTableHelper.java
@@ -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 idTableDefinitions,
+ public void executeIdTableCreationStatements(
+ List 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 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 );
}
}
+
}
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/id/IdTableInfo.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/IdTableInfo.java
new file mode 100644
index 0000000000..05b0ec7ada
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/IdTableInfo.java
@@ -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();
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/id/IdTableSupport.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/IdTableSupport.java
new file mode 100644
index 0000000000..4ebd8bc3b8
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/IdTableSupport.java
@@ -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();
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/id/IdTableSupportStandardImpl.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/IdTableSupportStandardImpl.java
new file mode 100644
index 0000000000..de1ad2f197
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/IdTableSupportStandardImpl.java
@@ -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";
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/MultiTableBulkIdStrategy.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/MultiTableBulkIdStrategy.java
similarity index 91%
rename from hibernate-core/src/main/java/org/hibernate/hql/spi/MultiTableBulkIdStrategy.java
rename to hibernate-core/src/main/java/org/hibernate/hql/spi/id/MultiTableBulkIdStrategy.java
index 78e9bc9974..c074184065 100644
--- a/hibernate-core/src/main/java/org/hibernate/hql/spi/MultiTableBulkIdStrategy.java
+++ b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/MultiTableBulkIdStrategy.java
@@ -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 {
* Adding tables to the passed Mappings, to be picked by by "schema management tools"
* Manually creating the tables immediately through the passed JDBC Connection access
*
- *
- * @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.
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/TableBasedDeleteHandlerImpl.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/TableBasedDeleteHandlerImpl.java
similarity index 95%
rename from hibernate-core/src/main/java/org/hibernate/hql/spi/TableBasedDeleteHandlerImpl.java
rename to hibernate-core/src/main/java/org/hibernate/hql/spi/id/TableBasedDeleteHandlerImpl.java
index 8e890fb492..a0c12ed817 100644
--- a/hibernate-core/src/main/java/org/hibernate/hql/spi/TableBasedDeleteHandlerImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/TableBasedDeleteHandlerImpl.java
@@ -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 idSelectParameterSpecifications;
private final List 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();
// If many-to-many, delete the FK row in the collection table.
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/TableBasedUpdateHandlerImpl.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/TableBasedUpdateHandlerImpl.java
similarity index 91%
rename from hibernate-core/src/main/java/org/hibernate/hql/spi/TableBasedUpdateHandlerImpl.java
rename to hibernate-core/src/main/java/org/hibernate/hql/spi/id/TableBasedUpdateHandlerImpl.java
index cc34035020..6f858d27c7 100644
--- a/hibernate-core/src/main/java/org/hibernate/hql/spi/TableBasedUpdateHandlerImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/TableBasedUpdateHandlerImpl.java
@@ -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() );
}
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/id/global/GlobalTemporaryTableBulkIdStrategy.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/global/GlobalTemporaryTableBulkIdStrategy.java
new file mode 100644
index 0000000000..c11f8e2ef1
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/global/GlobalTemporaryTableBulkIdStrategy.java
@@ -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
+ 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 );
+ }
+ };
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/id/global/IdTableInfoImpl.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/global/IdTableInfoImpl.java
new file mode 100644
index 0000000000..1bc708a31e
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/global/IdTableInfoImpl.java
@@ -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;
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/id/global/PreparationContextImpl.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/global/PreparationContextImpl.java
new file mode 100644
index 0000000000..41155ab77a
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/global/PreparationContextImpl.java
@@ -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 creationStatements = new ArrayList();
+ List dropStatements = new ArrayList();
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/id/local/AfterUseAction.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/local/AfterUseAction.java
new file mode 100644
index 0000000000..366b00d377
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/local/AfterUseAction.java
@@ -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
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/LocalTemporaryTableBulkIdStrategy.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/local/Helper.java
similarity index 51%
rename from hibernate-core/src/main/java/org/hibernate/hql/spi/LocalTemporaryTableBulkIdStrategy.java
rename to hibernate-core/src/main/java/org/hibernate/hql/spi/id/local/Helper.java
index 1c8b39e930..0c2e505745 100644
--- a/hibernate-core/src/main/java/org/hibernate/hql/spi/LocalTemporaryTableBulkIdStrategy.java
+++ b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/local/Helper.java
@@ -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) {
}
}
}
-
}
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/id/local/IdTableInfoImpl.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/local/IdTableInfoImpl.java
new file mode 100644
index 0000000000..7d88a77679
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/local/IdTableInfoImpl.java
@@ -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;
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/id/local/LocalTemporaryTableBulkIdStrategy.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/local/LocalTemporaryTableBulkIdStrategy.java
new file mode 100644
index 0000000000..62a63f8c78
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/local/LocalTemporaryTableBulkIdStrategy.java
@@ -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
+ 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
+ );
+ }
+ };
+ }
+
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/id/package-info.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/package-info.java
new file mode 100644
index 0000000000..675cc421ba
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/package-info.java
@@ -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;
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/id/persistent/DeleteHandlerImpl.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/persistent/DeleteHandlerImpl.java
new file mode 100644
index 0000000000..9f8944d919
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/persistent/DeleteHandlerImpl.java
@@ -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 );
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/id/persistent/Helper.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/persistent/Helper.java
new file mode 100644
index 0000000000..7e830b11e6
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/persistent/Helper.java
@@ -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 );
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/id/persistent/IdTableInfoImpl.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/persistent/IdTableInfoImpl.java
new file mode 100644
index 0000000000..fba0be9497
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/persistent/IdTableInfoImpl.java
@@ -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;
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/id/persistent/PersistentTableBulkIdStrategy.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/persistent/PersistentTableBulkIdStrategy.java
new file mode 100644
index 0000000000..d69e97593a
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/persistent/PersistentTableBulkIdStrategy.java
@@ -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
+ 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 );
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/id/persistent/PreparationContextImpl.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/persistent/PreparationContextImpl.java
new file mode 100644
index 0000000000..7bbd303a5e
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/persistent/PreparationContextImpl.java
@@ -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 creationStatements = new ArrayList();
+ List dropStatements = new ArrayList();
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/id/persistent/UpdateHandlerImpl.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/persistent/UpdateHandlerImpl.java
new file mode 100644
index 0000000000..cd94853a31
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/persistent/UpdateHandlerImpl.java
@@ -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 );
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/hql/spi/id/persistent/package-info.java b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/persistent/package-info.java
new file mode 100644
index 0000000000..367faa98f5
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/hql/spi/id/persistent/package-info.java
@@ -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;
diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java
index 087ac1ac64..dbe332e2a3 100644
--- a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java
@@ -337,7 +337,6 @@ public MetadataImplementor getMetadata() {
Map cacheAccessStrategiesMap = new HashMap();
Map inFlightClassMetadataMap = new HashMap();
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
);
diff --git a/hibernate-core/src/main/java/org/hibernate/internal/log/DeprecationLogger.java b/hibernate-core/src/main/java/org/hibernate/internal/log/DeprecationLogger.java
index cd5e92ace6..83fab7ab63 100644
--- a/hibernate-core/src/main/java/org/hibernate/internal/log/DeprecationLogger.java
+++ b/hibernate-core/src/main/java/org/hibernate/internal/log/DeprecationLogger.java
@@ -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();
diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java b/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java
index 9bf86c1fd4..24fa192726 100644
--- a/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java
+++ b/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java
@@ -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;
}
diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Table.java b/hibernate-core/src/main/java/org/hibernate/mapping/Table.java
index 93d3b4a1f9..39805afd88 100644
--- a/hibernate-core/src/main/java/org/hibernate/mapping/Table.java
+++ b/hibernate-core/src/main/java/org/hibernate/mapping/Table.java
@@ -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( ' ' )
diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
index 58ab70d7ea..c98f5e2f83 100644
--- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
+++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
@@ -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();
}
diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/Queryable.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/Queryable.java
index bf92493f04..968c9883ca 100644
--- a/hibernate-core/src/main/java/org/hibernate/persister/entity/Queryable.java
+++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/Queryable.java
@@ -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.
diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/TemporaryTableExporter.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/TemporaryTableExporter.java
deleted file mode 100644
index b618b4d98d..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/TemporaryTableExporter.java
+++ /dev/null
@@ -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
- */
-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) 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 sqlStrings) {
- // N/A
- }
-
- @Override
- protected void applyTableTypeString(StringBuilder buf) {
- buf.append( " " ).append( dialect.getCreateTemporaryTablePostfix() );
- }
-
- @Override
- public String[] getSqlDropStrings(Table exportable, Metadata metadata) {
- return null;
- }
-}
diff --git a/hibernate-core/src/test/java/org/hibernate/dialect/Oracle8iDialectTestCase.java b/hibernate-core/src/test/java/org/hibernate/dialect/Oracle8iDialectTestCase.java
index f71efd9842..b38b2cd4a4 100644
--- a/hibernate-core/src/test/java/org/hibernate/dialect/Oracle8iDialectTestCase.java
+++ b/hibernate-core/src/test/java/org/hibernate/dialect/Oracle8iDialectTestCase.java
@@ -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"
);
diff --git a/working-5.0-migration-guide.md b/working-5.0-migration-guide.md
index b47bc92e1d..f38ba40e8e 100644
--- a/working-5.0-migration-guide.md
+++ b/working-5.0-migration-guide.md
@@ -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
=====