package org.hibernate.hql.spi.id;
import java.util.HashMap;
import java.util.Iterator;
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;
public abstract class AbstractMultiTableBulkIdStrategyImpl<TT extends IdTableInfo, CT extends AbstractMultiTableBulkIdStrategyImpl.PreparationContext>
implements MultiTableBulkIdStrategy {
private final IdTableSupport idTableSupport;
private Map<String,TT> idTableInfoMap = new HashMap<String, TT>();
public AbstractMultiTableBulkIdStrategyImpl(IdTableSupport idTableSupport) {
this.idTableSupport = idTableSupport;
}
public IdTableSupport getIdTableSupport() {
return idTableSupport;
}
@Override
public final void prepare(
JdbcServices jdbcServices,
JdbcConnectionAccess connectionAccess,
MetadataImplementor metadata,
SessionFactoryOptions sessionFactoryOptions) {
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;
}
protected void initialize(MetadataBuildingOptions buildingOptions, SessionFactoryOptions sessionFactoryOptions) {
}
protected QualifiedTableName determineIdTableName(JdbcEnvironment jdbcEnvironment, PersistentClass entityBinding) {
final String entityPrimaryTableName = entityBinding.getTable().getName();
final String idTableName = getIdTableSupport().generateIdTableName( entityPrimaryTableName );
return new QualifiedTableName(
null,
null,
jdbcEnvironment.getIdentifierHelper().toIdentifier( idTableName )
);
}
protected void augmentIdTableDefinition(Table idTable) {
}
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 {
}
}