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)::
|
`*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?
|
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
|
==== Quoting options
|
||||||
|
|
||||||
`*hibernate.globally_quoted_identifiers*` (e.g. `true` or `false` (default value))::
|
`*hibernate.globally_quoted_identifiers*` (e.g. `true` or `false` (default value))::
|
||||||
|
|
|
@ -1790,4 +1790,13 @@ public interface AvailableSettings {
|
||||||
* @see JpaCompliance#isJpaClosedComplianceEnabled()
|
* @see JpaCompliance#isJpaClosedComplianceEnabled()
|
||||||
*/
|
*/
|
||||||
String JPA_CLOSED_COMPLIANCE = "hibernate.jpa.compliance.closed";
|
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() {
|
public String table() {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int initialValue() {
|
public int initialValue() {
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.hibernate.LockOptions;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.boot.model.naming.Identifier;
|
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.InitCommand;
|
||||||
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;
|
||||||
import org.hibernate.boot.model.relational.QualifiedNameParser;
|
import org.hibernate.boot.model.relational.QualifiedNameParser;
|
||||||
|
@ -226,6 +227,8 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
||||||
*/
|
*/
|
||||||
public static final String OPT_PARAM = "optimizer";
|
public static final String OPT_PARAM = "optimizer";
|
||||||
|
|
||||||
|
private boolean storeLastUsedValue;
|
||||||
|
|
||||||
|
|
||||||
private Type identifierType;
|
private Type identifierType;
|
||||||
|
|
||||||
|
@ -355,6 +358,8 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
|
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;
|
identifierType = type;
|
||||||
|
|
||||||
final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
|
final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
|
||||||
|
@ -374,11 +379,12 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
||||||
params,
|
params,
|
||||||
OptimizerFactory.determineImplicitOptimizerName( incrementSize, params )
|
OptimizerFactory.determineImplicitOptimizerName( incrementSize, params )
|
||||||
);
|
);
|
||||||
|
int optimizerInitialValue = ConfigurationHelper.getInt( INITIAL_PARAM, params, -1 );
|
||||||
optimizer = OptimizerFactory.buildOptimizer(
|
optimizer = OptimizerFactory.buildOptimizer(
|
||||||
optimizationStrategy,
|
optimizationStrategy,
|
||||||
identifierType.getReturnedClass(),
|
identifierType.getReturnedClass(),
|
||||||
incrementSize,
|
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 (?,?)";
|
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() {
|
private IntegralDataTypeHolder makeValue() {
|
||||||
return IdentifierGeneratorHelper.getIntegralDataTypeHolder( identifierType.getReturnedClass() );
|
return IdentifierGeneratorHelper.getIntegralDataTypeHolder( identifierType.getReturnedClass() );
|
||||||
}
|
}
|
||||||
|
@ -574,7 +588,14 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
||||||
selectPS.setString( 1, segmentValue );
|
selectPS.setString( 1, segmentValue );
|
||||||
final ResultSet selectRS = executeQuery( selectPS, statsCollector );
|
final ResultSet selectRS = executeQuery( selectPS, statsCollector );
|
||||||
if ( !selectRS.next() ) {
|
if ( !selectRS.next() ) {
|
||||||
value.initialize( initialValue );
|
long initializationValue;
|
||||||
|
if ( storeLastUsedValue ) {
|
||||||
|
initializationValue = initialValue - 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
initializationValue = initialValue;
|
||||||
|
}
|
||||||
|
value.initialize( initializationValue );
|
||||||
|
|
||||||
try (PreparedStatement insertPS = prepareStatement(
|
try (PreparedStatement insertPS = prepareStatement(
|
||||||
connection,
|
connection,
|
||||||
|
@ -589,7 +610,14 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
value.initialize( selectRS, 1 );
|
int defaultValue;
|
||||||
|
if ( storeLastUsedValue ) {
|
||||||
|
defaultValue = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
defaultValue = 1;
|
||||||
|
}
|
||||||
|
value.initialize( selectRS, defaultValue );
|
||||||
}
|
}
|
||||||
selectRS.close();
|
selectRS.close();
|
||||||
}
|
}
|
||||||
|
@ -625,9 +653,13 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
||||||
while ( rows == 0 );
|
while ( rows == 0 );
|
||||||
|
|
||||||
accessCount++;
|
accessCount++;
|
||||||
|
if ( storeLastUsedValue ) {
|
||||||
|
return value.increment();
|
||||||
|
}
|
||||||
|
else {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
@ -734,10 +766,10 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
||||||
table.getQualifiedTableName(),
|
table.getQualifiedTableName(),
|
||||||
dialect
|
dialect
|
||||||
);
|
);
|
||||||
|
table.addInitCommand( generateInsertInitCommand() );
|
||||||
|
|
||||||
this.selectQuery = buildSelectQuery( dialect );
|
this.selectQuery = buildSelectQuery( dialect );
|
||||||
this.updateQuery = buildUpdateQuery();
|
this.updateQuery = buildUpdateQuery();
|
||||||
this.insertQuery = buildInsertQuery();
|
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
|
reverted by setting the `hibernate.query.sql.jdbc_style_params_base` setting to `true` which
|
||||||
reverts to expecting zero-based binding.
|
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