HHH-9850 - Primary key generated for nullable column in sequence table
This commit is contained in:
parent
54a3bb244a
commit
1d61210826
|
@ -33,6 +33,7 @@ import org.hibernate.id.enhanced.AccessCallback;
|
||||||
import org.hibernate.id.enhanced.LegacyHiLoAlgorithmOptimizer;
|
import org.hibernate.id.enhanced.LegacyHiLoAlgorithmOptimizer;
|
||||||
import org.hibernate.internal.CoreLogging;
|
import org.hibernate.internal.CoreLogging;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
|
import org.hibernate.internal.log.DeprecationLogger;
|
||||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||||
import org.hibernate.jdbc.AbstractReturningWork;
|
import org.hibernate.jdbc.AbstractReturningWork;
|
||||||
import org.hibernate.jdbc.WorkExecutorVisitable;
|
import org.hibernate.jdbc.WorkExecutorVisitable;
|
||||||
|
@ -73,7 +74,10 @@ import org.hibernate.type.Type;
|
||||||
*
|
*
|
||||||
* @author Emmanuel Bernard
|
* @author Emmanuel Bernard
|
||||||
* @author <a href="mailto:kr@hbt.de">Klaus Richarz</a>.
|
* @author <a href="mailto:kr@hbt.de">Klaus Richarz</a>.
|
||||||
|
*
|
||||||
|
* @deprecated Use {@link org.hibernate.id.enhanced.TableGenerator} instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public class MultipleHiLoPerTableGenerator implements PersistentIdentifierGenerator, Configurable {
|
public class MultipleHiLoPerTableGenerator implements PersistentIdentifierGenerator, Configurable {
|
||||||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( MultipleHiLoPerTableGenerator.class );
|
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( MultipleHiLoPerTableGenerator.class );
|
||||||
|
|
||||||
|
@ -106,6 +110,8 @@ public class MultipleHiLoPerTableGenerator implements PersistentIdentifierGenera
|
||||||
private int keySize;
|
private int keySize;
|
||||||
|
|
||||||
public synchronized Serializable generate(final SessionImplementor session, Object obj) {
|
public synchronized Serializable generate(final SessionImplementor session, Object obj) {
|
||||||
|
DeprecationLogger.DEPRECATION_LOGGER.deprecatedTableGenerator( getClass().getName() );
|
||||||
|
|
||||||
final SqlStatementLogger statementLogger = session.getFactory().getServiceRegistry()
|
final SqlStatementLogger statementLogger = session.getFactory().getServiceRegistry()
|
||||||
.getService( JdbcServices.class )
|
.getService( JdbcServices.class )
|
||||||
.getSqlStatementLogger();
|
.getSqlStatementLogger();
|
||||||
|
|
|
@ -20,7 +20,7 @@ import org.hibernate.HibernateException;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.LockOptions;
|
import org.hibernate.LockOptions;
|
||||||
import org.hibernate.MappingException;
|
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.Database;
|
||||||
import org.hibernate.boot.model.relational.Namespace;
|
import org.hibernate.boot.model.relational.Namespace;
|
||||||
import org.hibernate.boot.model.relational.QualifiedName;
|
import org.hibernate.boot.model.relational.QualifiedName;
|
||||||
|
@ -351,10 +351,9 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
||||||
final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
|
final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
|
||||||
final Dialect dialect = jdbcEnvironment.getDialect();
|
final Dialect dialect = jdbcEnvironment.getDialect();
|
||||||
|
|
||||||
qualifiedTableName = determineGeneratorTableName( params, dialect );
|
qualifiedTableName = determineGeneratorTableName( params, jdbcEnvironment );
|
||||||
renderedTableName = jdbcEnvironment.getQualifiedObjectNameFormatter().format( qualifiedTableName, dialect );
|
segmentColumnName = determineSegmentColumnName( params, jdbcEnvironment );
|
||||||
segmentColumnName = determineSegmentColumnName( params, dialect );
|
valueColumnName = determineValueColumnName( params, jdbcEnvironment );
|
||||||
valueColumnName = determineValueColumnName( params, dialect );
|
|
||||||
|
|
||||||
segmentValue = determineSegmentValue( params );
|
segmentValue = determineSegmentValue( params );
|
||||||
|
|
||||||
|
@ -362,10 +361,6 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
||||||
initialValue = determineInitialValue( params );
|
initialValue = determineInitialValue( params );
|
||||||
incrementSize = determineIncrementSize( params );
|
incrementSize = determineIncrementSize( params );
|
||||||
|
|
||||||
this.selectQuery = buildSelectQuery( dialect );
|
|
||||||
this.updateQuery = buildUpdateQuery();
|
|
||||||
this.insertQuery = buildInsertQuery();
|
|
||||||
|
|
||||||
// if the increment size is greater than one, we prefer pooled optimization; but we
|
// if the increment size is greater than one, we prefer pooled optimization; but we
|
||||||
// need to see if the user prefers POOL or POOL_LO...
|
// need to see if the user prefers POOL or POOL_LO...
|
||||||
final String defaultPooledOptimizerStrategy = ConfigurationHelper.getBoolean( Environment.PREFER_POOLED_VALUES_LO, params, false )
|
final String defaultPooledOptimizerStrategy = ConfigurationHelper.getBoolean( Environment.PREFER_POOLED_VALUES_LO, params, false )
|
||||||
|
@ -390,18 +385,30 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
||||||
*
|
*
|
||||||
* @see #getTableName()
|
* @see #getTableName()
|
||||||
* @param params The params supplied in the generator config (plus some standard useful extras).
|
* @param params The params supplied in the generator config (plus some standard useful extras).
|
||||||
* @param dialect The dialect in effect
|
* @param jdbcEnvironment The JDBC environment
|
||||||
* @return The table name to use.
|
* @return The table name to use.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("UnusedParameters")
|
@SuppressWarnings("UnusedParameters")
|
||||||
protected QualifiedName determineGeneratorTableName(Properties params, Dialect dialect) {
|
protected QualifiedName determineGeneratorTableName(Properties params, JdbcEnvironment jdbcEnvironment) {
|
||||||
final ObjectNameNormalizer normalizer = (ObjectNameNormalizer) params.get( IDENTIFIER_NORMALIZER );
|
final String tableName = ConfigurationHelper.getString( TABLE_PARAM, params, DEF_TABLE );
|
||||||
|
|
||||||
return QualifiedNameParser.INSTANCE.parse(
|
if ( tableName.contains( "." ) ) {
|
||||||
ConfigurationHelper.getString( TABLE_PARAM, params, DEF_TABLE ),
|
return QualifiedNameParser.INSTANCE.parse( tableName );
|
||||||
normalizer.normalizeIdentifierQuoting( params.getProperty( CATALOG ) ),
|
}
|
||||||
normalizer.normalizeIdentifierQuoting( params.getProperty( SCHEMA ) )
|
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 )
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -412,14 +419,13 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
||||||
*
|
*
|
||||||
* @see #getSegmentColumnName()
|
* @see #getSegmentColumnName()
|
||||||
* @param params The params supplied in the generator config (plus some standard useful extras).
|
* @param params The params supplied in the generator config (plus some standard useful extras).
|
||||||
* @param dialect The dialect in effect
|
* @param jdbcEnvironment The JDBC environment
|
||||||
* @return The name of the segment column
|
* @return The name of the segment column
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("UnusedParameters")
|
@SuppressWarnings("UnusedParameters")
|
||||||
protected String determineSegmentColumnName(Properties params, Dialect dialect) {
|
protected String determineSegmentColumnName(Properties params, JdbcEnvironment jdbcEnvironment) {
|
||||||
final ObjectNameNormalizer normalizer = (ObjectNameNormalizer) params.get( IDENTIFIER_NORMALIZER );
|
|
||||||
final String name = ConfigurationHelper.getString( SEGMENT_COLUMN_PARAM, params, DEF_SEGMENT_COLUMN );
|
final String name = ConfigurationHelper.getString( SEGMENT_COLUMN_PARAM, params, DEF_SEGMENT_COLUMN );
|
||||||
return normalizer.toDatabaseIdentifierText( name );
|
return jdbcEnvironment.getIdentifierHelper().toIdentifier( name ).render( jdbcEnvironment.getDialect() );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -429,14 +435,13 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
||||||
*
|
*
|
||||||
* @see #getValueColumnName()
|
* @see #getValueColumnName()
|
||||||
* @param params The params supplied in the generator config (plus some standard useful extras).
|
* @param params The params supplied in the generator config (plus some standard useful extras).
|
||||||
* @param dialect The dialect in effect
|
* @param jdbcEnvironment The JDBC environment
|
||||||
* @return The name of the value column
|
* @return The name of the value column
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("UnusedParameters")
|
@SuppressWarnings("UnusedParameters")
|
||||||
protected String determineValueColumnName(Properties params, Dialect dialect) {
|
protected String determineValueColumnName(Properties params, JdbcEnvironment jdbcEnvironment) {
|
||||||
final ObjectNameNormalizer normalizer = (ObjectNameNormalizer) params.get( IDENTIFIER_NORMALIZER );
|
|
||||||
final String name = ConfigurationHelper.getString( VALUE_COLUMN_PARAM, params, DEF_VALUE_COLUMN );
|
final String name = ConfigurationHelper.getString( VALUE_COLUMN_PARAM, params, DEF_VALUE_COLUMN );
|
||||||
return normalizer.toDatabaseIdentifierText( name );
|
return jdbcEnvironment.getIdentifierHelper().toIdentifier( name ).render( jdbcEnvironment.getDialect() );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -667,8 +672,12 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
||||||
qualifiedTableName.getCatalogName(),
|
qualifiedTableName.getCatalogName(),
|
||||||
qualifiedTableName.getSchemaName()
|
qualifiedTableName.getSchemaName()
|
||||||
);
|
);
|
||||||
final Table table = namespace.createTable( qualifiedTableName.getObjectName(), false );
|
|
||||||
|
|
||||||
|
Table table = namespace.locateTable( qualifiedTableName.getObjectName() );
|
||||||
|
if ( table == null ) {
|
||||||
|
table = namespace.createTable( qualifiedTableName.getObjectName(), false );
|
||||||
|
|
||||||
|
// todo : note sure the best solution here. do we add the columns if missing? other?
|
||||||
final Column segmentColumn = new ExportableColumn(
|
final Column segmentColumn = new ExportableColumn(
|
||||||
database,
|
database,
|
||||||
table,
|
table,
|
||||||
|
@ -692,4 +701,16 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
||||||
);
|
);
|
||||||
table.addColumn( valueColumn );
|
table.addColumn( valueColumn );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// allow physical naming strategies a chance to kick in
|
||||||
|
this.renderedTableName = database.getJdbcEnvironment().getQualifiedObjectNameFormatter().format(
|
||||||
|
table.getQualifiedTableName(),
|
||||||
|
dialect
|
||||||
|
);
|
||||||
|
|
||||||
|
this.selectQuery = buildSelectQuery( dialect );
|
||||||
|
this.updateQuery = buildUpdateQuery();
|
||||||
|
this.insertQuery = buildInsertQuery();
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,4 +168,13 @@ public interface DeprecationLogger {
|
||||||
"See Hibernate Domain Model Mapping Guide for details."
|
"See Hibernate Domain Model Mapping Guide for details."
|
||||||
)
|
)
|
||||||
void deprecatedSequenceGenerator(String generatorImpl);
|
void deprecatedSequenceGenerator(String generatorImpl);
|
||||||
|
|
||||||
|
@LogMessage(level = WARN)
|
||||||
|
@Message(
|
||||||
|
id = 90000015,
|
||||||
|
value = "Found use of deprecated [%s] table-based id generator; " +
|
||||||
|
"use org.hibernate.id.enhanced.TableGenerator instead. " +
|
||||||
|
"See Hibernate Domain Model Mapping Guide for details."
|
||||||
|
)
|
||||||
|
void deprecatedTableGenerator(String generatorImpl);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.idgen.enhanced.table;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.hibernate.boot.Metadata;
|
||||||
|
import org.hibernate.boot.MetadataSources;
|
||||||
|
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.enhanced.TableGenerator;
|
||||||
|
import org.hibernate.mapping.Table;
|
||||||
|
import org.hibernate.type.IntegerType;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class Db2GenerationTest extends BaseUnitTestCase {
|
||||||
|
@Test
|
||||||
|
@TestForIssue( jiraKey = "HHH-9850" )
|
||||||
|
public void testDb2TableGeneratorCreation() {
|
||||||
|
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() );
|
||||||
|
|
||||||
|
TableGenerator generator = new TableGenerator();
|
||||||
|
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertContains(String subStr, String str) {
|
||||||
|
if ( !str.contains( subStr ) ) {
|
||||||
|
Assert.fail( "String [" + str + "] did not contain expected substring [" + subStr + "]" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue