mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-17 08:35:13 +00:00
HHH-4905 - Allow consistent handling of numeric primary key values by any integral data type
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18789 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
19de9d4ed9
commit
23ee88a55b
@ -91,7 +91,9 @@ public final Boolean isUnsaved(Object version) throws MappingException {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public Object getDefaultValue(Object currentValue) {
|
public Object getDefaultValue(Object currentValue) {
|
||||||
return IdentifierGeneratorHelper.createNumber( -1l, currentValue.getClass() );
|
return IdentifierGeneratorHelper.getIntegralDataTypeHolder( currentValue.getClass() )
|
||||||
|
.initialize( -1L )
|
||||||
|
.makeValue();
|
||||||
}
|
}
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "VERSION_NEGATIVE";
|
return "VERSION_NEGATIVE";
|
||||||
|
@ -25,6 +25,9 @@
|
|||||||
package org.hibernate.id;
|
package org.hibernate.id;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
|
||||||
@ -119,10 +122,17 @@ else if ( clazz == Short.class ) {
|
|||||||
else if ( clazz == String.class ) {
|
else if ( clazz == String.class ) {
|
||||||
return rs.getString( 1 );
|
return rs.getString( 1 );
|
||||||
}
|
}
|
||||||
else {
|
else if ( clazz == BigInteger.class ) {
|
||||||
throw new IdentifierGenerationException( "this id generator generates long, integer, short or string" );
|
return rs.getBigDecimal( 1 ).setScale( 0, BigDecimal.ROUND_UNNECESSARY ).toBigInteger();
|
||||||
|
}
|
||||||
|
else if ( clazz == BigDecimal.class ) {
|
||||||
|
return rs.getBigDecimal( 1 ).setScale( 0, BigDecimal.ROUND_UNNECESSARY );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IdentifierGenerationException(
|
||||||
|
"unrecognized id type : " + type.getName() + " -> " + clazz.getName()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -130,8 +140,12 @@ else if ( clazz == String.class ) {
|
|||||||
*
|
*
|
||||||
* @param value The primitive value to wrap.
|
* @param value The primitive value to wrap.
|
||||||
* @param clazz The Java numeric type in which to wrap the value.
|
* @param clazz The Java numeric type in which to wrap the value.
|
||||||
|
*
|
||||||
* @return The wrapped type.
|
* @return The wrapped type.
|
||||||
|
*
|
||||||
* @throws IdentifierGenerationException Indicates an unhandled 'clazz'.
|
* @throws IdentifierGenerationException Indicates an unhandled 'clazz'.
|
||||||
|
*
|
||||||
|
* @deprecated Use the {@link #getIntegralDataTypeHolder holders} instead.
|
||||||
*/
|
*/
|
||||||
public static Number createNumber(long value, Class clazz) throws IdentifierGenerationException {
|
public static Number createNumber(long value, Class clazz) throws IdentifierGenerationException {
|
||||||
if ( clazz == Long.class ) {
|
if ( clazz == Long.class ) {
|
||||||
@ -144,7 +158,510 @@ else if ( clazz == Short.class ) {
|
|||||||
return new Short( ( short ) value );
|
return new Short( ( short ) value );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new IdentifierGenerationException( "this id generator generates long, integer, short" );
|
throw new IdentifierGenerationException( "unrecognized id type : " + clazz.getName() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IntegralDataTypeHolder getIntegralDataTypeHolder(Class integralType) {
|
||||||
|
if ( integralType == Long.class
|
||||||
|
|| integralType == Integer.class
|
||||||
|
|| integralType == Short.class ) {
|
||||||
|
return new BasicHolder( integralType );
|
||||||
|
}
|
||||||
|
else if ( integralType == BigInteger.class ) {
|
||||||
|
return new BigIntegerHolder();
|
||||||
|
}
|
||||||
|
else if ( integralType == BigDecimal.class ) {
|
||||||
|
return new BigDecimalHolder();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IdentifierGenerationException(
|
||||||
|
"Unknown integral data type for ids : " + integralType.getName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long extractLong(IntegralDataTypeHolder holder) {
|
||||||
|
if ( holder.getClass() == BasicHolder.class ) {
|
||||||
|
( (BasicHolder) holder ).checkInitialized();
|
||||||
|
return ( (BasicHolder) holder ).value;
|
||||||
|
}
|
||||||
|
else if ( holder.getClass() == BigIntegerHolder.class ) {
|
||||||
|
( (BigIntegerHolder) holder ).checkInitialized();
|
||||||
|
return ( (BigIntegerHolder) holder ).value.longValue();
|
||||||
|
}
|
||||||
|
else if ( holder.getClass() == BigDecimalHolder.class ) {
|
||||||
|
( (BigDecimalHolder) holder ).checkInitialized();
|
||||||
|
return ( (BigDecimalHolder) holder ).value.longValue();
|
||||||
|
}
|
||||||
|
throw new IdentifierGenerationException( "Unknown IntegralDataTypeHolder impl [" + holder + "]" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BigInteger extractBigInteger(IntegralDataTypeHolder holder) {
|
||||||
|
if ( holder.getClass() == BasicHolder.class ) {
|
||||||
|
( (BasicHolder) holder ).checkInitialized();
|
||||||
|
return BigInteger.valueOf( ( (BasicHolder) holder ).value );
|
||||||
|
}
|
||||||
|
else if ( holder.getClass() == BigIntegerHolder.class ) {
|
||||||
|
( (BigIntegerHolder) holder ).checkInitialized();
|
||||||
|
return ( (BigIntegerHolder) holder ).value;
|
||||||
|
}
|
||||||
|
else if ( holder.getClass() == BigDecimalHolder.class ) {
|
||||||
|
( (BigDecimalHolder) holder ).checkInitialized();
|
||||||
|
// scale should already be set...
|
||||||
|
return ( (BigDecimalHolder) holder ).value.toBigInteger();
|
||||||
|
}
|
||||||
|
throw new IdentifierGenerationException( "Unknown IntegralDataTypeHolder impl [" + holder + "]" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BigDecimal extractBigDecimal(IntegralDataTypeHolder holder) {
|
||||||
|
if ( holder.getClass() == BasicHolder.class ) {
|
||||||
|
( (BasicHolder) holder ).checkInitialized();
|
||||||
|
return BigDecimal.valueOf( ( (BasicHolder) holder ).value );
|
||||||
|
}
|
||||||
|
else if ( holder.getClass() == BigIntegerHolder.class ) {
|
||||||
|
( (BigIntegerHolder) holder ).checkInitialized();
|
||||||
|
return new BigDecimal( ( (BigIntegerHolder) holder ).value );
|
||||||
|
}
|
||||||
|
else if ( holder.getClass() == BigDecimalHolder.class ) {
|
||||||
|
( (BigDecimalHolder) holder ).checkInitialized();
|
||||||
|
// scale should already be set...
|
||||||
|
return ( (BigDecimalHolder) holder ).value;
|
||||||
|
}
|
||||||
|
throw new IdentifierGenerationException( "Unknown IntegralDataTypeHolder impl [" + holder + "]" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BasicHolder implements IntegralDataTypeHolder {
|
||||||
|
private final Class exactType;
|
||||||
|
private long value = Long.MIN_VALUE;
|
||||||
|
|
||||||
|
public BasicHolder(Class exactType) {
|
||||||
|
this.exactType = exactType;
|
||||||
|
if ( exactType != Long.class && exactType != Integer.class && exactType != Short.class ) {
|
||||||
|
throw new IdentifierGenerationException( "Invalid type for basic integral holder : " + exactType );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getActualLongValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder initialize(long value) {
|
||||||
|
this.value = value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder initialize(ResultSet resultSet, long defaultValue) throws SQLException {
|
||||||
|
long value = resultSet.getLong( 1 );
|
||||||
|
if ( resultSet.wasNull() ) {
|
||||||
|
value = defaultValue;
|
||||||
|
}
|
||||||
|
return initialize( value );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bind(PreparedStatement preparedStatement, int position) throws SQLException {
|
||||||
|
// TODO : bind it as 'exact type'? Not sure if that gains us anything...
|
||||||
|
preparedStatement.setLong( position, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder increment() {
|
||||||
|
checkInitialized();
|
||||||
|
value++;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkInitialized() {
|
||||||
|
if ( value == Long.MIN_VALUE ) {
|
||||||
|
throw new IdentifierGenerationException( "integral holder was not initialized" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder add(long addend) {
|
||||||
|
checkInitialized();
|
||||||
|
value += addend;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder decrement() {
|
||||||
|
checkInitialized();
|
||||||
|
value--;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder subtract(long subtrahend) {
|
||||||
|
checkInitialized();
|
||||||
|
value -= subtrahend;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder multiplyBy(IntegralDataTypeHolder factor) {
|
||||||
|
return multiplyBy( extractLong( factor ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder multiplyBy(long factor) {
|
||||||
|
checkInitialized();
|
||||||
|
value *= factor;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean eq(IntegralDataTypeHolder other) {
|
||||||
|
return eq( extractLong( other ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean eq(long value) {
|
||||||
|
checkInitialized();
|
||||||
|
return this.value == value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean lt(IntegralDataTypeHolder other) {
|
||||||
|
return lt( extractLong( other ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean lt(long value) {
|
||||||
|
checkInitialized();
|
||||||
|
return this.value < value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean gt(IntegralDataTypeHolder other) {
|
||||||
|
return gt( extractLong( other ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean gt(long value) {
|
||||||
|
checkInitialized();
|
||||||
|
return this.value > value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder copy() {
|
||||||
|
BasicHolder copy = new BasicHolder( exactType );
|
||||||
|
copy.value = value;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Number makeValue() {
|
||||||
|
// TODO : should we check for truncation?
|
||||||
|
checkInitialized();
|
||||||
|
if ( exactType == Long.class ) {
|
||||||
|
return new Long( value );
|
||||||
|
}
|
||||||
|
else if ( exactType == Integer.class ) {
|
||||||
|
return new Integer( ( int ) value );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new Short( ( short ) value );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Number makeValueThenIncrement() {
|
||||||
|
final Number result = makeValue();
|
||||||
|
value++;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Number makeValueThenAdd(long addend) {
|
||||||
|
final Number result = makeValue();
|
||||||
|
value += addend;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "BasicHolder[" + exactType.getName() + "[" + value + "]]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if ( this == o ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( o == null || getClass() != o.getClass() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicHolder that = (BasicHolder) o;
|
||||||
|
|
||||||
|
return value == that.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
return (int) ( value ^ ( value >>> 32 ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BigIntegerHolder implements IntegralDataTypeHolder {
|
||||||
|
private BigInteger value;
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder initialize(long value) {
|
||||||
|
this.value = BigInteger.valueOf( value );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder initialize(ResultSet resultSet, long defaultValue) throws SQLException {
|
||||||
|
final BigDecimal rsValue = resultSet.getBigDecimal( 1 );
|
||||||
|
if ( resultSet.wasNull() ) {
|
||||||
|
return initialize( defaultValue );
|
||||||
|
}
|
||||||
|
this.value = rsValue.setScale( 0, BigDecimal.ROUND_UNNECESSARY ).toBigInteger();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bind(PreparedStatement preparedStatement, int position) throws SQLException {
|
||||||
|
preparedStatement.setBigDecimal( position, new BigDecimal( value ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder increment() {
|
||||||
|
checkInitialized();
|
||||||
|
value = value.add( BigInteger.ONE );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkInitialized() {
|
||||||
|
if ( value == null ) {
|
||||||
|
throw new IdentifierGenerationException( "integral holder was not initialized" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder add(long increment) {
|
||||||
|
checkInitialized();
|
||||||
|
value = value.add( BigInteger.valueOf( increment ) );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder decrement() {
|
||||||
|
checkInitialized();
|
||||||
|
value = value.subtract( BigInteger.ONE );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder subtract(long subtrahend) {
|
||||||
|
checkInitialized();
|
||||||
|
value = value.subtract( BigInteger.valueOf( subtrahend ) );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder multiplyBy(IntegralDataTypeHolder factor) {
|
||||||
|
checkInitialized();
|
||||||
|
value = value.multiply( extractBigInteger( factor ) );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder multiplyBy(long factor) {
|
||||||
|
checkInitialized();
|
||||||
|
value = value.multiply( BigInteger.valueOf( factor ) );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean eq(IntegralDataTypeHolder other) {
|
||||||
|
checkInitialized();
|
||||||
|
return value.compareTo( extractBigInteger( other ) ) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean eq(long value) {
|
||||||
|
checkInitialized();
|
||||||
|
return this.value.compareTo( BigInteger.valueOf( value ) ) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean lt(IntegralDataTypeHolder other) {
|
||||||
|
checkInitialized();
|
||||||
|
return value.compareTo( extractBigInteger( other ) ) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean lt(long value) {
|
||||||
|
checkInitialized();
|
||||||
|
return this.value.compareTo( BigInteger.valueOf( value ) ) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean gt(IntegralDataTypeHolder other) {
|
||||||
|
checkInitialized();
|
||||||
|
return value.compareTo( extractBigInteger( other ) ) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean gt(long value) {
|
||||||
|
checkInitialized();
|
||||||
|
return this.value.compareTo( BigInteger.valueOf( value ) ) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder copy() {
|
||||||
|
BigIntegerHolder copy = new BigIntegerHolder();
|
||||||
|
copy.value = value;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Number makeValue() {
|
||||||
|
checkInitialized();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Number makeValueThenIncrement() {
|
||||||
|
final Number result = makeValue();
|
||||||
|
value = value.add( BigInteger.ONE );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Number makeValueThenAdd(long addend) {
|
||||||
|
final Number result = makeValue();
|
||||||
|
value = value.add( BigInteger.valueOf( addend ) );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "BigIntegerHolder[" + value + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if ( this == o ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( o == null || getClass() != o.getClass() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BigIntegerHolder that = (BigIntegerHolder) o;
|
||||||
|
|
||||||
|
return this.value == null
|
||||||
|
? that.value == null
|
||||||
|
: value.equals( that.value );
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
return value != null ? value.hashCode() : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BigDecimalHolder implements IntegralDataTypeHolder {
|
||||||
|
private BigDecimal value;
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder initialize(long value) {
|
||||||
|
this.value = BigDecimal.valueOf( value );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder initialize(ResultSet resultSet, long defaultValue) throws SQLException {
|
||||||
|
final BigDecimal rsValue = resultSet.getBigDecimal( 1 );
|
||||||
|
if ( resultSet.wasNull() ) {
|
||||||
|
return initialize( defaultValue );
|
||||||
|
}
|
||||||
|
this.value = rsValue.setScale( 0, BigDecimal.ROUND_UNNECESSARY );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bind(PreparedStatement preparedStatement, int position) throws SQLException {
|
||||||
|
preparedStatement.setBigDecimal( position, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder increment() {
|
||||||
|
checkInitialized();
|
||||||
|
value = value.add( BigDecimal.ONE );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkInitialized() {
|
||||||
|
if ( value == null ) {
|
||||||
|
throw new IdentifierGenerationException( "integral holder was not initialized" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder add(long increment) {
|
||||||
|
checkInitialized();
|
||||||
|
value = value.add( BigDecimal.valueOf( increment ) );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder decrement() {
|
||||||
|
checkInitialized();
|
||||||
|
value = value.subtract( BigDecimal.ONE );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder subtract(long subtrahend) {
|
||||||
|
checkInitialized();
|
||||||
|
value = value.subtract( BigDecimal.valueOf( subtrahend ) );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder multiplyBy(IntegralDataTypeHolder factor) {
|
||||||
|
checkInitialized();
|
||||||
|
value = value.multiply( extractBigDecimal( factor ) );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder multiplyBy(long factor) {
|
||||||
|
checkInitialized();
|
||||||
|
value = value.multiply( BigDecimal.valueOf( factor ) );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean eq(IntegralDataTypeHolder other) {
|
||||||
|
checkInitialized();
|
||||||
|
return value.compareTo( extractBigDecimal( other ) ) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean eq(long value) {
|
||||||
|
checkInitialized();
|
||||||
|
return this.value.compareTo( BigDecimal.valueOf( value ) ) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean lt(IntegralDataTypeHolder other) {
|
||||||
|
checkInitialized();
|
||||||
|
return value.compareTo( extractBigDecimal( other ) ) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean lt(long value) {
|
||||||
|
checkInitialized();
|
||||||
|
return this.value.compareTo( BigDecimal.valueOf( value ) ) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean gt(IntegralDataTypeHolder other) {
|
||||||
|
checkInitialized();
|
||||||
|
return value.compareTo( extractBigDecimal( other ) ) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean gt(long value) {
|
||||||
|
checkInitialized();
|
||||||
|
return this.value.compareTo( BigDecimal.valueOf( value ) ) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegralDataTypeHolder copy() {
|
||||||
|
BigDecimalHolder copy = new BigDecimalHolder();
|
||||||
|
copy.value = value;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Number makeValue() {
|
||||||
|
checkInitialized();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Number makeValueThenIncrement() {
|
||||||
|
final Number result = makeValue();
|
||||||
|
value = value.add( BigDecimal.ONE );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Number makeValueThenAdd(long addend) {
|
||||||
|
final Number result = makeValue();
|
||||||
|
value = value.add( BigDecimal.valueOf( addend ) );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "BigDecimalHolder[" + value + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if ( this == o ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( o == null || getClass() != o.getClass() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BigDecimalHolder that = (BigDecimalHolder) o;
|
||||||
|
|
||||||
|
return this.value == null
|
||||||
|
? that.value == null
|
||||||
|
: this.value.equals( that.value );
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
return value != null ? value.hashCode() : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||||
* indicated by the @author tags or express copyright attribution
|
* indicated by the @author tags or express copyright attribution
|
||||||
* statements applied by the authors. All third-party contributions are
|
* statements applied by the authors. All third-party contributions are
|
||||||
* distributed under license by Red Hat Middleware LLC.
|
* distributed under license by Red Hat Inc.
|
||||||
*
|
*
|
||||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
@ -20,7 +20,6 @@
|
|||||||
* Free Software Foundation, Inc.
|
* Free Software Foundation, Inc.
|
||||||
* 51 Franklin Street, Fifth Floor
|
* 51 Franklin Street, Fifth Floor
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
package org.hibernate.id;
|
package org.hibernate.id;
|
||||||
|
|
||||||
@ -53,20 +52,21 @@
|
|||||||
* (The tables parameter specified a comma-separated list of table names.)
|
* (The tables parameter specified a comma-separated list of table names.)
|
||||||
*
|
*
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class IncrementGenerator implements IdentifierGenerator, Configurable {
|
public class IncrementGenerator implements IdentifierGenerator, Configurable {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(IncrementGenerator.class);
|
private static final Logger log = LoggerFactory.getLogger(IncrementGenerator.class);
|
||||||
|
|
||||||
private long next;
|
|
||||||
private String sql;
|
|
||||||
private Class returnClass;
|
private Class returnClass;
|
||||||
|
private String sql;
|
||||||
|
|
||||||
|
private IntegralDataTypeHolder previousValueHolder;
|
||||||
|
|
||||||
public synchronized Serializable generate(SessionImplementor session, Object object) throws HibernateException {
|
public synchronized Serializable generate(SessionImplementor session, Object object) throws HibernateException {
|
||||||
if ( sql != null ) {
|
if ( sql != null ) {
|
||||||
getNext( session );
|
initializePreviousValueHolder( session );
|
||||||
}
|
}
|
||||||
return IdentifierGeneratorHelper.createNumber( next++, returnClass );
|
return previousValueHolder.makeValueThenIncrement();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void configure(Type type, Properties params, Dialect dialect) throws MappingException {
|
public void configure(Type type, Properties params, Dialect dialect) throws MappingException {
|
||||||
@ -117,22 +117,23 @@ public void configure(Type type, Properties params, Dialect dialect) throws Mapp
|
|||||||
sql = "select max(" + column + ") from " + buf.toString();
|
sql = "select max(" + column + ") from " + buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getNext( SessionImplementor session ) {
|
private void initializePreviousValueHolder(SessionImplementor session) {
|
||||||
|
previousValueHolder = IdentifierGeneratorHelper.getIntegralDataTypeHolder( returnClass );
|
||||||
|
|
||||||
log.debug( "fetching initial value: " + sql );
|
log.debug( "fetching initial value: " + sql );
|
||||||
try {
|
try {
|
||||||
PreparedStatement st = session.getBatcher().prepareSelectStatement(sql);
|
PreparedStatement st = session.getBatcher().prepareSelectStatement( sql );
|
||||||
try {
|
try {
|
||||||
ResultSet rs = st.executeQuery();
|
ResultSet rs = st.executeQuery();
|
||||||
try {
|
try {
|
||||||
if ( rs.next() ) {
|
if ( rs.next() ) {
|
||||||
next = rs.getLong(1) + 1;
|
previousValueHolder.initialize( rs, 0L ).increment();
|
||||||
if ( rs.wasNull() ) next = 1;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
next = 1;
|
previousValueHolder.initialize( 1L );
|
||||||
}
|
}
|
||||||
sql=null;
|
sql = null;
|
||||||
log.debug("first free id: " + next);
|
log.debug( "first free id: " + previousValueHolder.makeValue() );
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
rs.close();
|
rs.close();
|
||||||
@ -141,7 +142,6 @@ private void getNext( SessionImplementor session ) {
|
|||||||
finally {
|
finally {
|
||||||
session.getBatcher().closeStatement(st);
|
session.getBatcher().closeStatement(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (SQLException sqle) {
|
catch (SQLException sqle) {
|
||||||
throw JDBCExceptionHelper.convert(
|
throw JDBCExceptionHelper.convert(
|
||||||
|
206
core/src/main/java/org/hibernate/id/IntegralDataTypeHolder.java
Normal file
206
core/src/main/java/org/hibernate/id/IntegralDataTypeHolder.java
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.id;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a common api for dealing with data of integral data type.
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public interface IntegralDataTypeHolder extends Serializable {
|
||||||
|
/**
|
||||||
|
* Initialize the internal value from the given primitive long.
|
||||||
|
*
|
||||||
|
* @param value The primitive integral value.
|
||||||
|
*
|
||||||
|
* @return <tt>this</tt>, for method chaining
|
||||||
|
*/
|
||||||
|
public IntegralDataTypeHolder initialize(long value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the internal value from the given result set, using the specified default value
|
||||||
|
* if we could not get a value from the result set (aka result was null).
|
||||||
|
*
|
||||||
|
* @param resultSet The JDBC result set
|
||||||
|
* @param defaultValue The default value to use if we did not get a result set value.
|
||||||
|
*
|
||||||
|
* @return <tt>this</tt>, for method chaining
|
||||||
|
*
|
||||||
|
* @throws SQLException Any exception from accessing the result set
|
||||||
|
*/
|
||||||
|
public IntegralDataTypeHolder initialize(ResultSet resultSet, long defaultValue) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bind this holders internal value to the given result set.
|
||||||
|
*
|
||||||
|
* @param preparedStatement The JDBC prepared statement
|
||||||
|
* @param position The position at which to bind
|
||||||
|
*
|
||||||
|
* @throws SQLException Any exception from accessing the statement
|
||||||
|
*/
|
||||||
|
public void bind(PreparedStatement preparedStatement, int position) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Equivalent to a ++ operation
|
||||||
|
*
|
||||||
|
* @return <tt>this</tt>, for method chaining
|
||||||
|
*/
|
||||||
|
public IntegralDataTypeHolder increment();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform an addition
|
||||||
|
*
|
||||||
|
* @param addend The value to add to this integral.
|
||||||
|
*
|
||||||
|
* @return <tt>this</tt>, for method chaining
|
||||||
|
*/
|
||||||
|
public IntegralDataTypeHolder add(long addend);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Equivalent to a -- operation
|
||||||
|
*
|
||||||
|
* @return <tt>this</tt>, for method chaining
|
||||||
|
*/
|
||||||
|
public IntegralDataTypeHolder decrement();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform a subtraction
|
||||||
|
*
|
||||||
|
* @param subtrahend The value to subtract from this integral.
|
||||||
|
*
|
||||||
|
* @return <tt>this</tt>, for method chaining
|
||||||
|
*/
|
||||||
|
public IntegralDataTypeHolder subtract(long subtrahend);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform a multiplication.
|
||||||
|
*
|
||||||
|
* @param factor The factor by which to multiple this integral
|
||||||
|
*
|
||||||
|
* @return <tt>this</tt>, for method chaining
|
||||||
|
*/
|
||||||
|
public IntegralDataTypeHolder multiplyBy(IntegralDataTypeHolder factor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform a multiplication.
|
||||||
|
*
|
||||||
|
* @param factor The factor by which to multiple this integral
|
||||||
|
*
|
||||||
|
* @return <tt>this</tt>, for method chaining
|
||||||
|
*/
|
||||||
|
public IntegralDataTypeHolder multiplyBy(long factor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform an equality comparison check
|
||||||
|
*
|
||||||
|
* @param other The other value to check against our internal state
|
||||||
|
*
|
||||||
|
* @return True if the two are equal
|
||||||
|
*/
|
||||||
|
public boolean eq(IntegralDataTypeHolder other);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform an equality comparison check
|
||||||
|
*
|
||||||
|
* @param other The other value to check against our internal state
|
||||||
|
*
|
||||||
|
* @return True if the two are equal
|
||||||
|
*/
|
||||||
|
public boolean eq(long other);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform a "less than" comparison check. We check to see if our value is less than
|
||||||
|
* the incoming value...
|
||||||
|
*
|
||||||
|
* @param other The other value to check against our internal state
|
||||||
|
*
|
||||||
|
* @return True if our value is less than the 'other' value.
|
||||||
|
*/
|
||||||
|
public boolean lt(IntegralDataTypeHolder other);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform a "less than" comparison check. We check to see if our value is less than
|
||||||
|
* the incoming value...
|
||||||
|
*
|
||||||
|
* @param other The other value to check against our internal state
|
||||||
|
*
|
||||||
|
* @return True if our value is less than the 'other' value.
|
||||||
|
*/
|
||||||
|
public boolean lt(long other);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform a "greater than" comparison check. We check to see if our value is greater
|
||||||
|
* than the incoming value...
|
||||||
|
*
|
||||||
|
* @param other The other value to check against our internal state
|
||||||
|
*
|
||||||
|
* @return True if our value is greater than the 'other' value.
|
||||||
|
*/
|
||||||
|
public boolean gt(IntegralDataTypeHolder other);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform a "greater than" comparison check. We check to see if our value is greater
|
||||||
|
* than the incoming value...
|
||||||
|
*
|
||||||
|
* @param other The other value to check against our internal state
|
||||||
|
*
|
||||||
|
* @return True if our value is greater than the 'other' value.
|
||||||
|
*/
|
||||||
|
public boolean gt(long other);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a copy of this holder.
|
||||||
|
*
|
||||||
|
* @return The copy.
|
||||||
|
*/
|
||||||
|
public IntegralDataTypeHolder copy();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the internal value.
|
||||||
|
*
|
||||||
|
* @return The current internal value
|
||||||
|
*/
|
||||||
|
public Number makeValue();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increment the internal state, but return the pre-incremented value.
|
||||||
|
*
|
||||||
|
* @return The pre-incremented internal value
|
||||||
|
*/
|
||||||
|
public Number makeValueThenIncrement();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increment the internal state by the given addend, but return the pre-incremented value.
|
||||||
|
*
|
||||||
|
* @param addend The value to be added to our internal state
|
||||||
|
*
|
||||||
|
* @return The pre-incremented internal value
|
||||||
|
*/
|
||||||
|
public Number makeValueThenAdd(long addend);
|
||||||
|
}
|
@ -1,10 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||||
* indicated by the @author tags or express copyright attribution
|
* indicated by the @author tags or express copyright attribution
|
||||||
* statements applied by the authors. All third-party contributions are
|
* statements applied by the authors. All third-party contributions are
|
||||||
* distributed under license by Red Hat Middleware LLC.
|
* distributed under license by Red Hat Inc.
|
||||||
*
|
*
|
||||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
@ -20,7 +20,6 @@
|
|||||||
* Free Software Foundation, Inc.
|
* Free Software Foundation, Inc.
|
||||||
* 51 Franklin Street, Fifth Floor
|
* 51 Franklin Street, Fifth Floor
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
package org.hibernate.id;
|
package org.hibernate.id;
|
||||||
|
|
||||||
@ -104,9 +103,10 @@ public class MultipleHiLoPerTableGenerator
|
|||||||
//hilo params
|
//hilo params
|
||||||
public static final String MAX_LO = "max_lo";
|
public static final String MAX_LO = "max_lo";
|
||||||
|
|
||||||
private long hi;
|
|
||||||
private int lo;
|
|
||||||
private int maxLo;
|
private int maxLo;
|
||||||
|
private int lo;
|
||||||
|
private IntegralDataTypeHolder value;
|
||||||
|
|
||||||
private Class returnClass;
|
private Class returnClass;
|
||||||
private int keySize;
|
private int keySize;
|
||||||
|
|
||||||
@ -146,7 +146,7 @@ public Object generatorKey() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Serializable doWorkInCurrentTransaction(Connection conn, String sql) throws SQLException {
|
public Serializable doWorkInCurrentTransaction(Connection conn, String sql) throws SQLException {
|
||||||
int result;
|
IntegralDataTypeHolder value = IdentifierGeneratorHelper.getIntegralDataTypeHolder( returnClass );
|
||||||
int rows;
|
int rows;
|
||||||
do {
|
do {
|
||||||
// The loop ensures atomicity of the
|
// The loop ensures atomicity of the
|
||||||
@ -158,18 +158,16 @@ public Serializable doWorkInCurrentTransaction(Connection conn, String sql) thro
|
|||||||
PreparedStatement qps = conn.prepareStatement(query);
|
PreparedStatement qps = conn.prepareStatement(query);
|
||||||
PreparedStatement ips = null;
|
PreparedStatement ips = null;
|
||||||
try {
|
try {
|
||||||
//qps.setString(1, key);
|
|
||||||
ResultSet rs = qps.executeQuery();
|
ResultSet rs = qps.executeQuery();
|
||||||
boolean isInitialized = rs.next();
|
boolean isInitialized = rs.next();
|
||||||
if ( !isInitialized ) {
|
if ( !isInitialized ) {
|
||||||
result = 0;
|
value.initialize( 0 );
|
||||||
ips = conn.prepareStatement(insert);
|
ips = conn.prepareStatement( insert );
|
||||||
//ips.setString(1, key);
|
value.bind( ips, 1 );
|
||||||
ips.setInt(1, result);
|
|
||||||
ips.execute();
|
ips.execute();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = rs.getInt(1);
|
value.initialize( rs, 0 );
|
||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
}
|
}
|
||||||
@ -184,12 +182,10 @@ public Serializable doWorkInCurrentTransaction(Connection conn, String sql) thro
|
|||||||
qps.close();
|
qps.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
//sql = update;
|
|
||||||
PreparedStatement ups = conn.prepareStatement(update);
|
PreparedStatement ups = conn.prepareStatement(update);
|
||||||
try {
|
try {
|
||||||
ups.setInt( 1, result + 1 );
|
value.copy().increment().bind( ups, 1 );
|
||||||
ups.setInt( 2, result );
|
value.bind( ups, 2 );
|
||||||
//ups.setString( 3, key );
|
|
||||||
rows = ups.executeUpdate();
|
rows = ups.executeUpdate();
|
||||||
}
|
}
|
||||||
catch (SQLException sqle) {
|
catch (SQLException sqle) {
|
||||||
@ -201,24 +197,30 @@ public Serializable doWorkInCurrentTransaction(Connection conn, String sql) thro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (rows==0);
|
while (rows==0);
|
||||||
return new Integer(result);
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized Serializable generate(SessionImplementor session, Object obj)
|
public synchronized Serializable generate(SessionImplementor session, Object obj)
|
||||||
throws HibernateException {
|
throws HibernateException {
|
||||||
if (maxLo < 1) {
|
// maxLo < 1 indicates a hilo generator with no hilo :?
|
||||||
|
if ( maxLo < 1 ) {
|
||||||
//keep the behavior consistent even for boundary usages
|
//keep the behavior consistent even for boundary usages
|
||||||
int val = ( (Integer) doWorkInNewTransaction(session) ).intValue();
|
IntegralDataTypeHolder value = null;
|
||||||
if (val == 0) val = ( (Integer) doWorkInNewTransaction(session) ).intValue();
|
while ( value == null || value.lt( 1 ) ) {
|
||||||
return IdentifierGeneratorHelper.createNumber( val, returnClass );
|
value = (IntegralDataTypeHolder) doWorkInNewTransaction( session );
|
||||||
}
|
}
|
||||||
if (lo>maxLo) {
|
return value.makeValue();
|
||||||
int hival = ( (Integer) doWorkInNewTransaction(session) ).intValue();
|
|
||||||
lo = (hival == 0) ? 1 : 0;
|
|
||||||
hi = hival * (maxLo+1);
|
|
||||||
log.debug("new hi value: " + hival);
|
|
||||||
}
|
}
|
||||||
return IdentifierGeneratorHelper.createNumber( hi + lo++, returnClass );
|
|
||||||
|
if ( lo > maxLo ) {
|
||||||
|
IntegralDataTypeHolder hiVal = (IntegralDataTypeHolder) doWorkInNewTransaction( session );
|
||||||
|
lo = ( hiVal.eq( 0 ) ) ? 1 : 0;
|
||||||
|
value = hiVal.copy().multiplyBy( maxLo+1 ).add( lo );
|
||||||
|
if ( log.isDebugEnabled() ) {
|
||||||
|
log.debug("new hi value: " + hiVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value.makeValueThenIncrement();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void configure(Type type, Properties params, Dialect dialect) throws MappingException {
|
public void configure(Type type, Properties params, Dialect dialect) throws MappingException {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||||
* indicated by the @author tags or express copyright attribution
|
* indicated by the @author tags or express copyright attribution
|
||||||
* statements applied by the authors. All third-party contributions are
|
* statements applied by the authors. All third-party contributions are
|
||||||
* distributed under license by Red Hat Middleware LLC.
|
* distributed under license by Red Hat Inc.
|
||||||
*
|
*
|
||||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
@ -20,7 +20,6 @@
|
|||||||
* Free Software Foundation, Inc.
|
* Free Software Foundation, Inc.
|
||||||
* 51 Franklin Street, Fifth Floor
|
* 51 Franklin Street, Fifth Floor
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
package org.hibernate.id;
|
package org.hibernate.id;
|
||||||
|
|
||||||
@ -98,19 +97,19 @@ public void configure(Type type, Properties params, Dialect dialect) throws Mapp
|
|||||||
sql = dialect.getSequenceNextValString( sequenceName );
|
sql = dialect.getSequenceNextValString( sequenceName );
|
||||||
}
|
}
|
||||||
|
|
||||||
public Serializable generate(SessionImplementor session, Object obj)
|
public Serializable generate(SessionImplementor session, Object obj) {
|
||||||
throws HibernateException {
|
return generateHolder( session ).makeValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IntegralDataTypeHolder generateHolder(SessionImplementor session) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
PreparedStatement st = session.getBatcher().prepareSelectStatement(sql);
|
PreparedStatement st = session.getBatcher().prepareSelectStatement(sql);
|
||||||
try {
|
try {
|
||||||
ResultSet rs = st.executeQuery();
|
ResultSet rs = st.executeQuery();
|
||||||
try {
|
try {
|
||||||
rs.next();
|
rs.next();
|
||||||
Serializable result = IdentifierGeneratorHelper.get(
|
IntegralDataTypeHolder result = buildHolder();
|
||||||
rs, identifierType
|
result.initialize( rs, 1 );
|
||||||
);
|
|
||||||
if ( log.isDebugEnabled() ) {
|
if ( log.isDebugEnabled() ) {
|
||||||
log.debug("Sequence identifier generated: " + result);
|
log.debug("Sequence identifier generated: " + result);
|
||||||
}
|
}
|
||||||
@ -133,7 +132,10 @@ public Serializable generate(SessionImplementor session, Object obj)
|
|||||||
sql
|
sql
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IntegralDataTypeHolder buildHolder() {
|
||||||
|
return IdentifierGeneratorHelper.getIntegralDataTypeHolder( identifierType.getReturnedClass() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] sqlCreateStrings(Dialect dialect) throws HibernateException {
|
public String[] sqlCreateStrings(Dialect dialect) throws HibernateException {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||||
* indicated by the @author tags or express copyright attribution
|
* indicated by the @author tags or express copyright attribution
|
||||||
* statements applied by the authors. All third-party contributions are
|
* statements applied by the authors. All third-party contributions are
|
||||||
* distributed under license by Red Hat Middleware LLC.
|
* distributed under license by Red Hat Inc.
|
||||||
*
|
*
|
||||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
@ -20,7 +20,6 @@
|
|||||||
* Free Software Foundation, Inc.
|
* Free Software Foundation, Inc.
|
||||||
* 51 Franklin Street, Fifth Floor
|
* 51 Franklin Street, Fifth Floor
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
package org.hibernate.id;
|
package org.hibernate.id;
|
||||||
|
|
||||||
@ -29,7 +28,6 @@
|
|||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.hibernate.HibernateException;
|
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.SessionImplementor;
|
import org.hibernate.engine.SessionImplementor;
|
||||||
@ -59,33 +57,36 @@ public class SequenceHiLoGenerator extends SequenceGenerator {
|
|||||||
|
|
||||||
private int maxLo;
|
private int maxLo;
|
||||||
private int lo;
|
private int lo;
|
||||||
private long hi;
|
|
||||||
private Class returnClass;
|
private IntegralDataTypeHolder value;
|
||||||
|
|
||||||
public void configure(Type type, Properties params, Dialect d) throws MappingException {
|
public void configure(Type type, Properties params, Dialect d) throws MappingException {
|
||||||
super.configure(type, params, d);
|
super.configure(type, params, d);
|
||||||
maxLo = PropertiesHelper.getInt(MAX_LO, params, 9);
|
maxLo = PropertiesHelper.getInt(MAX_LO, params, 9);
|
||||||
lo = maxLo + 1; // so we "clock over" on the first invocation
|
lo = maxLo + 1; // so we "clock over" on the first invocation
|
||||||
returnClass = type.getReturnedClass();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized Serializable generate(SessionImplementor session, Object obj)
|
public synchronized Serializable generate(SessionImplementor session, Object obj) {
|
||||||
throws HibernateException {
|
// maxLo < 1 indicates a hilo generator with no hilo :?
|
||||||
if (maxLo < 1) {
|
if ( maxLo < 1 ) {
|
||||||
//keep the behavior consistent even for boundary usages
|
//keep the behavior consistent even for boundary usages
|
||||||
long val = ( (Number) super.generate(session, obj) ).longValue();
|
IntegralDataTypeHolder value = null;
|
||||||
if (val == 0) val = ( (Number) super.generate(session, obj) ).longValue();
|
while ( value == null || value.lt( 0 ) ) {
|
||||||
return IdentifierGeneratorHelper.createNumber( val, returnClass );
|
value = super.generateHolder( session );
|
||||||
}
|
}
|
||||||
if ( lo>maxLo ) {
|
return value.makeValue();
|
||||||
long hival = ( (Number) super.generate(session, obj) ).longValue();
|
|
||||||
lo = (hival == 0) ? 1 : 0;
|
|
||||||
hi = hival * ( maxLo+1 );
|
|
||||||
if ( log.isDebugEnabled() )
|
|
||||||
log.debug("new hi value: " + hival);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return IdentifierGeneratorHelper.createNumber( hi + lo++, returnClass );
|
if ( lo > maxLo ) {
|
||||||
|
IntegralDataTypeHolder hiVal = generateHolder( session );
|
||||||
|
lo = ( hiVal.eq( 0 ) ) ? 1 : 0;
|
||||||
|
value = hiVal.copy().multiplyBy( maxLo+1 ).add( lo );
|
||||||
|
if ( log.isDebugEnabled() ) {
|
||||||
|
log.debug("new hi value: " + hiVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value.makeValueThenIncrement();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -50,17 +50,21 @@
|
|||||||
* table to store the last generated value. It is not
|
* table to store the last generated value. It is not
|
||||||
* intended that applications use this strategy directly.
|
* intended that applications use this strategy directly.
|
||||||
* However, it may be used to build other (efficient)
|
* However, it may be used to build other (efficient)
|
||||||
* strategies. The returned type is <tt>Integer</tt>.<br>
|
* strategies. The returned type is any supported by
|
||||||
* <br>
|
* {@link IntegralDataTypeHolder}
|
||||||
* The hi value MUST be fetched in a seperate transaction
|
* <p/>
|
||||||
* to the <tt>Session</tt> transaction so the generator must
|
* The value MUST be fetched in a separate transaction
|
||||||
* be able to obtain a new connection and commit it. Hence
|
* from that of the main {@link SessionImplementor session}
|
||||||
* this implementation may not be used when Hibernate is
|
* transaction so the generator must be able to obtain a new
|
||||||
* fetching connections when the user is supplying
|
* connection and commit it. Hence this implementation may only
|
||||||
* connections.<br>
|
* be used when Hibernate is fetching connections, not when the
|
||||||
* <br>
|
* user is supplying connections.
|
||||||
* The returned value is of type <tt>integer</tt>.<br>
|
* <p/>
|
||||||
* <br>
|
* Again, the return types supported here are any of the ones
|
||||||
|
* supported by {@link IntegralDataTypeHolder}. This is new
|
||||||
|
* as of 3.5. Prior to that this generator only returned {@link Integer}
|
||||||
|
* values.
|
||||||
|
* <p/>
|
||||||
* Mapping parameters supported: table, column
|
* Mapping parameters supported: table, column
|
||||||
*
|
*
|
||||||
* @see TableHiLoGenerator
|
* @see TableHiLoGenerator
|
||||||
@ -83,12 +87,15 @@ public class TableGenerator extends TransactionHelper
|
|||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(TableGenerator.class);
|
private static final Logger log = LoggerFactory.getLogger(TableGenerator.class);
|
||||||
|
|
||||||
|
private Type identifierType;
|
||||||
private String tableName;
|
private String tableName;
|
||||||
private String columnName;
|
private String columnName;
|
||||||
private String query;
|
private String query;
|
||||||
private String update;
|
private String update;
|
||||||
|
|
||||||
public void configure(Type type, Properties params, Dialect dialect) {
|
public void configure(Type type, Properties params, Dialect dialect) {
|
||||||
|
identifierType = type;
|
||||||
|
|
||||||
ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER );
|
ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER );
|
||||||
|
|
||||||
tableName = PropertiesHelper.getString( TABLE, params, DEFAULT_TABLE_NAME );
|
tableName = PropertiesHelper.getString( TABLE, params, DEFAULT_TABLE_NAME );
|
||||||
@ -127,12 +134,13 @@ public void configure(Type type, Properties params, Dialect dialect) {
|
|||||||
" = ?";
|
" = ?";
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized Serializable generate(SessionImplementor session, Object object)
|
public synchronized Serializable generate(SessionImplementor session, Object object) {
|
||||||
throws HibernateException {
|
return generateHolder( session ).makeValue();
|
||||||
int result = ( (Integer) doWorkInNewTransaction(session) ).intValue();
|
|
||||||
return new Integer(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected IntegralDataTypeHolder generateHolder(SessionImplementor session) {
|
||||||
|
return (IntegralDataTypeHolder) doWorkInNewTransaction( session );
|
||||||
|
}
|
||||||
|
|
||||||
public String[] sqlCreateStrings(Dialect dialect) throws HibernateException {
|
public String[] sqlCreateStrings(Dialect dialect) throws HibernateException {
|
||||||
return new String[] {
|
return new String[] {
|
||||||
@ -157,8 +165,19 @@ public Object generatorKey() {
|
|||||||
return tableName;
|
return tableName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the next value.
|
||||||
|
*
|
||||||
|
* @param conn The sql connection to use.
|
||||||
|
* @param sql n/a
|
||||||
|
*
|
||||||
|
* @return Prior to 3.5 this method returned an {@link Integer}. Since 3.5 it now
|
||||||
|
* returns a {@link IntegralDataTypeHolder}
|
||||||
|
*
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
public Serializable doWorkInCurrentTransaction(Connection conn, String sql) throws SQLException {
|
public Serializable doWorkInCurrentTransaction(Connection conn, String sql) throws SQLException {
|
||||||
int result;
|
IntegralDataTypeHolder value = buildHolder();
|
||||||
int rows;
|
int rows;
|
||||||
do {
|
do {
|
||||||
// The loop ensures atomicity of the
|
// The loop ensures atomicity of the
|
||||||
@ -175,7 +194,7 @@ public Serializable doWorkInCurrentTransaction(Connection conn, String sql) thro
|
|||||||
log.error(err);
|
log.error(err);
|
||||||
throw new IdentifierGenerationException(err);
|
throw new IdentifierGenerationException(err);
|
||||||
}
|
}
|
||||||
result = rs.getInt(1);
|
value.initialize( rs, 1 );
|
||||||
rs.close();
|
rs.close();
|
||||||
}
|
}
|
||||||
catch (SQLException sqle) {
|
catch (SQLException sqle) {
|
||||||
@ -190,8 +209,8 @@ public Serializable doWorkInCurrentTransaction(Connection conn, String sql) thro
|
|||||||
SQL_STATEMENT_LOGGER.logStatement( sql, FormatStyle.BASIC );
|
SQL_STATEMENT_LOGGER.logStatement( sql, FormatStyle.BASIC );
|
||||||
PreparedStatement ups = conn.prepareStatement(update);
|
PreparedStatement ups = conn.prepareStatement(update);
|
||||||
try {
|
try {
|
||||||
ups.setInt( 1, result + 1 );
|
value.copy().increment().bind( ups, 1 );
|
||||||
ups.setInt( 2, result );
|
value.bind( ups, 2 );
|
||||||
rows = ups.executeUpdate();
|
rows = ups.executeUpdate();
|
||||||
}
|
}
|
||||||
catch (SQLException sqle) {
|
catch (SQLException sqle) {
|
||||||
@ -203,6 +222,10 @@ public Serializable doWorkInCurrentTransaction(Connection conn, String sql) thro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (rows==0);
|
while (rows==0);
|
||||||
return new Integer(result);
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IntegralDataTypeHolder buildHolder() {
|
||||||
|
return IdentifierGeneratorHelper.getIntegralDataTypeHolder( identifierType.getReturnedClass() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.hibernate.HibernateException;
|
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.SessionImplementor;
|
import org.hibernate.engine.SessionImplementor;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
@ -58,10 +57,10 @@ public class TableHiLoGenerator extends TableGenerator {
|
|||||||
*/
|
*/
|
||||||
public static final String MAX_LO = "max_lo";
|
public static final String MAX_LO = "max_lo";
|
||||||
|
|
||||||
private long hi;
|
|
||||||
private int lo;
|
|
||||||
private int maxLo;
|
private int maxLo;
|
||||||
private Class returnClass;
|
private int lo;
|
||||||
|
|
||||||
|
private IntegralDataTypeHolder value;
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(TableHiLoGenerator.class);
|
private static final Logger log = LoggerFactory.getLogger(TableHiLoGenerator.class);
|
||||||
|
|
||||||
@ -69,26 +68,29 @@ public void configure(Type type, Properties params, Dialect d) {
|
|||||||
super.configure(type, params, d);
|
super.configure(type, params, d);
|
||||||
maxLo = PropertiesHelper.getInt(MAX_LO, params, Short.MAX_VALUE);
|
maxLo = PropertiesHelper.getInt(MAX_LO, params, Short.MAX_VALUE);
|
||||||
lo = maxLo + 1; // so we "clock over" on the first invocation
|
lo = maxLo + 1; // so we "clock over" on the first invocation
|
||||||
returnClass = type.getReturnedClass();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized Serializable generate(SessionImplementor session, Object obj)
|
public synchronized Serializable generate(SessionImplementor session, Object obj) {
|
||||||
throws HibernateException {
|
// maxLo < 1 indicates a hilo generator with no hilo :?
|
||||||
if (maxLo < 1) {
|
if ( maxLo < 1 ) {
|
||||||
//keep the behavior consistent even for boundary usages
|
//keep the behavior consistent even for boundary usages
|
||||||
long val = ( (Number) super.generate(session, obj) ).longValue();
|
IntegralDataTypeHolder value = null;
|
||||||
if (val == 0) val = ( (Number) super.generate(session, obj) ).longValue();
|
while ( value == null || value.lt( 0 ) ) {
|
||||||
return IdentifierGeneratorHelper.createNumber( val, returnClass );
|
value = generateHolder( session );
|
||||||
}
|
}
|
||||||
if (lo>maxLo) {
|
return value.makeValue();
|
||||||
long hival = ( (Number) super.generate(session, obj) ).longValue();
|
|
||||||
lo = (hival == 0) ? 1 : 0;
|
|
||||||
hi = hival * (maxLo+1);
|
|
||||||
log.debug("new hi value: " + hival);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return IdentifierGeneratorHelper.createNumber( hi + lo++, returnClass );
|
if ( lo > maxLo ) {
|
||||||
|
IntegralDataTypeHolder hiVal = generateHolder( session );
|
||||||
|
lo = ( hiVal.eq( 0 ) ) ? 1 : 0;
|
||||||
|
value = hiVal.copy().multiplyBy( maxLo+1 ).add( lo );
|
||||||
|
if ( log.isDebugEnabled() ) {
|
||||||
|
log.debug("new hi value: " + hiVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value.makeValueThenIncrement();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.hibernate.id.enhanced;
|
package org.hibernate.id.enhanced;
|
||||||
|
|
||||||
|
import org.hibernate.id.IntegralDataTypeHolder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contract for providing callback access to a {@link DatabaseStructure},
|
* Contract for providing callback access to a {@link DatabaseStructure},
|
||||||
* typically from the {@link Optimizer}.
|
* typically from the {@link Optimizer}.
|
||||||
@ -36,5 +38,5 @@ public interface AccessCallback {
|
|||||||
*
|
*
|
||||||
* @return The next value.
|
* @return The next value.
|
||||||
*/
|
*/
|
||||||
public long getNextValue();
|
public IntegralDataTypeHolder getNextValue();
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import org.hibernate.id.IntegralDataTypeHolder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs optimization on an optimizable identifier generator. Typically
|
* Performs optimization on an optimizable identifier generator. Typically
|
||||||
* this optimization takes the form of trying to ensure we do not have to
|
* this optimization takes the form of trying to ensure we do not have to
|
||||||
@ -51,12 +53,12 @@ public interface Optimizer {
|
|||||||
/**
|
/**
|
||||||
* A common means to access the last value obtained from the underlying
|
* A common means to access the last value obtained from the underlying
|
||||||
* source. This is intended for testing purposes, since accessing the
|
* source. This is intended for testing purposes, since accessing the
|
||||||
* unerlying database source directly is much more difficult.
|
* underlying database source directly is much more difficult.
|
||||||
*
|
*
|
||||||
* @return The last value we obtained from the underlying source;
|
* @return The last value we obtained from the underlying source;
|
||||||
* -1 indicates we have not yet consulted with the source.
|
* null indicates we have not yet consulted with the source.
|
||||||
*/
|
*/
|
||||||
public long getLastSourceValue();
|
public IntegralDataTypeHolder getLastSourceValue();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the defined increment size.
|
* Retrieves the defined increment size.
|
||||||
|
@ -31,8 +31,8 @@
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.id.IntegralDataTypeHolder;
|
||||||
import org.hibernate.util.ReflectHelper;
|
import org.hibernate.util.ReflectHelper;
|
||||||
import org.hibernate.id.IdentifierGeneratorHelper;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory for {@link Optimizer} instances.
|
* Factory for {@link Optimizer} instances.
|
||||||
@ -97,17 +97,6 @@ protected OptimizerSupport(Class returnClass, int incrementSize) {
|
|||||||
this.incrementSize = incrementSize;
|
this.incrementSize = incrementSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Take the primitive long value and "make" (or wrap) it into the
|
|
||||||
* {@link #getReturnClass id type}.
|
|
||||||
*
|
|
||||||
* @param value The primitive value to make/wrap.
|
|
||||||
* @return The wrapped value.
|
|
||||||
*/
|
|
||||||
protected final Serializable make(long value) {
|
|
||||||
return IdentifierGeneratorHelper.createNumber( value, returnClass );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Getter for property 'returnClass'. This is the Java
|
* Getter for property 'returnClass'. This is the Java
|
||||||
* class which is used to represent the id (e.g. {@link java.lang.Long}).
|
* class which is used to represent the id (e.g. {@link java.lang.Long}).
|
||||||
@ -131,7 +120,7 @@ public final int getIncrementSize() {
|
|||||||
* every request.
|
* every request.
|
||||||
*/
|
*/
|
||||||
public static class NoopOptimizer extends OptimizerSupport {
|
public static class NoopOptimizer extends OptimizerSupport {
|
||||||
private long lastSourceValue = -1;
|
private IntegralDataTypeHolder lastSourceValue;
|
||||||
|
|
||||||
public NoopOptimizer(Class returnClass, int incrementSize) {
|
public NoopOptimizer(Class returnClass, int incrementSize) {
|
||||||
super( returnClass, incrementSize );
|
super( returnClass, incrementSize );
|
||||||
@ -141,21 +130,21 @@ public NoopOptimizer(Class returnClass, int incrementSize) {
|
|||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public Serializable generate(AccessCallback callback) {
|
public Serializable generate(AccessCallback callback) {
|
||||||
if ( lastSourceValue == -1 ) {
|
if ( lastSourceValue == null ) {
|
||||||
while( lastSourceValue <= 0 ) {
|
do {
|
||||||
lastSourceValue = callback.getNextValue();
|
lastSourceValue = callback.getNextValue();
|
||||||
}
|
} while ( lastSourceValue.lt( 1 ) );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lastSourceValue = callback.getNextValue();
|
lastSourceValue = callback.getNextValue();
|
||||||
}
|
}
|
||||||
return make( lastSourceValue );
|
return lastSourceValue.makeValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public long getLastSourceValue() {
|
public IntegralDataTypeHolder getLastSourceValue() {
|
||||||
return lastSourceValue;
|
return lastSourceValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,11 +159,40 @@ public boolean applyIncrementSizeToSourceValues() {
|
|||||||
/**
|
/**
|
||||||
* Optimizer which applies a 'hilo' algorithm in memory to achieve
|
* Optimizer which applies a 'hilo' algorithm in memory to achieve
|
||||||
* optimization.
|
* optimization.
|
||||||
|
* <p/>
|
||||||
|
* A 'hilo' algorithm is simply a means for a single value stored in the
|
||||||
|
* database to represent a "bucket" of possible, contiguous values. The
|
||||||
|
* database value identifies which particular bucket we are on.
|
||||||
|
* <p/>
|
||||||
|
* This database value must be paired with another value that defines the
|
||||||
|
* size of the bucket; the number of possible values available.
|
||||||
|
* The {@link #getIncrementSize() incrementSize} serves this purpose. The
|
||||||
|
* naming here is meant more for consistency in that this value serves the
|
||||||
|
* same purpose as the increment supplied to the {@link PooledOptimizer}.
|
||||||
|
* <p/>
|
||||||
|
* The general algorithms used to determine the bucket are:<ol>
|
||||||
|
* <li>{@code upperLimit = (databaseValue * incrementSize) + 1}</li>
|
||||||
|
* <li>{@code lowerLimit = upperLimit - 1}</li>
|
||||||
|
* </ol>
|
||||||
|
* As an example, consider a case with incrementSize of 10. Initially the
|
||||||
|
* database holds 1:<ol>
|
||||||
|
* <li>{@code upperLimit = (1 * 20) + 1 = 21}</li>
|
||||||
|
* <li>{@code lowerLimit = 21 - 20 = 1}</li>
|
||||||
|
* </ol>
|
||||||
|
* From there we increment the value from lowerLimit until we reach the
|
||||||
|
* upperLimit, at which point we would define a new bucket. The database
|
||||||
|
* now contains 2, though incrementSize remains unchanged:<ol>
|
||||||
|
* <li>{@code upperLimit = (2 * 20) + 1 = 41}</li>
|
||||||
|
* <li>{@code lowerLimit = 41 - 20 = 21}</li>
|
||||||
|
* </ol>
|
||||||
|
* And so on...
|
||||||
|
* <p/>
|
||||||
|
* Note, 'value' always (after init) holds the next value to return
|
||||||
*/
|
*/
|
||||||
public static class HiLoOptimizer extends OptimizerSupport {
|
public static class HiLoOptimizer extends OptimizerSupport {
|
||||||
private long lastSourceValue = -1;
|
private IntegralDataTypeHolder lastSourceValue;
|
||||||
private long value;
|
private IntegralDataTypeHolder upperLimit;
|
||||||
private long hiValue;
|
private IntegralDataTypeHolder value;
|
||||||
|
|
||||||
public HiLoOptimizer(Class returnClass, int incrementSize) {
|
public HiLoOptimizer(Class returnClass, int incrementSize) {
|
||||||
super( returnClass, incrementSize );
|
super( returnClass, incrementSize );
|
||||||
@ -190,26 +208,30 @@ public HiLoOptimizer(Class returnClass, int incrementSize) {
|
|||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public synchronized Serializable generate(AccessCallback callback) {
|
public synchronized Serializable generate(AccessCallback callback) {
|
||||||
if ( lastSourceValue < 0 ) {
|
if ( lastSourceValue == null ) {
|
||||||
|
// first call, so initialize ourselves. we need to read the database
|
||||||
|
// value and set up the 'bucket' boundaries
|
||||||
lastSourceValue = callback.getNextValue();
|
lastSourceValue = callback.getNextValue();
|
||||||
while ( lastSourceValue <= 0 ) {
|
while ( lastSourceValue.lt( 1 ) ) {
|
||||||
lastSourceValue = callback.getNextValue();
|
lastSourceValue = callback.getNextValue();
|
||||||
}
|
}
|
||||||
hiValue = ( lastSourceValue * incrementSize ) + 1;
|
// upperLimit defines the upper end of the bucket values
|
||||||
value = hiValue - incrementSize;
|
upperLimit = lastSourceValue.copy().multiplyBy( incrementSize ).increment();
|
||||||
|
// initialize value to the low end of the bucket
|
||||||
|
value = upperLimit.copy().subtract( incrementSize );
|
||||||
}
|
}
|
||||||
else if ( value >= hiValue ) {
|
else if ( ! upperLimit.gt( value ) ) {
|
||||||
lastSourceValue = callback.getNextValue();
|
lastSourceValue = callback.getNextValue();
|
||||||
hiValue = ( lastSourceValue * incrementSize ) + 1;
|
upperLimit = lastSourceValue.copy().multiplyBy( incrementSize ).increment();
|
||||||
}
|
}
|
||||||
return make( value++ );
|
return value.makeValueThenIncrement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public long getLastSourceValue() {
|
public IntegralDataTypeHolder getLastSourceValue() {
|
||||||
return lastSourceValue;
|
return lastSourceValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,30 +244,38 @@ public boolean applyIncrementSizeToSourceValues() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Getter for property 'lastValue'.
|
* Getter for property 'lastValue'.
|
||||||
|
* <p/>
|
||||||
|
* Exposure intended for testing purposes.
|
||||||
*
|
*
|
||||||
* @return Value for property 'lastValue'.
|
* @return Value for property 'lastValue'.
|
||||||
*/
|
*/
|
||||||
public long getLastValue() {
|
public IntegralDataTypeHolder getLastValue() {
|
||||||
return value - 1;
|
return value.copy().decrement();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Getter for property 'hiValue'.
|
* Getter for property 'upperLimit'.
|
||||||
|
* <p/>
|
||||||
|
* Exposure intended for testing purposes.
|
||||||
*
|
*
|
||||||
* @return Value for property 'hiValue'.
|
* @return Value for property 'upperLimit'.
|
||||||
*/
|
*/
|
||||||
public long getHiValue() {
|
public IntegralDataTypeHolder getHiValue() {
|
||||||
return hiValue;
|
return upperLimit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optimizer which uses a pool of values, storing the next low value of the
|
* Optimizer which uses a pool of values, storing the next low value of the
|
||||||
* range in the database.
|
* range in the database.
|
||||||
|
* <p/>
|
||||||
|
* Note that this optimizer works essentially the same as the
|
||||||
|
* {@link HiLoOptimizer} except that here the bucket ranges are actually
|
||||||
|
* encoded into the database structures.
|
||||||
*/
|
*/
|
||||||
public static class PooledOptimizer extends OptimizerSupport {
|
public static class PooledOptimizer extends OptimizerSupport {
|
||||||
private long value;
|
private IntegralDataTypeHolder hiValue;
|
||||||
private long hiValue = -1;
|
private IntegralDataTypeHolder value;
|
||||||
|
|
||||||
public PooledOptimizer(Class returnClass, int incrementSize) {
|
public PooledOptimizer(Class returnClass, int incrementSize) {
|
||||||
super( returnClass, incrementSize );
|
super( returnClass, incrementSize );
|
||||||
@ -261,9 +291,9 @@ public PooledOptimizer(Class returnClass, int incrementSize) {
|
|||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public synchronized Serializable generate(AccessCallback callback) {
|
public synchronized Serializable generate(AccessCallback callback) {
|
||||||
if ( hiValue < 0 ) {
|
if ( hiValue == null ) {
|
||||||
value = callback.getNextValue();
|
value = callback.getNextValue();
|
||||||
if ( value < 1 ) {
|
if ( value.lt( 1 ) ) {
|
||||||
// unfortunately not really safe to normalize this
|
// unfortunately not really safe to normalize this
|
||||||
// to 1 as an initial value like we do the others
|
// to 1 as an initial value like we do the others
|
||||||
// because we would not be able to control this if
|
// because we would not be able to control this if
|
||||||
@ -272,17 +302,17 @@ public synchronized Serializable generate(AccessCallback callback) {
|
|||||||
}
|
}
|
||||||
hiValue = callback.getNextValue();
|
hiValue = callback.getNextValue();
|
||||||
}
|
}
|
||||||
else if ( value >= hiValue ) {
|
else if ( ! hiValue.gt( value ) ) {
|
||||||
hiValue = callback.getNextValue();
|
hiValue = callback.getNextValue();
|
||||||
value = hiValue - incrementSize;
|
value = hiValue.copy().subtract( incrementSize );
|
||||||
}
|
}
|
||||||
return make( value++ );
|
return value.makeValueThenIncrement();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public long getLastSourceValue() {
|
public IntegralDataTypeHolder getLastSourceValue() {
|
||||||
return hiValue;
|
return hiValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,11 +325,13 @@ public boolean applyIncrementSizeToSourceValues() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Getter for property 'lastValue'.
|
* Getter for property 'lastValue'.
|
||||||
|
* <p/>
|
||||||
|
* Exposure intended for testing purposes.
|
||||||
*
|
*
|
||||||
* @return Value for property 'lastValue'.
|
* @return Value for property 'lastValue'.
|
||||||
*/
|
*/
|
||||||
public long getLastValue() {
|
public IntegralDataTypeHolder getLastValue() {
|
||||||
return value - 1;
|
return value.copy().decrement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,8 @@
|
|||||||
import org.hibernate.engine.SessionImplementor;
|
import org.hibernate.engine.SessionImplementor;
|
||||||
import org.hibernate.exception.JDBCExceptionHelper;
|
import org.hibernate.exception.JDBCExceptionHelper;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.id.IdentifierGeneratorHelper;
|
||||||
|
import org.hibernate.id.IntegralDataTypeHolder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes a sequence.
|
* Describes a sequence.
|
||||||
@ -47,14 +49,21 @@ public class SequenceStructure implements DatabaseStructure {
|
|||||||
private final String sequenceName;
|
private final String sequenceName;
|
||||||
private final int initialValue;
|
private final int initialValue;
|
||||||
private final int incrementSize;
|
private final int incrementSize;
|
||||||
|
private final Class numberType;
|
||||||
private final String sql;
|
private final String sql;
|
||||||
private boolean applyIncrementSizeToSourceValues;
|
private boolean applyIncrementSizeToSourceValues;
|
||||||
private int accessCounter;
|
private int accessCounter;
|
||||||
|
|
||||||
public SequenceStructure(Dialect dialect, String sequenceName, int initialValue, int incrementSize) {
|
public SequenceStructure(
|
||||||
|
Dialect dialect,
|
||||||
|
String sequenceName,
|
||||||
|
int initialValue,
|
||||||
|
int incrementSize,
|
||||||
|
Class numberType) {
|
||||||
this.sequenceName = sequenceName;
|
this.sequenceName = sequenceName;
|
||||||
this.initialValue = initialValue;
|
this.initialValue = initialValue;
|
||||||
this.incrementSize = incrementSize;
|
this.incrementSize = incrementSize;
|
||||||
|
this.numberType = numberType;
|
||||||
sql = dialect.getSequenceNextValString( sequenceName );
|
sql = dialect.getSequenceNextValString( sequenceName );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +100,7 @@ public int getInitialValue() {
|
|||||||
*/
|
*/
|
||||||
public AccessCallback buildCallback(final SessionImplementor session) {
|
public AccessCallback buildCallback(final SessionImplementor session) {
|
||||||
return new AccessCallback() {
|
return new AccessCallback() {
|
||||||
public long getNextValue() {
|
public IntegralDataTypeHolder getNextValue() {
|
||||||
accessCounter++;
|
accessCounter++;
|
||||||
try {
|
try {
|
||||||
PreparedStatement st = session.getBatcher().prepareSelectStatement( sql );
|
PreparedStatement st = session.getBatcher().prepareSelectStatement( sql );
|
||||||
@ -99,11 +108,12 @@ public long getNextValue() {
|
|||||||
ResultSet rs = st.executeQuery();
|
ResultSet rs = st.executeQuery();
|
||||||
try {
|
try {
|
||||||
rs.next();
|
rs.next();
|
||||||
long result = rs.getLong( 1 );
|
IntegralDataTypeHolder value = IdentifierGeneratorHelper.getIntegralDataTypeHolder( numberType );
|
||||||
|
value.initialize( rs, 1 );
|
||||||
if ( log.isDebugEnabled() ) {
|
if ( log.isDebugEnabled() ) {
|
||||||
log.debug("Sequence identifier generated: " + result);
|
log.debug( "Sequence value obtained: " + value.makeValue() );
|
||||||
}
|
}
|
||||||
return result;
|
return value;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
try {
|
try {
|
||||||
|
@ -178,7 +178,15 @@ public void configure(Type type, Properties params, Dialect dialect) throws Mapp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.databaseStructure = buildDatabaseStructure( params, dialect, forceTableUse, sequenceName, initialValue, incrementSize );
|
this.databaseStructure = buildDatabaseStructure(
|
||||||
|
type,
|
||||||
|
params,
|
||||||
|
dialect,
|
||||||
|
forceTableUse,
|
||||||
|
sequenceName,
|
||||||
|
initialValue,
|
||||||
|
incrementSize
|
||||||
|
);
|
||||||
|
|
||||||
this.optimizer = OptimizerFactory.buildOptimizer( optimizationStrategy, identifierType.getReturnedClass(), incrementSize );
|
this.optimizer = OptimizerFactory.buildOptimizer( optimizationStrategy, identifierType.getReturnedClass(), incrementSize );
|
||||||
this.databaseStructure.prepare( optimizer );
|
this.databaseStructure.prepare( optimizer );
|
||||||
@ -291,15 +299,16 @@ protected int determineAdjustedIncrementSize(String optimizationStrategy, int in
|
|||||||
/**
|
/**
|
||||||
* Build the database structure.
|
* Build the database structure.
|
||||||
*
|
*
|
||||||
|
* @param type The Hibernate type of the identifier property
|
||||||
* @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 being used.
|
* @param dialect The dialect being used.
|
||||||
* @param forceTableUse Should a table be used even if the dialect supports sequences?
|
* @param forceTableUse Should a table be used even if the dialect supports sequences?
|
||||||
* @param sequenceName The name to use for the sequence or table.
|
* @param sequenceName The name to use for the sequence or table.
|
||||||
* @param initialValue The initial value.
|
* @param initialValue The initial value.
|
||||||
* @param incrementSize the increment size to use (after any adjustments).
|
* @param incrementSize the increment size to use (after any adjustments). @return The db structure representation
|
||||||
* @return The db structure representation
|
|
||||||
*/
|
*/
|
||||||
protected DatabaseStructure buildDatabaseStructure(
|
protected DatabaseStructure buildDatabaseStructure(
|
||||||
|
Type type,
|
||||||
Properties params,
|
Properties params,
|
||||||
Dialect dialect,
|
Dialect dialect,
|
||||||
boolean forceTableUse,
|
boolean forceTableUse,
|
||||||
@ -308,11 +317,11 @@ protected DatabaseStructure buildDatabaseStructure(
|
|||||||
int incrementSize) {
|
int incrementSize) {
|
||||||
boolean useSequence = dialect.supportsSequences() && !forceTableUse;
|
boolean useSequence = dialect.supportsSequences() && !forceTableUse;
|
||||||
if ( useSequence ) {
|
if ( useSequence ) {
|
||||||
return new SequenceStructure( dialect, sequenceName, initialValue, incrementSize );
|
return new SequenceStructure( dialect, sequenceName, initialValue, incrementSize, type.getReturnedClass() );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
String valueColumnName = determineValueColumnName( params, dialect );
|
String valueColumnName = determineValueColumnName( params, dialect );
|
||||||
return new TableStructure( dialect, sequenceName, valueColumnName, initialValue, incrementSize );
|
return new TableStructure( dialect, sequenceName, valueColumnName, initialValue, incrementSize, type.getReturnedClass() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +39,8 @@
|
|||||||
|
|
||||||
import org.hibernate.engine.TransactionHelper;
|
import org.hibernate.engine.TransactionHelper;
|
||||||
import org.hibernate.engine.SessionImplementor;
|
import org.hibernate.engine.SessionImplementor;
|
||||||
|
import org.hibernate.id.IdentifierGeneratorHelper;
|
||||||
|
import org.hibernate.id.IntegralDataTypeHolder;
|
||||||
import org.hibernate.id.PersistentIdentifierGenerator;
|
import org.hibernate.id.PersistentIdentifierGenerator;
|
||||||
import org.hibernate.id.Configurable;
|
import org.hibernate.id.Configurable;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
@ -287,7 +289,7 @@ public final long getTableAccessCount() {
|
|||||||
public void configure(Type type, Properties params, Dialect dialect) throws MappingException {
|
public void configure(Type type, Properties params, Dialect dialect) throws MappingException {
|
||||||
identifierType = type;
|
identifierType = type;
|
||||||
|
|
||||||
tableName = determneGeneratorTableName( params, dialect );
|
tableName = determineGeneratorTableName( params, dialect );
|
||||||
segmentColumnName = determineSegmentColumnName( params, dialect );
|
segmentColumnName = determineSegmentColumnName( params, dialect );
|
||||||
valueColumnName = determineValueColumnName( params, dialect );
|
valueColumnName = determineValueColumnName( params, dialect );
|
||||||
|
|
||||||
@ -316,7 +318,7 @@ public void configure(Type type, Properties params, Dialect dialect) throws Mapp
|
|||||||
* @param dialect The dialect in effect
|
* @param dialect The dialect in effect
|
||||||
* @return The table name to use.
|
* @return The table name to use.
|
||||||
*/
|
*/
|
||||||
protected String determneGeneratorTableName(Properties params, Dialect dialect) {
|
protected String determineGeneratorTableName(Properties params, Dialect dialect) {
|
||||||
String name = PropertiesHelper.getString( TABLE_PARAM, params, DEF_TABLE );
|
String name = PropertiesHelper.getString( TABLE_PARAM, params, DEF_TABLE );
|
||||||
boolean isGivenNameUnqualified = name.indexOf( '.' ) < 0;
|
boolean isGivenNameUnqualified = name.indexOf( '.' ) < 0;
|
||||||
if ( isGivenNameUnqualified ) {
|
if ( isGivenNameUnqualified ) {
|
||||||
@ -450,8 +452,8 @@ protected String buildInsertQuery() {
|
|||||||
public synchronized Serializable generate(final SessionImplementor session, Object obj) {
|
public synchronized Serializable generate(final SessionImplementor session, Object obj) {
|
||||||
return optimizer.generate(
|
return optimizer.generate(
|
||||||
new AccessCallback() {
|
new AccessCallback() {
|
||||||
public long getNextValue() {
|
public IntegralDataTypeHolder getNextValue() {
|
||||||
return ( ( Number ) doWorkInNewTransaction( session ) ).longValue();
|
return ( IntegralDataTypeHolder ) doWorkInNewTransaction( session );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -461,7 +463,7 @@ public long getNextValue() {
|
|||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public Serializable doWorkInCurrentTransaction(Connection conn, String sql) throws SQLException {
|
public Serializable doWorkInCurrentTransaction(Connection conn, String sql) throws SQLException {
|
||||||
int result;
|
IntegralDataTypeHolder value = IdentifierGeneratorHelper.getIntegralDataTypeHolder( identifierType.getReturnedClass() );
|
||||||
int rows;
|
int rows;
|
||||||
do {
|
do {
|
||||||
SQL_STATEMENT_LOGGER.logStatement( selectQuery, FormatStyle.BASIC );
|
SQL_STATEMENT_LOGGER.logStatement( selectQuery, FormatStyle.BASIC );
|
||||||
@ -470,13 +472,13 @@ public Serializable doWorkInCurrentTransaction(Connection conn, String sql) thro
|
|||||||
selectPS.setString( 1, segmentValue );
|
selectPS.setString( 1, segmentValue );
|
||||||
ResultSet selectRS = selectPS.executeQuery();
|
ResultSet selectRS = selectPS.executeQuery();
|
||||||
if ( !selectRS.next() ) {
|
if ( !selectRS.next() ) {
|
||||||
|
value.initialize( initialValue );
|
||||||
PreparedStatement insertPS = null;
|
PreparedStatement insertPS = null;
|
||||||
try {
|
try {
|
||||||
result = initialValue;
|
|
||||||
SQL_STATEMENT_LOGGER.logStatement( insertQuery, FormatStyle.BASIC );
|
SQL_STATEMENT_LOGGER.logStatement( insertQuery, FormatStyle.BASIC );
|
||||||
insertPS = conn.prepareStatement( insertQuery );
|
insertPS = conn.prepareStatement( insertQuery );
|
||||||
insertPS.setString( 1, segmentValue );
|
insertPS.setString( 1, segmentValue );
|
||||||
insertPS.setLong( 2, result );
|
value.bind( insertPS, 2 );
|
||||||
insertPS.execute();
|
insertPS.execute();
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
@ -486,7 +488,7 @@ public Serializable doWorkInCurrentTransaction(Connection conn, String sql) thro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = selectRS.getInt( 1 );
|
value.initialize( selectRS, 1 );
|
||||||
}
|
}
|
||||||
selectRS.close();
|
selectRS.close();
|
||||||
}
|
}
|
||||||
@ -501,10 +503,15 @@ public Serializable doWorkInCurrentTransaction(Connection conn, String sql) thro
|
|||||||
SQL_STATEMENT_LOGGER.logStatement( updateQuery, FormatStyle.BASIC );
|
SQL_STATEMENT_LOGGER.logStatement( updateQuery, FormatStyle.BASIC );
|
||||||
PreparedStatement updatePS = conn.prepareStatement( updateQuery );
|
PreparedStatement updatePS = conn.prepareStatement( updateQuery );
|
||||||
try {
|
try {
|
||||||
long newValue = optimizer.applyIncrementSizeToSourceValues()
|
final IntegralDataTypeHolder updateValue = value.copy();
|
||||||
? result + incrementSize : result + 1;
|
if ( optimizer.applyIncrementSizeToSourceValues() ) {
|
||||||
updatePS.setLong( 1, newValue );
|
updateValue.add( incrementSize );
|
||||||
updatePS.setLong( 2, result );
|
}
|
||||||
|
else {
|
||||||
|
updateValue.increment();
|
||||||
|
}
|
||||||
|
updateValue.bind( updatePS, 1 );
|
||||||
|
value.bind( updatePS, 2 );
|
||||||
updatePS.setString( 3, segmentValue );
|
updatePS.setString( 3, segmentValue );
|
||||||
rows = updatePS.executeUpdate();
|
rows = updatePS.executeUpdate();
|
||||||
}
|
}
|
||||||
@ -520,7 +527,7 @@ public Serializable doWorkInCurrentTransaction(Connection conn, String sql) thro
|
|||||||
|
|
||||||
accessCount++;
|
accessCount++;
|
||||||
|
|
||||||
return new Integer( result );
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,6 +40,8 @@
|
|||||||
import org.hibernate.engine.SessionImplementor;
|
import org.hibernate.engine.SessionImplementor;
|
||||||
import org.hibernate.engine.TransactionHelper;
|
import org.hibernate.engine.TransactionHelper;
|
||||||
import org.hibernate.id.IdentifierGenerationException;
|
import org.hibernate.id.IdentifierGenerationException;
|
||||||
|
import org.hibernate.id.IdentifierGeneratorHelper;
|
||||||
|
import org.hibernate.id.IntegralDataTypeHolder;
|
||||||
import org.hibernate.jdbc.util.FormatStyle;
|
import org.hibernate.jdbc.util.FormatStyle;
|
||||||
import org.hibernate.jdbc.util.SQLStatementLogger;
|
import org.hibernate.jdbc.util.SQLStatementLogger;
|
||||||
|
|
||||||
@ -56,17 +58,25 @@ public class TableStructure extends TransactionHelper implements DatabaseStructu
|
|||||||
private final String valueColumnName;
|
private final String valueColumnName;
|
||||||
private final int initialValue;
|
private final int initialValue;
|
||||||
private final int incrementSize;
|
private final int incrementSize;
|
||||||
|
private final Class numberType;
|
||||||
private final String selectQuery;
|
private final String selectQuery;
|
||||||
private final String updateQuery;
|
private final String updateQuery;
|
||||||
|
|
||||||
private boolean applyIncrementSizeToSourceValues;
|
private boolean applyIncrementSizeToSourceValues;
|
||||||
private int accessCounter;
|
private int accessCounter;
|
||||||
|
|
||||||
public TableStructure(Dialect dialect, String tableName, String valueColumnName, int initialValue, int incrementSize) {
|
public TableStructure(
|
||||||
|
Dialect dialect,
|
||||||
|
String tableName,
|
||||||
|
String valueColumnName,
|
||||||
|
int initialValue,
|
||||||
|
int incrementSize,
|
||||||
|
Class numberType) {
|
||||||
this.tableName = tableName;
|
this.tableName = tableName;
|
||||||
this.initialValue = initialValue;
|
this.initialValue = initialValue;
|
||||||
this.incrementSize = incrementSize;
|
this.incrementSize = incrementSize;
|
||||||
this.valueColumnName = valueColumnName;
|
this.valueColumnName = valueColumnName;
|
||||||
|
this.numberType = numberType;
|
||||||
|
|
||||||
selectQuery = "select " + valueColumnName + " as id_val" +
|
selectQuery = "select " + valueColumnName + " as id_val" +
|
||||||
" from " + dialect.appendLockHint( LockMode.PESSIMISTIC_WRITE, tableName ) +
|
" from " + dialect.appendLockHint( LockMode.PESSIMISTIC_WRITE, tableName ) +
|
||||||
@ -117,8 +127,8 @@ public void prepare(Optimizer optimizer) {
|
|||||||
*/
|
*/
|
||||||
public AccessCallback buildCallback(final SessionImplementor session) {
|
public AccessCallback buildCallback(final SessionImplementor session) {
|
||||||
return new AccessCallback() {
|
return new AccessCallback() {
|
||||||
public long getNextValue() {
|
public IntegralDataTypeHolder getNextValue() {
|
||||||
return ( ( Number ) doWorkInNewTransaction( session ) ).longValue();
|
return ( IntegralDataTypeHolder ) doWorkInNewTransaction( session );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -152,7 +162,7 @@ public String[] sqlDropStrings(Dialect dialect) throws HibernateException {
|
|||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
protected Serializable doWorkInCurrentTransaction(Connection conn, String sql) throws SQLException {
|
protected Serializable doWorkInCurrentTransaction(Connection conn, String sql) throws SQLException {
|
||||||
long result;
|
IntegralDataTypeHolder value = IdentifierGeneratorHelper.getIntegralDataTypeHolder( numberType );
|
||||||
int rows;
|
int rows;
|
||||||
do {
|
do {
|
||||||
SQL_STATEMENT_LOGGER.logStatement( selectQuery, FormatStyle.BASIC );
|
SQL_STATEMENT_LOGGER.logStatement( selectQuery, FormatStyle.BASIC );
|
||||||
@ -164,7 +174,7 @@ protected Serializable doWorkInCurrentTransaction(Connection conn, String sql) t
|
|||||||
log.error( err );
|
log.error( err );
|
||||||
throw new IdentifierGenerationException( err );
|
throw new IdentifierGenerationException( err );
|
||||||
}
|
}
|
||||||
result = selectRS.getLong( 1 );
|
value.initialize( selectRS, 1 );
|
||||||
selectRS.close();
|
selectRS.close();
|
||||||
}
|
}
|
||||||
catch ( SQLException sqle ) {
|
catch ( SQLException sqle ) {
|
||||||
@ -178,9 +188,10 @@ protected Serializable doWorkInCurrentTransaction(Connection conn, String sql) t
|
|||||||
SQL_STATEMENT_LOGGER.logStatement( updateQuery, FormatStyle.BASIC );
|
SQL_STATEMENT_LOGGER.logStatement( updateQuery, FormatStyle.BASIC );
|
||||||
PreparedStatement updatePS = conn.prepareStatement( updateQuery );
|
PreparedStatement updatePS = conn.prepareStatement( updateQuery );
|
||||||
try {
|
try {
|
||||||
int increment = applyIncrementSizeToSourceValues ? incrementSize : 1;
|
final int increment = applyIncrementSizeToSourceValues ? incrementSize : 1;
|
||||||
updatePS.setLong( 1, result + increment );
|
final IntegralDataTypeHolder updateValue = value.copy().add( increment );
|
||||||
updatePS.setLong( 2, result );
|
updateValue.bind( updatePS, 1 );
|
||||||
|
value.bind( updatePS, 2 );
|
||||||
rows = updatePS.executeUpdate();
|
rows = updatePS.executeUpdate();
|
||||||
}
|
}
|
||||||
catch ( SQLException sqle ) {
|
catch ( SQLException sqle ) {
|
||||||
@ -194,7 +205,7 @@ protected Serializable doWorkInCurrentTransaction(Connection conn, String sql) t
|
|||||||
|
|
||||||
accessCounter++;
|
accessCounter++;
|
||||||
|
|
||||||
return new Long( result );
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
167
core/src/test/java/org/hibernate/id/AbstractHolderTest.java
Normal file
167
core/src/test/java/org/hibernate/id/AbstractHolderTest.java
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.id;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO : javadoc
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public abstract class AbstractHolderTest extends TestCase {
|
||||||
|
protected abstract IntegralDataTypeHolder makeHolder();
|
||||||
|
|
||||||
|
public void testInitializationChecking() {
|
||||||
|
IntegralDataTypeHolder holder = makeHolder();
|
||||||
|
try {
|
||||||
|
holder.increment();
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
catch ( IdentifierGenerationException expected ) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
holder.add( 1 );
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
catch ( IdentifierGenerationException expected ) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
holder.decrement();
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
catch ( IdentifierGenerationException expected ) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
holder.subtract( 1 );
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
catch ( IdentifierGenerationException expected ) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
holder.multiplyBy( holder );
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
catch ( IdentifierGenerationException expected ) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
holder.multiplyBy( 1 );
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
catch ( IdentifierGenerationException expected ) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
holder.eq( holder );
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
catch ( IdentifierGenerationException expected ) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
holder.eq( 1 );
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
catch ( IdentifierGenerationException expected ) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
holder.lt( holder );
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
catch ( IdentifierGenerationException expected ) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
holder.lt( 1 );
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
catch ( IdentifierGenerationException expected ) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
holder.gt( holder );
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
catch ( IdentifierGenerationException expected ) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
holder.gt( 1 );
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
catch ( IdentifierGenerationException expected ) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
holder.makeValue();
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
catch ( IdentifierGenerationException expected ) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIncrement() {
|
||||||
|
IntegralDataTypeHolder holder = makeHolder();
|
||||||
|
holder.initialize( 0 );
|
||||||
|
int i = 0;
|
||||||
|
for ( ; i < 5008; i++ ) {
|
||||||
|
holder.increment();
|
||||||
|
}
|
||||||
|
assertEquals( holder.copy().initialize( i ), holder );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBasicHiloAlgorithm() {
|
||||||
|
// mimic an initialValue of 1 and increment of 20
|
||||||
|
final long initialValue = 1;
|
||||||
|
final long incrementSize = 2;
|
||||||
|
|
||||||
|
// initialization
|
||||||
|
IntegralDataTypeHolder lastSourceValue = makeHolder().initialize( 1 );
|
||||||
|
IntegralDataTypeHolder upperLimit = lastSourceValue.copy().multiplyBy( incrementSize ).increment();
|
||||||
|
IntegralDataTypeHolder value = upperLimit.copy().subtract( incrementSize );
|
||||||
|
|
||||||
|
assertEquals( 1, lastSourceValue.makeValue().longValue() );
|
||||||
|
assertEquals( 3, upperLimit.makeValue().longValue() );
|
||||||
|
assertEquals( 1, value.makeValue().longValue() );
|
||||||
|
|
||||||
|
value.increment();
|
||||||
|
value.increment();
|
||||||
|
|
||||||
|
assertFalse( upperLimit.gt( value ) );
|
||||||
|
|
||||||
|
// at which point we would "clock over"
|
||||||
|
lastSourceValue.increment();
|
||||||
|
upperLimit = lastSourceValue.copy().multiplyBy( incrementSize ).increment();
|
||||||
|
|
||||||
|
assertEquals( 2, lastSourceValue.makeValue().longValue() );
|
||||||
|
assertEquals( 5, upperLimit.makeValue().longValue() );
|
||||||
|
assertEquals( 3, value.makeValue().longValue() );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.id;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO : javadoc
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class BigDecimalHolderTest extends AbstractHolderTest {
|
||||||
|
protected IntegralDataTypeHolder makeHolder() {
|
||||||
|
return IdentifierGeneratorHelper.getIntegralDataTypeHolder( BigDecimal.class );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.id;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO : javadoc
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class BigIntegerHolderTest extends AbstractHolderTest {
|
||||||
|
protected IntegralDataTypeHolder makeHolder() {
|
||||||
|
return IdentifierGeneratorHelper.getIntegralDataTypeHolder( BigInteger.class );
|
||||||
|
}
|
||||||
|
}
|
35
core/src/test/java/org/hibernate/id/LongHolderTest.java
Normal file
35
core/src/test/java/org/hibernate/id/LongHolderTest.java
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO : javadoc
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class LongHolderTest extends AbstractHolderTest {
|
||||||
|
protected IntegralDataTypeHolder makeHolder() {
|
||||||
|
return IdentifierGeneratorHelper.getIntegralDataTypeHolder( Long.class );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.idgen.biginteger.increment;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import junit.framework.Test;
|
||||||
|
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.junit.functional.FunctionalTestCase;
|
||||||
|
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class BigIntegerIncrementGeneratorTest extends FunctionalTestCase {
|
||||||
|
public BigIntegerIncrementGeneratorTest(String string) {
|
||||||
|
super( string );
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getMappings() {
|
||||||
|
return new String[] { "idgen/biginteger/increment/Mapping.hbm.xml" };
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Test suite() {
|
||||||
|
return new FunctionalTestClassTestSuite( BigIntegerIncrementGeneratorTest.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBasics() {
|
||||||
|
Session s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
Entity entity = new Entity( "BigInteger + increment #1" );
|
||||||
|
s.save( entity );
|
||||||
|
Entity entity2 = new Entity( "BigInteger + increment #2" );
|
||||||
|
s.save( entity2 );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
assertEquals( BigInteger.valueOf( 1 ), entity.getId() );
|
||||||
|
assertEquals( BigInteger.valueOf( 2 ), entity2.getId() );
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.delete( entity );
|
||||||
|
s.delete( entity2 );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.idgen.biginteger.increment;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO : javadoc
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class Entity {
|
||||||
|
private BigInteger id;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public Entity() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Entity(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigInteger getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(BigInteger id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
~
|
||||||
|
~ Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||||
|
~ indicated by the @author tags or express copyright attribution
|
||||||
|
~ statements applied by the authors. All third-party contributions are
|
||||||
|
~ distributed under license by Red Hat Inc.
|
||||||
|
~
|
||||||
|
~ This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
~ copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
~ Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
~
|
||||||
|
~ This program is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
~ for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU Lesser General Public License
|
||||||
|
~ along with this distribution; if not, write to:
|
||||||
|
~ Free Software Foundation, Inc.
|
||||||
|
~ 51 Franklin Street, Fifth Floor
|
||||||
|
~ Boston, MA 02110-1301 USA
|
||||||
|
-->
|
||||||
|
<!DOCTYPE hibernate-mapping PUBLIC
|
||||||
|
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||||
|
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Demonstrates use of simple increment generator on a BigInteger property.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<hibernate-mapping package="org.hibernate.test.idgen.biginteger.increment">
|
||||||
|
|
||||||
|
<class name="Entity">
|
||||||
|
<id name="id" column="ID" type="big_integer">
|
||||||
|
<generator class="increment" />
|
||||||
|
</id>
|
||||||
|
<property name="name" type="string"/>
|
||||||
|
</class>
|
||||||
|
|
||||||
|
</hibernate-mapping>
|
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.idgen.biginteger.sequence;
|
||||||
|
|
||||||
|
import junit.framework.Test;
|
||||||
|
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.dialect.Dialect;
|
||||||
|
import org.hibernate.junit.functional.DatabaseSpecificFunctionalTestCase;
|
||||||
|
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class BigIntegerSequenceGeneratorTest extends DatabaseSpecificFunctionalTestCase {
|
||||||
|
public BigIntegerSequenceGeneratorTest(String string) {
|
||||||
|
super( string );
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getMappings() {
|
||||||
|
return new String[] { "idgen/biginteger/sequence/Mapping.hbm.xml" };
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Test suite() {
|
||||||
|
return new FunctionalTestClassTestSuite( BigIntegerSequenceGeneratorTest.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean appliesTo(Dialect dialect) {
|
||||||
|
return dialect.supportsSequences();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBasics() {
|
||||||
|
Session s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
Entity entity = new Entity( "BigInteger + sequence #1" );
|
||||||
|
s.save( entity );
|
||||||
|
Entity entity2 = new Entity( "BigInteger + sequence #2" );
|
||||||
|
s.save( entity2 );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
// hsqldb defines different behavior for the initial select from a sequence
|
||||||
|
// then say oracle
|
||||||
|
// assertEquals( BigInteger.valueOf( 1 ), entity.getId() );
|
||||||
|
// assertEquals( BigInteger.valueOf( 2 ), entity2.getId() );
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.delete( entity );
|
||||||
|
s.delete( entity2 );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.idgen.biginteger.sequence;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO : javadoc
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class Entity {
|
||||||
|
private BigInteger id;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public Entity() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Entity(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigInteger getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(BigInteger id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
~
|
||||||
|
~ Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||||
|
~ indicated by the @author tags or express copyright attribution
|
||||||
|
~ statements applied by the authors. All third-party contributions are
|
||||||
|
~ distributed under license by Red Hat Inc.
|
||||||
|
~
|
||||||
|
~ This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
~ copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
~ Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
~
|
||||||
|
~ This program is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
~ for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU Lesser General Public License
|
||||||
|
~ along with this distribution; if not, write to:
|
||||||
|
~ Free Software Foundation, Inc.
|
||||||
|
~ 51 Franklin Street, Fifth Floor
|
||||||
|
~ Boston, MA 02110-1301 USA
|
||||||
|
-->
|
||||||
|
<!DOCTYPE hibernate-mapping PUBLIC
|
||||||
|
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||||
|
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Demonstrates use of a sequence generator on a BigInteger property.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<hibernate-mapping package="org.hibernate.test.idgen.biginteger.sequence">
|
||||||
|
|
||||||
|
<class name="Entity">
|
||||||
|
<id name="id" column="ID" type="big_integer">
|
||||||
|
<generator class="sequence">
|
||||||
|
</generator>
|
||||||
|
</id>
|
||||||
|
<property name="name" type="string"/>
|
||||||
|
</class>
|
||||||
|
|
||||||
|
</hibernate-mapping>
|
@ -3,6 +3,8 @@
|
|||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
import junit.framework.TestSuite;
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
|
import org.hibernate.id.IdentifierGeneratorHelper;
|
||||||
|
import org.hibernate.id.IntegralDataTypeHolder;
|
||||||
import org.hibernate.junit.UnitTestCase;
|
import org.hibernate.junit.UnitTestCase;
|
||||||
import org.hibernate.id.enhanced.Optimizer;
|
import org.hibernate.id.enhanced.Optimizer;
|
||||||
import org.hibernate.id.enhanced.OptimizerFactory;
|
import org.hibernate.id.enhanced.OptimizerFactory;
|
||||||
@ -88,7 +90,7 @@ public void testBasicPooledOptimizerUsage() {
|
|||||||
next = ( Long ) optimizer.generate( sequence );
|
next = ( Long ) optimizer.generate( sequence );
|
||||||
assertEquals( i, next.intValue() );
|
assertEquals( i, next.intValue() );
|
||||||
}
|
}
|
||||||
assertEquals( 2, sequence.getTimesCalled() ); // twice to initialze state
|
assertEquals( 2, sequence.getTimesCalled() ); // twice to initialize state
|
||||||
assertEquals( 11, sequence.getCurrentValue() );
|
assertEquals( 11, sequence.getCurrentValue() );
|
||||||
// force a "clock over"
|
// force a "clock over"
|
||||||
next = ( Long ) optimizer.generate( sequence );
|
next = ( Long ) optimizer.generate( sequence );
|
||||||
@ -98,7 +100,7 @@ public void testBasicPooledOptimizerUsage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class SourceMock implements AccessCallback {
|
private static class SourceMock implements AccessCallback {
|
||||||
private long value;
|
private IdentifierGeneratorHelper.BasicHolder value = new IdentifierGeneratorHelper.BasicHolder( Long.class );
|
||||||
private int increment;
|
private int increment;
|
||||||
private int timesCalled = 0;
|
private int timesCalled = 0;
|
||||||
|
|
||||||
@ -108,12 +110,12 @@ public SourceMock(long initialValue) {
|
|||||||
|
|
||||||
public SourceMock(long initialValue, int increment) {
|
public SourceMock(long initialValue, int increment) {
|
||||||
this.increment = increment;
|
this.increment = increment;
|
||||||
this.value = initialValue - increment;
|
this.value.initialize( initialValue - increment );
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getNextValue() {
|
public IntegralDataTypeHolder getNextValue() {
|
||||||
timesCalled++;
|
timesCalled++;
|
||||||
return ( value += increment );
|
return value.add( increment ).copy();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getTimesCalled() {
|
public int getTimesCalled() {
|
||||||
@ -121,7 +123,7 @@ public int getTimesCalled() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public long getCurrentValue() {
|
public long getCurrentValue() {
|
||||||
return value;
|
return value.getActualLongValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,13 +2,15 @@
|
|||||||
|
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
|
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.id.enhanced.OptimizerFactory;
|
||||||
|
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
||||||
|
import org.hibernate.id.enhanced.TableStructure;
|
||||||
import org.hibernate.junit.functional.DatabaseSpecificFunctionalTestCase;
|
import org.hibernate.junit.functional.DatabaseSpecificFunctionalTestCase;
|
||||||
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
|
||||||
import org.hibernate.id.enhanced.TableStructure;
|
import static org.hibernate.id.IdentifierGeneratorHelper.BasicHolder;
|
||||||
import org.hibernate.id.enhanced.OptimizerFactory;
|
|
||||||
import org.hibernate.Session;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
@ -54,7 +56,7 @@ public void testNormalBoundary() {
|
|||||||
long expectedId = i + 1;
|
long expectedId = i + 1;
|
||||||
assertEquals( expectedId, entities[i].getId().longValue() );
|
assertEquals( expectedId, entities[i].getId().longValue() );
|
||||||
assertEquals( expectedId, generator.getDatabaseStructure().getTimesAccessed() );
|
assertEquals( expectedId, generator.getDatabaseStructure().getTimesAccessed() );
|
||||||
assertEquals( expectedId, generator.getOptimizer().getLastSourceValue() );
|
assertEquals( expectedId, ( (BasicHolder) generator.getOptimizer().getLastSourceValue() ).getActualLongValue() );
|
||||||
}
|
}
|
||||||
s.getTransaction().commit();
|
s.getTransaction().commit();
|
||||||
|
|
||||||
|
@ -2,13 +2,15 @@
|
|||||||
|
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
|
|
||||||
import org.hibernate.junit.functional.DatabaseSpecificFunctionalTestCase;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
|
||||||
import org.hibernate.id.enhanced.OptimizerFactory;
|
import org.hibernate.id.enhanced.OptimizerFactory;
|
||||||
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
||||||
import org.hibernate.id.enhanced.TableStructure;
|
import org.hibernate.id.enhanced.TableStructure;
|
||||||
import org.hibernate.Session;
|
import org.hibernate.junit.functional.DatabaseSpecificFunctionalTestCase;
|
||||||
|
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
|
||||||
|
import static org.hibernate.id.IdentifierGeneratorHelper.BasicHolder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
@ -54,18 +56,18 @@ public void testNormalBoundary() {
|
|||||||
s.save( entities[i] );
|
s.save( entities[i] );
|
||||||
long expectedId = i + 1;
|
long expectedId = i + 1;
|
||||||
assertEquals( expectedId, entities[i].getId().longValue() );
|
assertEquals( expectedId, entities[i].getId().longValue() );
|
||||||
assertEquals( 1, generator.getOptimizer().getLastSourceValue() );
|
assertEquals( 1, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() );
|
||||||
assertEquals( i + 1, optimizer.getLastValue() );
|
assertEquals( i + 1, ( (BasicHolder) optimizer.getLastValue() ).getActualLongValue() );
|
||||||
assertEquals( increment + 1, optimizer.getHiValue() );
|
assertEquals( increment + 1, ( (BasicHolder) optimizer.getHiValue() ).getActualLongValue() );
|
||||||
}
|
}
|
||||||
// now force a "clock over"
|
// now force a "clock over"
|
||||||
entities[ increment ] = new Entity( "" + increment );
|
entities[ increment ] = new Entity( "" + increment );
|
||||||
s.save( entities[ increment ] );
|
s.save( entities[ increment ] );
|
||||||
long expectedId = optimizer.getIncrementSize() + 1;
|
long expectedId = optimizer.getIncrementSize() + 1;
|
||||||
assertEquals( expectedId, entities[ optimizer.getIncrementSize() ].getId().longValue() );
|
assertEquals( expectedId, entities[ optimizer.getIncrementSize() ].getId().longValue() );
|
||||||
assertEquals( 2, optimizer.getLastSourceValue() ); // initialization + clokc-over
|
assertEquals( 2, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() ); // initialization + clock-over
|
||||||
assertEquals( increment + 1, optimizer.getLastValue() );
|
assertEquals( increment + 1, ( (BasicHolder) optimizer.getLastValue() ).getActualLongValue() );
|
||||||
assertEquals( ( increment * 2 ) + 1, optimizer.getHiValue() );
|
assertEquals( ( increment * 2 ) + 1, ( (BasicHolder) optimizer.getHiValue() ).getActualLongValue() );
|
||||||
|
|
||||||
s.getTransaction().commit();
|
s.getTransaction().commit();
|
||||||
|
|
||||||
|
@ -2,13 +2,15 @@
|
|||||||
|
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
|
|
||||||
import org.hibernate.junit.functional.DatabaseSpecificFunctionalTestCase;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
|
||||||
import org.hibernate.id.enhanced.OptimizerFactory;
|
import org.hibernate.id.enhanced.OptimizerFactory;
|
||||||
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
||||||
import org.hibernate.id.enhanced.TableStructure;
|
import org.hibernate.id.enhanced.TableStructure;
|
||||||
import org.hibernate.Session;
|
import org.hibernate.junit.functional.DatabaseSpecificFunctionalTestCase;
|
||||||
|
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
|
||||||
|
import static org.hibernate.id.IdentifierGeneratorHelper.BasicHolder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
@ -54,19 +56,21 @@ public void testNormalBoundary() {
|
|||||||
s.save( entities[i] );
|
s.save( entities[i] );
|
||||||
long expectedId = i + 1;
|
long expectedId = i + 1;
|
||||||
assertEquals( expectedId, entities[i].getId().longValue() );
|
assertEquals( expectedId, entities[i].getId().longValue() );
|
||||||
assertEquals( 2, generator.getDatabaseStructure().getTimesAccessed() ); // initialization calls table twice
|
// NOTE : initialization calls table twice
|
||||||
assertEquals( increment + 1, optimizer.getLastSourceValue() ); // initialization calls table twice
|
assertEquals( 2, generator.getDatabaseStructure().getTimesAccessed() );
|
||||||
assertEquals( i + 1, optimizer.getLastValue() );
|
assertEquals( increment + 1, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() );
|
||||||
assertEquals( increment + 1, optimizer.getLastSourceValue() );
|
assertEquals( i + 1, ( (BasicHolder) optimizer.getLastValue() ).getActualLongValue() );
|
||||||
|
assertEquals( increment + 1, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() );
|
||||||
}
|
}
|
||||||
// now force a "clock over"
|
// now force a "clock over"
|
||||||
entities[ increment ] = new Entity( "" + increment );
|
entities[ increment ] = new Entity( "" + increment );
|
||||||
s.save( entities[ increment ] );
|
s.save( entities[ increment ] );
|
||||||
long expectedId = optimizer.getIncrementSize() + 1;
|
long expectedId = optimizer.getIncrementSize() + 1;
|
||||||
assertEquals( expectedId, entities[ optimizer.getIncrementSize() ].getId().longValue() );
|
assertEquals( expectedId, entities[ optimizer.getIncrementSize() ].getId().longValue() );
|
||||||
assertEquals( 3, generator.getDatabaseStructure().getTimesAccessed() ); // initialization (2) + clock over
|
// initialization (2) + clock over
|
||||||
assertEquals( ( increment * 2 ) + 1, optimizer.getLastSourceValue() ); // initialization (2) + clock over
|
assertEquals( 3, generator.getDatabaseStructure().getTimesAccessed() );
|
||||||
assertEquals( increment + 1, optimizer.getLastValue() );
|
assertEquals( ( increment * 2 ) + 1, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() );
|
||||||
|
assertEquals( increment + 1, ( (BasicHolder) optimizer.getLastValue() ).getActualLongValue() );
|
||||||
s.getTransaction().commit();
|
s.getTransaction().commit();
|
||||||
|
|
||||||
s.beginTransaction();
|
s.beginTransaction();
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
|
||||||
|
import static org.hibernate.id.IdentifierGeneratorHelper.BasicHolder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
@ -41,7 +43,7 @@ public void testNormalBoundary() {
|
|||||||
long expectedId = i + 1;
|
long expectedId = i + 1;
|
||||||
assertEquals( expectedId, entities[i].getId().longValue() );
|
assertEquals( expectedId, entities[i].getId().longValue() );
|
||||||
assertEquals( expectedId, generator.getDatabaseStructure().getTimesAccessed() );
|
assertEquals( expectedId, generator.getDatabaseStructure().getTimesAccessed() );
|
||||||
assertEquals( expectedId, generator.getOptimizer().getLastSourceValue() );
|
assertEquals( expectedId, ( (BasicHolder) generator.getOptimizer().getLastSourceValue() ).getActualLongValue() );
|
||||||
}
|
}
|
||||||
s.getTransaction().commit();
|
s.getTransaction().commit();
|
||||||
|
|
||||||
|
@ -9,6 +9,9 @@
|
|||||||
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
|
||||||
|
import static org.hibernate.id.IdentifierGeneratorHelper.BasicHolder;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
@ -42,17 +45,17 @@ public void testNormalBoundary() {
|
|||||||
entities[i] = new Entity( "" + ( i + 1 ) );
|
entities[i] = new Entity( "" + ( i + 1 ) );
|
||||||
s.save( entities[i] );
|
s.save( entities[i] );
|
||||||
assertEquals( 1, generator.getDatabaseStructure().getTimesAccessed() ); // initialization
|
assertEquals( 1, generator.getDatabaseStructure().getTimesAccessed() ); // initialization
|
||||||
assertEquals( 1, optimizer.getLastSourceValue() ); // initialization
|
assertEquals( 1, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() ); // initialization
|
||||||
assertEquals( i + 1, optimizer.getLastValue() );
|
assertEquals( i + 1, ( (BasicHolder) optimizer.getLastValue() ).getActualLongValue() );
|
||||||
assertEquals( increment + 1, optimizer.getHiValue() );
|
assertEquals( increment + 1, ( (BasicHolder) optimizer.getHiValue() ).getActualLongValue() );
|
||||||
}
|
}
|
||||||
// now force a "clock over"
|
// now force a "clock over"
|
||||||
entities[ increment ] = new Entity( "" + increment );
|
entities[ increment ] = new Entity( "" + increment );
|
||||||
s.save( entities[ increment ] );
|
s.save( entities[ increment ] );
|
||||||
assertEquals( 2, generator.getDatabaseStructure().getTimesAccessed() ); // initialization
|
assertEquals( 2, generator.getDatabaseStructure().getTimesAccessed() ); // initialization
|
||||||
assertEquals( 2, optimizer.getLastSourceValue() ); // initialization
|
assertEquals( 2, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() ); // initialization
|
||||||
assertEquals( increment + 1, optimizer.getLastValue() );
|
assertEquals( increment + 1, ( (BasicHolder) optimizer.getLastValue() ).getActualLongValue() );
|
||||||
assertEquals( ( increment * 2 ) + 1, optimizer.getHiValue() );
|
assertEquals( ( increment * 2 ) + 1, ( (BasicHolder) optimizer.getHiValue() ).getActualLongValue() );
|
||||||
|
|
||||||
s.getTransaction().commit();
|
s.getTransaction().commit();
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
|
|
||||||
|
import static org.hibernate.id.IdentifierGeneratorHelper.BasicHolder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
@ -42,16 +44,16 @@ public void testNormalBoundary() {
|
|||||||
entities[i] = new Entity( "" + ( i + 1 ) );
|
entities[i] = new Entity( "" + ( i + 1 ) );
|
||||||
s.save( entities[i] );
|
s.save( entities[i] );
|
||||||
assertEquals( 2, generator.getDatabaseStructure().getTimesAccessed() ); // initialization calls seq twice
|
assertEquals( 2, generator.getDatabaseStructure().getTimesAccessed() ); // initialization calls seq twice
|
||||||
assertEquals( increment + 1, optimizer.getLastSourceValue() ); // initialization calls seq twice
|
assertEquals( increment + 1, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() ); // initialization calls seq twice
|
||||||
assertEquals( i + 1, optimizer.getLastValue() );
|
assertEquals( i + 1, ( (BasicHolder) optimizer.getLastValue() ).getActualLongValue() );
|
||||||
assertEquals( increment + 1, optimizer.getLastSourceValue() );
|
assertEquals( increment + 1, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() );
|
||||||
}
|
}
|
||||||
// now force a "clock over"
|
// now force a "clock over"
|
||||||
entities[ increment ] = new Entity( "" + increment );
|
entities[ increment ] = new Entity( "" + increment );
|
||||||
s.save( entities[ increment ] );
|
s.save( entities[ increment ] );
|
||||||
assertEquals( 3, generator.getDatabaseStructure().getTimesAccessed() ); // initialization (2) + clock over
|
assertEquals( 3, generator.getDatabaseStructure().getTimesAccessed() ); // initialization (2) + clock over
|
||||||
assertEquals( ( increment * 2 ) + 1, optimizer.getLastSourceValue() ); // initialization (2) + clock over
|
assertEquals( ( increment * 2 ) + 1, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() ); // initialization (2) + clock over
|
||||||
assertEquals( increment + 1, optimizer.getLastValue() );
|
assertEquals( increment + 1, ( (BasicHolder) optimizer.getLastValue() ).getActualLongValue() );
|
||||||
s.getTransaction().commit();
|
s.getTransaction().commit();
|
||||||
|
|
||||||
s.beginTransaction();
|
s.beginTransaction();
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
import org.hibernate.id.enhanced.TableGenerator;
|
import org.hibernate.id.enhanced.TableGenerator;
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
|
|
||||||
|
import static org.hibernate.id.IdentifierGeneratorHelper.BasicHolder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
@ -41,7 +43,7 @@ public void testNormalBoundary() {
|
|||||||
long expectedId = i + 1;
|
long expectedId = i + 1;
|
||||||
assertEquals( expectedId, entities[i].getId().longValue() );
|
assertEquals( expectedId, entities[i].getId().longValue() );
|
||||||
assertEquals( expectedId, generator.getTableAccessCount() );
|
assertEquals( expectedId, generator.getTableAccessCount() );
|
||||||
assertEquals( expectedId, generator.getOptimizer().getLastSourceValue() );
|
assertEquals( expectedId, ( (BasicHolder) generator.getOptimizer().getLastSourceValue() ).getActualLongValue() );
|
||||||
}
|
}
|
||||||
s.getTransaction().commit();
|
s.getTransaction().commit();
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
import org.hibernate.id.enhanced.TableGenerator;
|
import org.hibernate.id.enhanced.TableGenerator;
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
|
|
||||||
|
import static org.hibernate.id.IdentifierGeneratorHelper.BasicHolder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
@ -42,17 +44,17 @@ public void testNormalBoundary() {
|
|||||||
entities[i] = new Entity( "" + ( i + 1 ) );
|
entities[i] = new Entity( "" + ( i + 1 ) );
|
||||||
s.save( entities[i] );
|
s.save( entities[i] );
|
||||||
assertEquals( 1, generator.getTableAccessCount() ); // initialization
|
assertEquals( 1, generator.getTableAccessCount() ); // initialization
|
||||||
assertEquals( 1, optimizer.getLastSourceValue() ); // initialization
|
assertEquals( 1, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() ); // initialization
|
||||||
assertEquals( i + 1, optimizer.getLastValue() );
|
assertEquals( i + 1, ( (BasicHolder) optimizer.getLastValue() ).getActualLongValue() );
|
||||||
assertEquals( increment + 1, optimizer.getHiValue() );
|
assertEquals( increment + 1, ( (BasicHolder) optimizer.getHiValue() ).getActualLongValue() );
|
||||||
}
|
}
|
||||||
// now force a "clock over"
|
// now force a "clock over"
|
||||||
entities[ increment ] = new Entity( "" + increment );
|
entities[ increment ] = new Entity( "" + increment );
|
||||||
s.save( entities[ increment ] );
|
s.save( entities[ increment ] );
|
||||||
assertEquals( 2, generator.getTableAccessCount() ); // initialization
|
assertEquals( 2, generator.getTableAccessCount() ); // initialization
|
||||||
assertEquals( 2, optimizer.getLastSourceValue() ); // initialization
|
assertEquals( 2, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() ); // initialization
|
||||||
assertEquals( increment + 1, optimizer.getLastValue() );
|
assertEquals( increment + 1, ( (BasicHolder) optimizer.getLastValue() ).getActualLongValue() );
|
||||||
assertEquals( ( increment * 2 ) + 1, optimizer.getHiValue() );
|
assertEquals( ( increment * 2 ) + 1, ( (BasicHolder) optimizer.getHiValue() ).getActualLongValue() );
|
||||||
|
|
||||||
s.getTransaction().commit();
|
s.getTransaction().commit();
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
import org.hibernate.id.enhanced.TableGenerator;
|
import org.hibernate.id.enhanced.TableGenerator;
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
|
|
||||||
|
import static org.hibernate.id.IdentifierGeneratorHelper.BasicHolder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
@ -42,16 +44,16 @@ public void testNormalBoundary() {
|
|||||||
entities[i] = new Entity( "" + ( i + 1 ) );
|
entities[i] = new Entity( "" + ( i + 1 ) );
|
||||||
s.save( entities[i] );
|
s.save( entities[i] );
|
||||||
assertEquals( 2, generator.getTableAccessCount() ); // initialization calls seq twice
|
assertEquals( 2, generator.getTableAccessCount() ); // initialization calls seq twice
|
||||||
assertEquals( increment + 1, optimizer.getLastSourceValue() ); // initialization calls seq twice
|
assertEquals( increment + 1, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() ); // initialization calls seq twice
|
||||||
assertEquals( i + 1, optimizer.getLastValue() );
|
assertEquals( i + 1, ( (BasicHolder) optimizer.getLastValue() ).getActualLongValue() );
|
||||||
assertEquals( increment + 1, optimizer.getLastSourceValue() );
|
assertEquals( increment + 1, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() );
|
||||||
}
|
}
|
||||||
// now force a "clock over"
|
// now force a "clock over"
|
||||||
entities[ increment ] = new Entity( "" + increment );
|
entities[ increment ] = new Entity( "" + increment );
|
||||||
s.save( entities[ increment ] );
|
s.save( entities[ increment ] );
|
||||||
assertEquals( 3, generator.getTableAccessCount() ); // initialization (2) + clock over
|
assertEquals( 3, generator.getTableAccessCount() ); // initialization (2) + clock over
|
||||||
assertEquals( ( increment * 2 ) + 1, optimizer.getLastSourceValue() ); // initialization (2) + clock over
|
assertEquals( ( increment * 2 ) + 1, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() ); // initialization (2) + clock over
|
||||||
assertEquals( increment + 1, optimizer.getLastValue() );
|
assertEquals( increment + 1, ( (BasicHolder) optimizer.getLastValue() ).getActualLongValue() );
|
||||||
s.getTransaction().commit();
|
s.getTransaction().commit();
|
||||||
|
|
||||||
s.beginTransaction();
|
s.beginTransaction();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user