HHH-9850 - Primary key generated for nullable column in sequence table
This commit is contained in:
parent
182146f0ad
commit
1556c272d5
|
@ -17,7 +17,7 @@ import java.util.Properties;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.model.naming.ObjectNameNormalizer;
|
||||
import org.hibernate.boot.model.naming.Identifier;
|
||||
import org.hibernate.boot.model.relational.Database;
|
||||
import org.hibernate.boot.model.relational.Namespace;
|
||||
import org.hibernate.boot.model.relational.QualifiedName;
|
||||
|
@ -94,7 +94,8 @@ public class MultipleHiLoPerTableGenerator implements PersistentIdentifierGenera
|
|||
|
||||
private QualifiedName qualifiedTableName;
|
||||
private String tableName;
|
||||
private String pkColumnName;
|
||||
private String segmentColumnName;
|
||||
private String segmentName;
|
||||
private String valueColumnName;
|
||||
private String query;
|
||||
private String insert;
|
||||
|
@ -254,62 +255,58 @@ public class MultipleHiLoPerTableGenerator implements PersistentIdentifierGenera
|
|||
|
||||
@SuppressWarnings({"StatementWithEmptyBody", "deprecation"})
|
||||
public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
|
||||
returnClass = type.getReturnedClass();
|
||||
|
||||
final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
|
||||
final ObjectNameNormalizer normalizer = (ObjectNameNormalizer) params.get( IDENTIFIER_NORMALIZER );
|
||||
|
||||
qualifiedTableName = QualifiedNameParser.INSTANCE.parse(
|
||||
ConfigurationHelper.getString( ID_TABLE, params, DEFAULT_TABLE ),
|
||||
normalizer.normalizeIdentifierQuoting( params.getProperty( CATALOG ) ),
|
||||
normalizer.normalizeIdentifierQuoting( params.getProperty( SCHEMA ) )
|
||||
);
|
||||
|
||||
tableName = jdbcEnvironment.getQualifiedObjectNameFormatter().format(
|
||||
qualifiedTableName,
|
||||
jdbcEnvironment.getDialect()
|
||||
);
|
||||
pkColumnName = normalizer.toDatabaseIdentifierText(
|
||||
ConfigurationHelper.getString( PK_COLUMN_NAME, params, DEFAULT_PK_COLUMN )
|
||||
);
|
||||
valueColumnName = normalizer.toDatabaseIdentifierText(
|
||||
ConfigurationHelper.getString( VALUE_COLUMN_NAME, params, DEFAULT_VALUE_COLUMN )
|
||||
);
|
||||
qualifiedTableName = determineGeneratorTableName( params, jdbcEnvironment );
|
||||
|
||||
segmentColumnName = determineSegmentColumnName( params, jdbcEnvironment );
|
||||
keySize = ConfigurationHelper.getInt( PK_LENGTH_NAME, params, DEFAULT_PK_LENGTH );
|
||||
String keyValue = ConfigurationHelper.getString( PK_VALUE_NAME, params, params.getProperty( TABLE ) );
|
||||
|
||||
query = "select " +
|
||||
valueColumnName +
|
||||
" from " +
|
||||
jdbcEnvironment.getDialect().appendLockHint( LockMode.PESSIMISTIC_WRITE, tableName ) +
|
||||
" where " + pkColumnName + " = '" + keyValue + "'" +
|
||||
jdbcEnvironment.getDialect().getForUpdateString();
|
||||
|
||||
update = "update " +
|
||||
tableName +
|
||||
" set " +
|
||||
valueColumnName +
|
||||
" = ? where " +
|
||||
valueColumnName +
|
||||
" = ? and " +
|
||||
pkColumnName +
|
||||
" = '" +
|
||||
keyValue
|
||||
+ "'";
|
||||
|
||||
insert = "insert into " + tableName +
|
||||
"(" + pkColumnName + ", " + valueColumnName + ") " +
|
||||
"values('" + keyValue + "', ?)";
|
||||
segmentName = ConfigurationHelper.getString( PK_VALUE_NAME, params, params.getProperty( TABLE ) );
|
||||
|
||||
valueColumnName = determineValueColumnName( params, jdbcEnvironment );
|
||||
|
||||
//hilo config
|
||||
maxLo = ConfigurationHelper.getInt( MAX_LO, params, Short.MAX_VALUE );
|
||||
returnClass = type.getReturnedClass();
|
||||
|
||||
if ( maxLo >= 1 ) {
|
||||
hiloOptimizer = new LegacyHiLoAlgorithmOptimizer( returnClass, maxLo );
|
||||
}
|
||||
}
|
||||
|
||||
protected QualifiedName determineGeneratorTableName(Properties params, JdbcEnvironment jdbcEnvironment) {
|
||||
final String tableName = ConfigurationHelper.getString( ID_TABLE, params, DEFAULT_TABLE );
|
||||
|
||||
if ( tableName.contains( "." ) ) {
|
||||
return QualifiedNameParser.INSTANCE.parse( tableName );
|
||||
}
|
||||
else {
|
||||
// todo : need to incorporate implicit catalog and schema names
|
||||
final Identifier catalog = jdbcEnvironment.getIdentifierHelper().toIdentifier(
|
||||
ConfigurationHelper.getString( CATALOG, params )
|
||||
);
|
||||
final Identifier schema = jdbcEnvironment.getIdentifierHelper().toIdentifier(
|
||||
ConfigurationHelper.getString( SCHEMA, params )
|
||||
);
|
||||
return new QualifiedNameParser.NameParts(
|
||||
catalog,
|
||||
schema,
|
||||
jdbcEnvironment.getIdentifierHelper().toIdentifier( tableName )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected String determineSegmentColumnName(Properties params, JdbcEnvironment jdbcEnvironment) {
|
||||
final String name = ConfigurationHelper.getString( PK_COLUMN_NAME, params, DEFAULT_PK_COLUMN );
|
||||
return jdbcEnvironment.getIdentifierHelper().toIdentifier( name ).render( jdbcEnvironment.getDialect() );
|
||||
}
|
||||
|
||||
protected String determineValueColumnName(Properties params, JdbcEnvironment jdbcEnvironment) {
|
||||
final String name = ConfigurationHelper.getString( VALUE_COLUMN_NAME, params, DEFAULT_VALUE_COLUMN );
|
||||
return jdbcEnvironment.getIdentifierHelper().toIdentifier( name ).render( jdbcEnvironment.getDialect() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerExportables(Database database) {
|
||||
final Namespace namespace = database.locateNamespace(
|
||||
|
@ -317,33 +314,73 @@ public class MultipleHiLoPerTableGenerator implements PersistentIdentifierGenera
|
|||
qualifiedTableName.getSchemaName()
|
||||
);
|
||||
|
||||
final Table table = namespace.createTable( qualifiedTableName.getObjectName(), false );
|
||||
table.setPrimaryKey( new PrimaryKey() );
|
||||
Table table = namespace.locateTable( qualifiedTableName.getObjectName() );
|
||||
if ( table == null ) {
|
||||
table = namespace.createTable( qualifiedTableName.getObjectName(), false );
|
||||
|
||||
final Column pkColumn = new ExportableColumn(
|
||||
database,
|
||||
table,
|
||||
pkColumnName,
|
||||
StringType.INSTANCE,
|
||||
database.getDialect().getTypeName( Types.VARCHAR, keySize, 0, 0 )
|
||||
);
|
||||
table.addColumn( pkColumn );
|
||||
table.getPrimaryKey().addColumn( pkColumn );
|
||||
// todo : note sure the best solution here. do we add the columns if missing? other?
|
||||
table.setPrimaryKey( new PrimaryKey() );
|
||||
|
||||
final Column valueColumn = new ExportableColumn(
|
||||
database,
|
||||
table,
|
||||
valueColumnName,
|
||||
LongType.INSTANCE
|
||||
final Column pkColumn = new ExportableColumn(
|
||||
database,
|
||||
table,
|
||||
segmentColumnName,
|
||||
StringType.INSTANCE,
|
||||
database.getDialect().getTypeName( Types.VARCHAR, keySize, 0, 0 )
|
||||
);
|
||||
pkColumn.setNullable( false );
|
||||
table.addColumn( pkColumn );
|
||||
table.getPrimaryKey().addColumn( pkColumn );
|
||||
|
||||
final Column valueColumn = new ExportableColumn(
|
||||
database,
|
||||
table,
|
||||
valueColumnName,
|
||||
LongType.INSTANCE
|
||||
);
|
||||
table.addColumn( valueColumn );
|
||||
}
|
||||
|
||||
final JdbcEnvironment jdbcEnvironment = database.getJdbcEnvironment();
|
||||
|
||||
// allow physical naming strategies a chance to kick in
|
||||
tableName = jdbcEnvironment.getQualifiedObjectNameFormatter().format(
|
||||
table.getQualifiedTableName(),
|
||||
jdbcEnvironment.getDialect()
|
||||
);
|
||||
table.addColumn( valueColumn );
|
||||
|
||||
query = "select " +
|
||||
valueColumnName +
|
||||
" from " +
|
||||
jdbcEnvironment.getDialect().appendLockHint( LockMode.PESSIMISTIC_WRITE, tableName ) +
|
||||
" where " + segmentColumnName + " = '" + segmentName + "'" +
|
||||
jdbcEnvironment.getDialect().getForUpdateString();
|
||||
|
||||
update = "update " +
|
||||
tableName +
|
||||
" set " +
|
||||
valueColumnName +
|
||||
" = ? where " +
|
||||
valueColumnName +
|
||||
" = ? and " +
|
||||
segmentColumnName +
|
||||
" = '" +
|
||||
segmentName
|
||||
+ "'";
|
||||
|
||||
insert = "insert into " + tableName +
|
||||
"(" + segmentColumnName + ", " + valueColumnName + ") " +
|
||||
"values('" + segmentName + "', ?)";
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public String[] sqlCreateStrings(Dialect dialect) throws HibernateException {
|
||||
return new String[] {
|
||||
dialect.getCreateTableString()
|
||||
+ ' ' + tableName + " ( "
|
||||
+ pkColumnName + ' ' + dialect.getTypeName( Types.VARCHAR, keySize, 0, 0 ) + ", "
|
||||
+ segmentColumnName + ' ' + dialect.getTypeName( Types.VARCHAR, keySize, 0, 0 ) + ", "
|
||||
+ valueColumnName + ' ' + dialect.getTypeName( Types.INTEGER )
|
||||
+ " )" + dialect.getTableTypeString()
|
||||
};
|
||||
|
|
|
@ -349,7 +349,6 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
identifierType = type;
|
||||
|
||||
final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
|
||||
final Dialect dialect = jdbcEnvironment.getDialect();
|
||||
|
||||
qualifiedTableName = determineGeneratorTableName( params, jdbcEnvironment );
|
||||
segmentColumnName = determineSegmentColumnName( params, jdbcEnvironment );
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.hibernate.boot.registry.StandardServiceRegistry;
|
|||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.dialect.DB2Dialect;
|
||||
import org.hibernate.id.MultipleHiLoPerTableGenerator;
|
||||
import org.hibernate.id.enhanced.TableGenerator;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.type.IntegerType;
|
||||
|
@ -24,7 +25,6 @@ import org.junit.Assert;
|
|||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -32,7 +32,7 @@ import static org.junit.Assert.assertTrue;
|
|||
public class Db2GenerationTest extends BaseUnitTestCase {
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-9850" )
|
||||
public void testDb2TableGeneratorCreation() {
|
||||
public void testNewGeneratorTableCreationOnDb2() {
|
||||
StandardServiceRegistry ssr = new StandardServiceRegistryBuilder()
|
||||
.applySetting( AvailableSettings.DIALECT, DB2Dialect.class.getName() )
|
||||
.build();
|
||||
|
@ -66,4 +66,34 @@ public class Db2GenerationTest extends BaseUnitTestCase {
|
|||
Assert.fail( "String [" + str + "] did not contain expected substring [" + subStr + "]" );
|
||||
}
|
||||
}
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-9850" )
|
||||
public void testLegacyGeneratorTableCreationOnDb2() {
|
||||
StandardServiceRegistry ssr = new StandardServiceRegistryBuilder()
|
||||
.applySetting( AvailableSettings.DIALECT, DB2Dialect.class.getName() )
|
||||
.build();
|
||||
|
||||
try {
|
||||
Metadata metadata = new MetadataSources( ssr )
|
||||
.buildMetadata();
|
||||
|
||||
assertEquals( 0, metadata.getDatabase().getDefaultNamespace().getTables().size() );
|
||||
|
||||
MultipleHiLoPerTableGenerator generator = new MultipleHiLoPerTableGenerator();
|
||||
|
||||
Properties properties = new Properties();
|
||||
generator.configure( IntegerType.INSTANCE, properties, ssr );
|
||||
|
||||
generator.registerExportables( metadata.getDatabase() );
|
||||
|
||||
assertEquals( 1, metadata.getDatabase().getDefaultNamespace().getTables().size() );
|
||||
|
||||
final Table table = metadata.getDatabase().getDefaultNamespace().getTables().iterator().next();
|
||||
final String[] createCommands = new DB2Dialect().getTableExporter().getSqlCreateStrings( table, metadata );
|
||||
assertContains( "sequence_name varchar(255) not null", createCommands[0] );
|
||||
}
|
||||
finally {
|
||||
StandardServiceRegistryBuilder.destroy( ssr );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue