HHH-12148 - Add setting indicating if the value stored in the table used by the @TableGenerator is the last value used or the next value to be used
This commit is contained in:
parent
2b7c2c883c
commit
9af5655100
|
@ -186,6 +186,9 @@ If true, generated identifier properties are reset to default values when object
|
|||
`*hibernate.id.optimizer.pooled.preferred*` (e.g. `none`, `hilo`, `legacy-hilo`, `pooled` (default value), `pooled-lo`, `pooled-lotl` or a fully-qualified name of the https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/id/enhanced/Optimizer.html[`Optimizer`] implementation)::
|
||||
When a generator specified an increment-size and an optimizer was not explicitly specified, which of the _pooled_ optimizers should be preferred?
|
||||
|
||||
`*hibernate.id.generator.stored_last_used*` (e.g. `true` (default value) or `false`)::
|
||||
If true, the value stored in the table used by the `@TableGenerator` is the last value used, if false the value is the next value to be used.
|
||||
|
||||
==== Quoting options
|
||||
|
||||
`*hibernate.globally_quoted_identifiers*` (e.g. `true` or `false` (default value))::
|
||||
|
|
|
@ -1790,4 +1790,13 @@ public interface AvailableSettings {
|
|||
* @see JpaCompliance#isJpaClosedComplianceEnabled()
|
||||
*/
|
||||
String JPA_CLOSED_COMPLIANCE = "hibernate.jpa.compliance.closed";
|
||||
|
||||
/**
|
||||
* True/False setting indicating if the value stored in the table used by the {@link javax.persistence.TableGenerator}
|
||||
* is the last value generated or the next value to be used.
|
||||
*
|
||||
* The default value is true.
|
||||
*
|
||||
*/
|
||||
String TABLE_GENERATOR_STORE_LAST_USED = "hibernate.id.generator.stored_last_used";
|
||||
}
|
||||
|
|
|
@ -812,9 +812,10 @@ public class BinderHelper {
|
|||
public String table() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int initialValue() {
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.hibernate.LockOptions;
|
|||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.model.naming.Identifier;
|
||||
import org.hibernate.boot.model.relational.Database;
|
||||
import org.hibernate.boot.model.relational.InitCommand;
|
||||
import org.hibernate.boot.model.relational.Namespace;
|
||||
import org.hibernate.boot.model.relational.QualifiedName;
|
||||
import org.hibernate.boot.model.relational.QualifiedNameParser;
|
||||
|
@ -226,6 +227,8 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
*/
|
||||
public static final String OPT_PARAM = "optimizer";
|
||||
|
||||
private boolean storeLastUsedValue;
|
||||
|
||||
|
||||
private Type identifierType;
|
||||
|
||||
|
@ -355,6 +358,8 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
|
||||
@Override
|
||||
public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
|
||||
storeLastUsedValue = serviceRegistry.getService( ConfigurationService.class )
|
||||
.getSetting( AvailableSettings.TABLE_GENERATOR_STORE_LAST_USED, StandardConverters.BOOLEAN, true );
|
||||
identifierType = type;
|
||||
|
||||
final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
|
||||
|
@ -374,11 +379,12 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
params,
|
||||
OptimizerFactory.determineImplicitOptimizerName( incrementSize, params )
|
||||
);
|
||||
int optimizerInitialValue = ConfigurationHelper.getInt( INITIAL_PARAM, params, -1 );
|
||||
optimizer = OptimizerFactory.buildOptimizer(
|
||||
optimizationStrategy,
|
||||
identifierType.getReturnedClass(),
|
||||
incrementSize,
|
||||
ConfigurationHelper.getInt( INITIAL_PARAM, params, -1 )
|
||||
optimizerInitialValue
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -542,6 +548,14 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
return "insert into " + renderedTableName + " (" + segmentColumnName + ", " + valueColumnName + ") " + " values (?,?)";
|
||||
}
|
||||
|
||||
protected InitCommand generateInsertInitCommand() {
|
||||
int value = initialValue;
|
||||
if ( storeLastUsedValue ) {
|
||||
value = initialValue - 1;
|
||||
}
|
||||
return new InitCommand( "insert into " + renderedTableName + "(" + segmentColumnName + ", " + valueColumnName + ")" + " values ('" + segmentValue + "'," + ( value ) + ")" );
|
||||
}
|
||||
|
||||
private IntegralDataTypeHolder makeValue() {
|
||||
return IdentifierGeneratorHelper.getIntegralDataTypeHolder( identifierType.getReturnedClass() );
|
||||
}
|
||||
|
@ -574,7 +588,14 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
selectPS.setString( 1, segmentValue );
|
||||
final ResultSet selectRS = executeQuery( selectPS, statsCollector );
|
||||
if ( !selectRS.next() ) {
|
||||
value.initialize( initialValue );
|
||||
long initializationValue;
|
||||
if ( storeLastUsedValue ) {
|
||||
initializationValue = initialValue - 1;
|
||||
}
|
||||
else {
|
||||
initializationValue = initialValue;
|
||||
}
|
||||
value.initialize( initializationValue );
|
||||
|
||||
try (PreparedStatement insertPS = prepareStatement(
|
||||
connection,
|
||||
|
@ -589,7 +610,14 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
}
|
||||
}
|
||||
else {
|
||||
value.initialize( selectRS, 1 );
|
||||
int defaultValue;
|
||||
if ( storeLastUsedValue ) {
|
||||
defaultValue = 0;
|
||||
}
|
||||
else {
|
||||
defaultValue = 1;
|
||||
}
|
||||
value.initialize( selectRS, defaultValue );
|
||||
}
|
||||
selectRS.close();
|
||||
}
|
||||
|
@ -625,8 +653,12 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
while ( rows == 0 );
|
||||
|
||||
accessCount++;
|
||||
|
||||
return value;
|
||||
if ( storeLastUsedValue ) {
|
||||
return value.increment();
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
},
|
||||
true
|
||||
|
@ -734,10 +766,10 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
table.getQualifiedTableName(),
|
||||
dialect
|
||||
);
|
||||
table.addInitCommand( generateInsertInitCommand() );
|
||||
|
||||
this.selectQuery = buildSelectQuery( dialect );
|
||||
this.updateQuery = buildUpdateQuery();
|
||||
this.insertQuery = buildInsertQuery();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,3 +27,11 @@ instead of zero-bade parameter binding to be consistent with JPA. That can temp
|
|||
reverted by setting the `hibernate.query.sql.jdbc_style_params_base` setting to `true` which
|
||||
reverts to expecting zero-based binding.
|
||||
|
||||
== Change in the `@TableGenerator` stored value
|
||||
|
||||
In order to be compliant with JPA specifications, the value stored by Hibernate 5.3 in the Table used by the `javax.persistence.TableGenerator` is the last value generated.
|
||||
Previous versions of Hibernate instead stored the next value to be used.
|
||||
|
||||
For backward compatibility a new setting, `hibernate.id.generator.stored_last_used`, has been introduced that gives the opportunity to fall back to the old Hibernate behaviour.
|
||||
Existing applications migrating to 5.3 and using @TableGenerator have to set `hibernate.id.generator.stored_last_used` to `false`.
|
||||
|
||||
|
|
Loading…
Reference in New Issue