Steve Ebersole commented on Bug HHH-7816

Ok, it is as I suspected. The Oracle XA driver just returns bad information here. For DatabaseMetaData#supportsDataDefinitionInTransaction() it returns true. Yet clearly it does not.

I have developed a work around and am working on a fix to allow dialects to override know bad DatabaseMetaData#supportsDataDefinitionInTransaction() implementations much like we have with org.hibernate.dialect.Dialect#performTemporaryTableDDLInIsolation for handling bad DatabaseMetaData#dataDefinitionCausesTransactionCommit() implementations.

The work-around is to specify a custom org.hibernate.hql.spi.MultiTableBulkIdStrategy implementation using the hibernate.hql.bulk_id_strategy setting:

CustomBulkIdDelegate.java
import java.sql.Connection;
import java.sql.SQLWarning;
import java.sql.Statement;

import org.jboss.logging.Logger;

import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.hql.spi.TemporaryTableBulkIdStrategy;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.jdbc.AbstractWork;
import org.hibernate.persister.entity.Queryable;

/**
 * @author Steve Ebersole
 */
public class CustomBulkIdDelegate extends TemporaryTableBulkIdStrategy {
	private static final CoreMessageLogger log = Logger.getMessageLogger( CoreMessageLogger.class, CustomBulkIdDelegate.class.getName() );

	@Override
	protected void createTempTable(Queryable persister, SessionImplementor session) {
		TemporaryTableCreationWork work = new TemporaryTableCreationWork( persister );
		// here we always want to (a) create the tables in isolation and (b) do not start a new transaction for the creation
		session.getTransactionCoordinator()
				.getTransaction()
				.createIsolationDelegate()
				.delegateWork( work, false );
	}

	// todo make these protected on TemporaryTableBulkIdStrategy ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	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 TemporaryTableCreationWork extends AbstractWork {
		private final Queryable persister;

		private TemporaryTableCreationWork(Queryable persister) {
			this.persister = persister;
		}

		@Override
		public void execute(Connection connection) {
			try {
				Statement statement = connection.createStatement();
				try {
					statement.executeUpdate( persister.getTemporaryIdTableDDL() );
					persister.getFactory()
							.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() + "]" );
			}
		}
	}
}
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira