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 class VersionValue {
|
|||
}
|
||||
}
|
||||
public Object getDefaultValue(Object currentValue) {
|
||||
return IdentifierGeneratorHelper.createNumber( -1l, currentValue.getClass() );
|
||||
return IdentifierGeneratorHelper.getIntegralDataTypeHolder( currentValue.getClass() )
|
||||
.initialize( -1L )
|
||||
.makeValue();
|
||||
}
|
||||
public String toString() {
|
||||
return "VERSION_NEGATIVE";
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
package org.hibernate.id;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
|
@ -119,10 +122,17 @@ public final class IdentifierGeneratorHelper {
|
|||
else if ( clazz == String.class ) {
|
||||
return rs.getString( 1 );
|
||||
}
|
||||
else {
|
||||
throw new IdentifierGenerationException( "this id generator generates long, integer, short or string" );
|
||||
else if ( clazz == BigInteger.class ) {
|
||||
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 @@ public final class IdentifierGeneratorHelper {
|
|||
*
|
||||
* @param value The primitive value to wrap.
|
||||
* @param clazz The Java numeric type in which to wrap the value.
|
||||
*
|
||||
* @return The wrapped type.
|
||||
*
|
||||
* @throws IdentifierGenerationException Indicates an unhandled 'clazz'.
|
||||
*
|
||||
* @deprecated Use the {@link #getIntegralDataTypeHolder holders} instead.
|
||||
*/
|
||||
public static Number createNumber(long value, Class clazz) throws IdentifierGenerationException {
|
||||
if ( clazz == Long.class ) {
|
||||
|
@ -144,7 +158,510 @@ public final class IdentifierGeneratorHelper {
|
|||
return new Short( ( short ) value );
|
||||
}
|
||||
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
|
||||
*
|
||||
* 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
|
||||
* 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,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,7 +20,6 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.id;
|
||||
|
||||
|
@ -53,20 +52,21 @@ import org.hibernate.util.StringHelper;
|
|||
* (The tables parameter specified a comma-separated list of table names.)
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class IncrementGenerator implements IdentifierGenerator, Configurable {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(IncrementGenerator.class);
|
||||
|
||||
private long next;
|
||||
private String sql;
|
||||
private Class returnClass;
|
||||
private String sql;
|
||||
|
||||
private IntegralDataTypeHolder previousValueHolder;
|
||||
|
||||
public synchronized Serializable generate(SessionImplementor session, Object object) throws HibernateException {
|
||||
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 {
|
||||
|
@ -117,22 +117,23 @@ public class IncrementGenerator implements IdentifierGenerator, Configurable {
|
|||
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 );
|
||||
try {
|
||||
PreparedStatement st = session.getBatcher().prepareSelectStatement(sql);
|
||||
PreparedStatement st = session.getBatcher().prepareSelectStatement( sql );
|
||||
try {
|
||||
ResultSet rs = st.executeQuery();
|
||||
try {
|
||||
if ( rs.next() ) {
|
||||
next = rs.getLong(1) + 1;
|
||||
if ( rs.wasNull() ) next = 1;
|
||||
previousValueHolder.initialize( rs, 0L ).increment();
|
||||
}
|
||||
else {
|
||||
next = 1;
|
||||
previousValueHolder.initialize( 1L );
|
||||
}
|
||||
sql=null;
|
||||
log.debug("first free id: " + next);
|
||||
sql = null;
|
||||
log.debug( "first free id: " + previousValueHolder.makeValue() );
|
||||
}
|
||||
finally {
|
||||
rs.close();
|
||||
|
@ -141,7 +142,6 @@ public class IncrementGenerator implements IdentifierGenerator, Configurable {
|
|||
finally {
|
||||
session.getBatcher().closeStatement(st);
|
||||
}
|
||||
|
||||
}
|
||||
catch (SQLException sqle) {
|
||||
throw JDBCExceptionHelper.convert(
|
||||
|
|
|
@ -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
|
||||
*
|
||||
* 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
|
||||
* 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,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,7 +20,6 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.id;
|
||||
|
||||
|
@ -104,9 +103,10 @@ public class MultipleHiLoPerTableGenerator
|
|||
//hilo params
|
||||
public static final String MAX_LO = "max_lo";
|
||||
|
||||
private long hi;
|
||||
private int lo;
|
||||
private int maxLo;
|
||||
private int lo;
|
||||
private IntegralDataTypeHolder value;
|
||||
|
||||
private Class returnClass;
|
||||
private int keySize;
|
||||
|
||||
|
@ -146,7 +146,7 @@ public class MultipleHiLoPerTableGenerator
|
|||
}
|
||||
|
||||
public Serializable doWorkInCurrentTransaction(Connection conn, String sql) throws SQLException {
|
||||
int result;
|
||||
IntegralDataTypeHolder value = IdentifierGeneratorHelper.getIntegralDataTypeHolder( returnClass );
|
||||
int rows;
|
||||
do {
|
||||
// The loop ensures atomicity of the
|
||||
|
@ -158,18 +158,16 @@ public class MultipleHiLoPerTableGenerator
|
|||
PreparedStatement qps = conn.prepareStatement(query);
|
||||
PreparedStatement ips = null;
|
||||
try {
|
||||
//qps.setString(1, key);
|
||||
ResultSet rs = qps.executeQuery();
|
||||
boolean isInitialized = rs.next();
|
||||
if ( !isInitialized ) {
|
||||
result = 0;
|
||||
ips = conn.prepareStatement(insert);
|
||||
//ips.setString(1, key);
|
||||
ips.setInt(1, result);
|
||||
value.initialize( 0 );
|
||||
ips = conn.prepareStatement( insert );
|
||||
value.bind( ips, 1 );
|
||||
ips.execute();
|
||||
}
|
||||
else {
|
||||
result = rs.getInt(1);
|
||||
value.initialize( rs, 0 );
|
||||
}
|
||||
rs.close();
|
||||
}
|
||||
|
@ -184,12 +182,10 @@ public class MultipleHiLoPerTableGenerator
|
|||
qps.close();
|
||||
}
|
||||
|
||||
//sql = update;
|
||||
PreparedStatement ups = conn.prepareStatement(update);
|
||||
try {
|
||||
ups.setInt( 1, result + 1 );
|
||||
ups.setInt( 2, result );
|
||||
//ups.setString( 3, key );
|
||||
value.copy().increment().bind( ups, 1 );
|
||||
value.bind( ups, 2 );
|
||||
rows = ups.executeUpdate();
|
||||
}
|
||||
catch (SQLException sqle) {
|
||||
|
@ -201,24 +197,30 @@ public class MultipleHiLoPerTableGenerator
|
|||
}
|
||||
}
|
||||
while (rows==0);
|
||||
return new Integer(result);
|
||||
return value;
|
||||
}
|
||||
|
||||
public synchronized Serializable generate(SessionImplementor session, Object obj)
|
||||
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
|
||||
int val = ( (Integer) doWorkInNewTransaction(session) ).intValue();
|
||||
if (val == 0) val = ( (Integer) doWorkInNewTransaction(session) ).intValue();
|
||||
return IdentifierGeneratorHelper.createNumber( val, returnClass );
|
||||
IntegralDataTypeHolder value = null;
|
||||
while ( value == null || value.lt( 1 ) ) {
|
||||
value = (IntegralDataTypeHolder) doWorkInNewTransaction( session );
|
||||
}
|
||||
return value.makeValue();
|
||||
}
|
||||
if (lo>maxLo) {
|
||||
int hival = ( (Integer) doWorkInNewTransaction(session) ).intValue();
|
||||
lo = (hival == 0) ? 1 : 0;
|
||||
hi = hival * (maxLo+1);
|
||||
log.debug("new hi value: " + hival);
|
||||
|
||||
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 IdentifierGeneratorHelper.createNumber( hi + lo++, returnClass );
|
||||
return value.makeValueThenIncrement();
|
||||
}
|
||||
|
||||
public void configure(Type type, Properties params, Dialect dialect) throws MappingException {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* 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
|
||||
* 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,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,7 +20,6 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.id;
|
||||
|
||||
|
@ -98,19 +97,19 @@ public class SequenceGenerator implements PersistentIdentifierGenerator, Configu
|
|||
sql = dialect.getSequenceNextValString( sequenceName );
|
||||
}
|
||||
|
||||
public Serializable generate(SessionImplementor session, Object obj)
|
||||
throws HibernateException {
|
||||
|
||||
try {
|
||||
public Serializable generate(SessionImplementor session, Object obj) {
|
||||
return generateHolder( session ).makeValue();
|
||||
}
|
||||
|
||||
protected IntegralDataTypeHolder generateHolder(SessionImplementor session) {
|
||||
try {
|
||||
PreparedStatement st = session.getBatcher().prepareSelectStatement(sql);
|
||||
try {
|
||||
ResultSet rs = st.executeQuery();
|
||||
try {
|
||||
rs.next();
|
||||
Serializable result = IdentifierGeneratorHelper.get(
|
||||
rs, identifierType
|
||||
);
|
||||
IntegralDataTypeHolder result = buildHolder();
|
||||
result.initialize( rs, 1 );
|
||||
if ( log.isDebugEnabled() ) {
|
||||
log.debug("Sequence identifier generated: " + result);
|
||||
}
|
||||
|
@ -123,7 +122,7 @@ public class SequenceGenerator implements PersistentIdentifierGenerator, Configu
|
|||
finally {
|
||||
session.getBatcher().closeStatement(st);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
catch (SQLException sqle) {
|
||||
throw JDBCExceptionHelper.convert(
|
||||
|
@ -131,9 +130,12 @@ public class SequenceGenerator implements PersistentIdentifierGenerator, Configu
|
|||
sqle,
|
||||
"could not get next sequence value",
|
||||
sql
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected IntegralDataTypeHolder buildHolder() {
|
||||
return IdentifierGeneratorHelper.getIntegralDataTypeHolder( identifierType.getReturnedClass() );
|
||||
}
|
||||
|
||||
public String[] sqlCreateStrings(Dialect dialect) throws HibernateException {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* 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
|
||||
* 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,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,7 +20,6 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.id;
|
||||
|
||||
|
@ -29,7 +28,6 @@ import java.util.Properties;
|
|||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
|
@ -59,33 +57,36 @@ public class SequenceHiLoGenerator extends SequenceGenerator {
|
|||
|
||||
private int maxLo;
|
||||
private int lo;
|
||||
private long hi;
|
||||
private Class returnClass;
|
||||
|
||||
private IntegralDataTypeHolder value;
|
||||
|
||||
public void configure(Type type, Properties params, Dialect d) throws MappingException {
|
||||
super.configure(type, params, d);
|
||||
maxLo = PropertiesHelper.getInt(MAX_LO, params, 9);
|
||||
lo = maxLo + 1; // so we "clock over" on the first invocation
|
||||
returnClass = type.getReturnedClass();
|
||||
}
|
||||
|
||||
public synchronized Serializable generate(SessionImplementor session, Object obj)
|
||||
throws HibernateException {
|
||||
if (maxLo < 1) {
|
||||
public synchronized Serializable generate(SessionImplementor session, Object obj) {
|
||||
// maxLo < 1 indicates a hilo generator with no hilo :?
|
||||
if ( maxLo < 1 ) {
|
||||
//keep the behavior consistent even for boundary usages
|
||||
long val = ( (Number) super.generate(session, obj) ).longValue();
|
||||
if (val == 0) val = ( (Number) super.generate(session, obj) ).longValue();
|
||||
return IdentifierGeneratorHelper.createNumber( val, returnClass );
|
||||
}
|
||||
if ( lo>maxLo ) {
|
||||
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);
|
||||
IntegralDataTypeHolder value = null;
|
||||
while ( value == null || value.lt( 0 ) ) {
|
||||
value = super.generateHolder( session );
|
||||
}
|
||||
return value.makeValue();
|
||||
}
|
||||
|
||||
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 @@ import org.hibernate.util.PropertiesHelper;
|
|||
* table to store the last generated value. It is not
|
||||
* intended that applications use this strategy directly.
|
||||
* However, it may be used to build other (efficient)
|
||||
* strategies. The returned type is <tt>Integer</tt>.<br>
|
||||
* <br>
|
||||
* The hi value MUST be fetched in a seperate transaction
|
||||
* to the <tt>Session</tt> transaction so the generator must
|
||||
* be able to obtain a new connection and commit it. Hence
|
||||
* this implementation may not be used when Hibernate is
|
||||
* fetching connections when the user is supplying
|
||||
* connections.<br>
|
||||
* <br>
|
||||
* The returned value is of type <tt>integer</tt>.<br>
|
||||
* <br>
|
||||
* strategies. The returned type is any supported by
|
||||
* {@link IntegralDataTypeHolder}
|
||||
* <p/>
|
||||
* The value MUST be fetched in a separate transaction
|
||||
* from that of the main {@link SessionImplementor session}
|
||||
* transaction so the generator must be able to obtain a new
|
||||
* connection and commit it. Hence this implementation may only
|
||||
* be used when Hibernate is fetching connections, not when the
|
||||
* user is supplying connections.
|
||||
* <p/>
|
||||
* 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
|
||||
*
|
||||
* @see TableHiLoGenerator
|
||||
|
@ -83,12 +87,15 @@ public class TableGenerator extends TransactionHelper
|
|||
|
||||
private static final Logger log = LoggerFactory.getLogger(TableGenerator.class);
|
||||
|
||||
private Type identifierType;
|
||||
private String tableName;
|
||||
private String columnName;
|
||||
private String query;
|
||||
private String update;
|
||||
|
||||
public void configure(Type type, Properties params, Dialect dialect) {
|
||||
identifierType = type;
|
||||
|
||||
ObjectNameNormalizer normalizer = ( ObjectNameNormalizer ) params.get( IDENTIFIER_NORMALIZER );
|
||||
|
||||
tableName = PropertiesHelper.getString( TABLE, params, DEFAULT_TABLE_NAME );
|
||||
|
@ -127,12 +134,13 @@ public class TableGenerator extends TransactionHelper
|
|||
" = ?";
|
||||
}
|
||||
|
||||
public synchronized Serializable generate(SessionImplementor session, Object object)
|
||||
throws HibernateException {
|
||||
int result = ( (Integer) doWorkInNewTransaction(session) ).intValue();
|
||||
return new Integer(result);
|
||||
public synchronized Serializable generate(SessionImplementor session, Object object) {
|
||||
return generateHolder( session ).makeValue();
|
||||
}
|
||||
|
||||
protected IntegralDataTypeHolder generateHolder(SessionImplementor session) {
|
||||
return (IntegralDataTypeHolder) doWorkInNewTransaction( session );
|
||||
}
|
||||
|
||||
public String[] sqlCreateStrings(Dialect dialect) throws HibernateException {
|
||||
return new String[] {
|
||||
|
@ -157,8 +165,19 @@ public class TableGenerator extends TransactionHelper
|
|||
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 {
|
||||
int result;
|
||||
IntegralDataTypeHolder value = buildHolder();
|
||||
int rows;
|
||||
do {
|
||||
// The loop ensures atomicity of the
|
||||
|
@ -175,7 +194,7 @@ public class TableGenerator extends TransactionHelper
|
|||
log.error(err);
|
||||
throw new IdentifierGenerationException(err);
|
||||
}
|
||||
result = rs.getInt(1);
|
||||
value.initialize( rs, 1 );
|
||||
rs.close();
|
||||
}
|
||||
catch (SQLException sqle) {
|
||||
|
@ -190,8 +209,8 @@ public class TableGenerator extends TransactionHelper
|
|||
SQL_STATEMENT_LOGGER.logStatement( sql, FormatStyle.BASIC );
|
||||
PreparedStatement ups = conn.prepareStatement(update);
|
||||
try {
|
||||
ups.setInt( 1, result + 1 );
|
||||
ups.setInt( 2, result );
|
||||
value.copy().increment().bind( ups, 1 );
|
||||
value.bind( ups, 2 );
|
||||
rows = ups.executeUpdate();
|
||||
}
|
||||
catch (SQLException sqle) {
|
||||
|
@ -203,6 +222,10 @@ public class TableGenerator extends TransactionHelper
|
|||
}
|
||||
}
|
||||
while (rows==0);
|
||||
return new Integer(result);
|
||||
return value;
|
||||
}
|
||||
|
||||
protected IntegralDataTypeHolder buildHolder() {
|
||||
return IdentifierGeneratorHelper.getIntegralDataTypeHolder( identifierType.getReturnedClass() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import java.util.Properties;
|
|||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
import org.hibernate.type.Type;
|
||||
|
@ -58,10 +57,10 @@ public class TableHiLoGenerator extends TableGenerator {
|
|||
*/
|
||||
public static final String MAX_LO = "max_lo";
|
||||
|
||||
private long hi;
|
||||
private int lo;
|
||||
private int maxLo;
|
||||
private Class returnClass;
|
||||
private int lo;
|
||||
|
||||
private IntegralDataTypeHolder value;
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(TableHiLoGenerator.class);
|
||||
|
||||
|
@ -69,26 +68,29 @@ public class TableHiLoGenerator extends TableGenerator {
|
|||
super.configure(type, params, d);
|
||||
maxLo = PropertiesHelper.getInt(MAX_LO, params, Short.MAX_VALUE);
|
||||
lo = maxLo + 1; // so we "clock over" on the first invocation
|
||||
returnClass = type.getReturnedClass();
|
||||
}
|
||||
|
||||
public synchronized Serializable generate(SessionImplementor session, Object obj)
|
||||
throws HibernateException {
|
||||
if (maxLo < 1) {
|
||||
public synchronized Serializable generate(SessionImplementor session, Object obj) {
|
||||
// maxLo < 1 indicates a hilo generator with no hilo :?
|
||||
if ( maxLo < 1 ) {
|
||||
//keep the behavior consistent even for boundary usages
|
||||
long val = ( (Number) super.generate(session, obj) ).longValue();
|
||||
if (val == 0) val = ( (Number) super.generate(session, obj) ).longValue();
|
||||
return IdentifierGeneratorHelper.createNumber( val, returnClass );
|
||||
}
|
||||
if (lo>maxLo) {
|
||||
long hival = ( (Number) super.generate(session, obj) ).longValue();
|
||||
lo = (hival == 0) ? 1 : 0;
|
||||
hi = hival * (maxLo+1);
|
||||
log.debug("new hi value: " + hival);
|
||||
IntegralDataTypeHolder value = null;
|
||||
while ( value == null || value.lt( 0 ) ) {
|
||||
value = generateHolder( session );
|
||||
}
|
||||
return value.makeValue();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
import org.hibernate.id.IntegralDataTypeHolder;
|
||||
|
||||
/**
|
||||
* Contract for providing callback access to a {@link DatabaseStructure},
|
||||
* typically from the {@link Optimizer}.
|
||||
|
@ -36,5 +38,5 @@ public interface AccessCallback {
|
|||
*
|
||||
* @return The next value.
|
||||
*/
|
||||
public long getNextValue();
|
||||
public IntegralDataTypeHolder getNextValue();
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@ package org.hibernate.id.enhanced;
|
|||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.hibernate.id.IntegralDataTypeHolder;
|
||||
|
||||
/**
|
||||
* Performs optimization on an optimizable identifier generator. Typically
|
||||
* 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
|
||||
* 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;
|
||||
* -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.
|
||||
|
|
|
@ -31,8 +31,8 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.id.IntegralDataTypeHolder;
|
||||
import org.hibernate.util.ReflectHelper;
|
||||
import org.hibernate.id.IdentifierGeneratorHelper;
|
||||
|
||||
/**
|
||||
* Factory for {@link Optimizer} instances.
|
||||
|
@ -97,17 +97,6 @@ public class OptimizerFactory {
|
|||
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
|
||||
* class which is used to represent the id (e.g. {@link java.lang.Long}).
|
||||
|
@ -131,7 +120,7 @@ public class OptimizerFactory {
|
|||
* every request.
|
||||
*/
|
||||
public static class NoopOptimizer extends OptimizerSupport {
|
||||
private long lastSourceValue = -1;
|
||||
private IntegralDataTypeHolder lastSourceValue;
|
||||
|
||||
public NoopOptimizer(Class returnClass, int incrementSize) {
|
||||
super( returnClass, incrementSize );
|
||||
|
@ -141,21 +130,21 @@ public class OptimizerFactory {
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
public Serializable generate(AccessCallback callback) {
|
||||
if ( lastSourceValue == -1 ) {
|
||||
while( lastSourceValue <= 0 ) {
|
||||
if ( lastSourceValue == null ) {
|
||||
do {
|
||||
lastSourceValue = callback.getNextValue();
|
||||
}
|
||||
} while ( lastSourceValue.lt( 1 ) );
|
||||
}
|
||||
else {
|
||||
lastSourceValue = callback.getNextValue();
|
||||
}
|
||||
return make( lastSourceValue );
|
||||
return lastSourceValue.makeValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public long getLastSourceValue() {
|
||||
public IntegralDataTypeHolder getLastSourceValue() {
|
||||
return lastSourceValue;
|
||||
}
|
||||
|
||||
|
@ -170,11 +159,40 @@ public class OptimizerFactory {
|
|||
/**
|
||||
* Optimizer which applies a 'hilo' algorithm in memory to achieve
|
||||
* 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 {
|
||||
private long lastSourceValue = -1;
|
||||
private long value;
|
||||
private long hiValue;
|
||||
private IntegralDataTypeHolder lastSourceValue;
|
||||
private IntegralDataTypeHolder upperLimit;
|
||||
private IntegralDataTypeHolder value;
|
||||
|
||||
public HiLoOptimizer(Class returnClass, int incrementSize) {
|
||||
super( returnClass, incrementSize );
|
||||
|
@ -190,26 +208,30 @@ public class OptimizerFactory {
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
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();
|
||||
while ( lastSourceValue <= 0 ) {
|
||||
while ( lastSourceValue.lt( 1 ) ) {
|
||||
lastSourceValue = callback.getNextValue();
|
||||
}
|
||||
hiValue = ( lastSourceValue * incrementSize ) + 1;
|
||||
value = hiValue - incrementSize;
|
||||
// upperLimit defines the upper end of the bucket values
|
||||
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();
|
||||
hiValue = ( lastSourceValue * incrementSize ) + 1;
|
||||
upperLimit = lastSourceValue.copy().multiplyBy( incrementSize ).increment();
|
||||
}
|
||||
return make( value++ );
|
||||
return value.makeValueThenIncrement();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public long getLastSourceValue() {
|
||||
public IntegralDataTypeHolder getLastSourceValue() {
|
||||
return lastSourceValue;
|
||||
}
|
||||
|
||||
|
@ -222,30 +244,38 @@ public class OptimizerFactory {
|
|||
|
||||
/**
|
||||
* Getter for property 'lastValue'.
|
||||
* <p/>
|
||||
* Exposure intended for testing purposes.
|
||||
*
|
||||
* @return Value for property 'lastValue'.
|
||||
*/
|
||||
public long getLastValue() {
|
||||
return value - 1;
|
||||
public IntegralDataTypeHolder getLastValue() {
|
||||
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() {
|
||||
return hiValue;
|
||||
public IntegralDataTypeHolder getHiValue() {
|
||||
return upperLimit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimizer which uses a pool of values, storing the next low value of the
|
||||
* 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 {
|
||||
private long value;
|
||||
private long hiValue = -1;
|
||||
private IntegralDataTypeHolder hiValue;
|
||||
private IntegralDataTypeHolder value;
|
||||
|
||||
public PooledOptimizer(Class returnClass, int incrementSize) {
|
||||
super( returnClass, incrementSize );
|
||||
|
@ -261,9 +291,9 @@ public class OptimizerFactory {
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
public synchronized Serializable generate(AccessCallback callback) {
|
||||
if ( hiValue < 0 ) {
|
||||
if ( hiValue == null ) {
|
||||
value = callback.getNextValue();
|
||||
if ( value < 1 ) {
|
||||
if ( value.lt( 1 ) ) {
|
||||
// unfortunately not really safe to normalize this
|
||||
// to 1 as an initial value like we do the others
|
||||
// because we would not be able to control this if
|
||||
|
@ -272,17 +302,17 @@ public class OptimizerFactory {
|
|||
}
|
||||
hiValue = callback.getNextValue();
|
||||
}
|
||||
else if ( value >= hiValue ) {
|
||||
else if ( ! hiValue.gt( value ) ) {
|
||||
hiValue = callback.getNextValue();
|
||||
value = hiValue - incrementSize;
|
||||
value = hiValue.copy().subtract( incrementSize );
|
||||
}
|
||||
return make( value++ );
|
||||
return value.makeValueThenIncrement();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public long getLastSourceValue() {
|
||||
public IntegralDataTypeHolder getLastSourceValue() {
|
||||
return hiValue;
|
||||
}
|
||||
|
||||
|
@ -295,11 +325,13 @@ public class OptimizerFactory {
|
|||
|
||||
/**
|
||||
* Getter for property 'lastValue'.
|
||||
* <p/>
|
||||
* Exposure intended for testing purposes.
|
||||
*
|
||||
* @return Value for property 'lastValue'.
|
||||
*/
|
||||
public long getLastValue() {
|
||||
return value - 1;
|
||||
public IntegralDataTypeHolder getLastValue() {
|
||||
return value.copy().decrement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@ import org.hibernate.dialect.Dialect;
|
|||
import org.hibernate.engine.SessionImplementor;
|
||||
import org.hibernate.exception.JDBCExceptionHelper;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.id.IdentifierGeneratorHelper;
|
||||
import org.hibernate.id.IntegralDataTypeHolder;
|
||||
|
||||
/**
|
||||
* Describes a sequence.
|
||||
|
@ -47,14 +49,21 @@ public class SequenceStructure implements DatabaseStructure {
|
|||
private final String sequenceName;
|
||||
private final int initialValue;
|
||||
private final int incrementSize;
|
||||
private final Class numberType;
|
||||
private final String sql;
|
||||
private boolean applyIncrementSizeToSourceValues;
|
||||
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.initialValue = initialValue;
|
||||
this.incrementSize = incrementSize;
|
||||
this.numberType = numberType;
|
||||
sql = dialect.getSequenceNextValString( sequenceName );
|
||||
}
|
||||
|
||||
|
@ -91,7 +100,7 @@ public class SequenceStructure implements DatabaseStructure {
|
|||
*/
|
||||
public AccessCallback buildCallback(final SessionImplementor session) {
|
||||
return new AccessCallback() {
|
||||
public long getNextValue() {
|
||||
public IntegralDataTypeHolder getNextValue() {
|
||||
accessCounter++;
|
||||
try {
|
||||
PreparedStatement st = session.getBatcher().prepareSelectStatement( sql );
|
||||
|
@ -99,11 +108,12 @@ public class SequenceStructure implements DatabaseStructure {
|
|||
ResultSet rs = st.executeQuery();
|
||||
try {
|
||||
rs.next();
|
||||
long result = rs.getLong( 1 );
|
||||
IntegralDataTypeHolder value = IdentifierGeneratorHelper.getIntegralDataTypeHolder( numberType );
|
||||
value.initialize( rs, 1 );
|
||||
if ( log.isDebugEnabled() ) {
|
||||
log.debug("Sequence identifier generated: " + result);
|
||||
log.debug( "Sequence value obtained: " + value.makeValue() );
|
||||
}
|
||||
return result;
|
||||
return value;
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
|
|
|
@ -178,7 +178,15 @@ public class SequenceStyleGenerator implements PersistentIdentifierGenerator, Co
|
|||
}
|
||||
}
|
||||
|
||||
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.databaseStructure.prepare( optimizer );
|
||||
|
@ -291,15 +299,16 @@ public class SequenceStyleGenerator implements PersistentIdentifierGenerator, Co
|
|||
/**
|
||||
* 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 dialect The dialect being used.
|
||||
* @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 initialValue The initial value.
|
||||
* @param incrementSize the increment size to use (after any adjustments).
|
||||
* @return The db structure representation
|
||||
* @param incrementSize the increment size to use (after any adjustments). @return The db structure representation
|
||||
*/
|
||||
protected DatabaseStructure buildDatabaseStructure(
|
||||
Type type,
|
||||
Properties params,
|
||||
Dialect dialect,
|
||||
boolean forceTableUse,
|
||||
|
@ -308,11 +317,11 @@ public class SequenceStyleGenerator implements PersistentIdentifierGenerator, Co
|
|||
int incrementSize) {
|
||||
boolean useSequence = dialect.supportsSequences() && !forceTableUse;
|
||||
if ( useSequence ) {
|
||||
return new SequenceStructure( dialect, sequenceName, initialValue, incrementSize );
|
||||
return new SequenceStructure( dialect, sequenceName, initialValue, incrementSize, type.getReturnedClass() );
|
||||
}
|
||||
else {
|
||||
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.slf4j.LoggerFactory;
|
|||
|
||||
import org.hibernate.engine.TransactionHelper;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
import org.hibernate.id.IdentifierGeneratorHelper;
|
||||
import org.hibernate.id.IntegralDataTypeHolder;
|
||||
import org.hibernate.id.PersistentIdentifierGenerator;
|
||||
import org.hibernate.id.Configurable;
|
||||
import org.hibernate.type.Type;
|
||||
|
@ -287,7 +289,7 @@ public class TableGenerator extends TransactionHelper implements PersistentIdent
|
|||
public void configure(Type type, Properties params, Dialect dialect) throws MappingException {
|
||||
identifierType = type;
|
||||
|
||||
tableName = determneGeneratorTableName( params, dialect );
|
||||
tableName = determineGeneratorTableName( params, dialect );
|
||||
segmentColumnName = determineSegmentColumnName( params, dialect );
|
||||
valueColumnName = determineValueColumnName( params, dialect );
|
||||
|
||||
|
@ -316,7 +318,7 @@ public class TableGenerator extends TransactionHelper implements PersistentIdent
|
|||
* @param dialect The dialect in effect
|
||||
* @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 );
|
||||
boolean isGivenNameUnqualified = name.indexOf( '.' ) < 0;
|
||||
if ( isGivenNameUnqualified ) {
|
||||
|
@ -450,8 +452,8 @@ public class TableGenerator extends TransactionHelper implements PersistentIdent
|
|||
public synchronized Serializable generate(final SessionImplementor session, Object obj) {
|
||||
return optimizer.generate(
|
||||
new AccessCallback() {
|
||||
public long getNextValue() {
|
||||
return ( ( Number ) doWorkInNewTransaction( session ) ).longValue();
|
||||
public IntegralDataTypeHolder getNextValue() {
|
||||
return ( IntegralDataTypeHolder ) doWorkInNewTransaction( session );
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -461,7 +463,7 @@ public class TableGenerator extends TransactionHelper implements PersistentIdent
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
public Serializable doWorkInCurrentTransaction(Connection conn, String sql) throws SQLException {
|
||||
int result;
|
||||
IntegralDataTypeHolder value = IdentifierGeneratorHelper.getIntegralDataTypeHolder( identifierType.getReturnedClass() );
|
||||
int rows;
|
||||
do {
|
||||
SQL_STATEMENT_LOGGER.logStatement( selectQuery, FormatStyle.BASIC );
|
||||
|
@ -470,13 +472,13 @@ public class TableGenerator extends TransactionHelper implements PersistentIdent
|
|||
selectPS.setString( 1, segmentValue );
|
||||
ResultSet selectRS = selectPS.executeQuery();
|
||||
if ( !selectRS.next() ) {
|
||||
value.initialize( initialValue );
|
||||
PreparedStatement insertPS = null;
|
||||
try {
|
||||
result = initialValue;
|
||||
SQL_STATEMENT_LOGGER.logStatement( insertQuery, FormatStyle.BASIC );
|
||||
insertPS = conn.prepareStatement( insertQuery );
|
||||
insertPS.setString( 1, segmentValue );
|
||||
insertPS.setLong( 2, result );
|
||||
value.bind( insertPS, 2 );
|
||||
insertPS.execute();
|
||||
}
|
||||
finally {
|
||||
|
@ -486,7 +488,7 @@ public class TableGenerator extends TransactionHelper implements PersistentIdent
|
|||
}
|
||||
}
|
||||
else {
|
||||
result = selectRS.getInt( 1 );
|
||||
value.initialize( selectRS, 1 );
|
||||
}
|
||||
selectRS.close();
|
||||
}
|
||||
|
@ -501,10 +503,15 @@ public class TableGenerator extends TransactionHelper implements PersistentIdent
|
|||
SQL_STATEMENT_LOGGER.logStatement( updateQuery, FormatStyle.BASIC );
|
||||
PreparedStatement updatePS = conn.prepareStatement( updateQuery );
|
||||
try {
|
||||
long newValue = optimizer.applyIncrementSizeToSourceValues()
|
||||
? result + incrementSize : result + 1;
|
||||
updatePS.setLong( 1, newValue );
|
||||
updatePS.setLong( 2, result );
|
||||
final IntegralDataTypeHolder updateValue = value.copy();
|
||||
if ( optimizer.applyIncrementSizeToSourceValues() ) {
|
||||
updateValue.add( incrementSize );
|
||||
}
|
||||
else {
|
||||
updateValue.increment();
|
||||
}
|
||||
updateValue.bind( updatePS, 1 );
|
||||
value.bind( updatePS, 2 );
|
||||
updatePS.setString( 3, segmentValue );
|
||||
rows = updatePS.executeUpdate();
|
||||
}
|
||||
|
@ -520,7 +527,7 @@ public class TableGenerator extends TransactionHelper implements PersistentIdent
|
|||
|
||||
accessCount++;
|
||||
|
||||
return new Integer( result );
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -40,6 +40,8 @@ import org.hibernate.dialect.Dialect;
|
|||
import org.hibernate.engine.SessionImplementor;
|
||||
import org.hibernate.engine.TransactionHelper;
|
||||
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.SQLStatementLogger;
|
||||
|
||||
|
@ -56,17 +58,25 @@ public class TableStructure extends TransactionHelper implements DatabaseStructu
|
|||
private final String valueColumnName;
|
||||
private final int initialValue;
|
||||
private final int incrementSize;
|
||||
private final Class numberType;
|
||||
private final String selectQuery;
|
||||
private final String updateQuery;
|
||||
|
||||
private boolean applyIncrementSizeToSourceValues;
|
||||
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.initialValue = initialValue;
|
||||
this.incrementSize = incrementSize;
|
||||
this.valueColumnName = valueColumnName;
|
||||
this.numberType = numberType;
|
||||
|
||||
selectQuery = "select " + valueColumnName + " as id_val" +
|
||||
" from " + dialect.appendLockHint( LockMode.PESSIMISTIC_WRITE, tableName ) +
|
||||
|
@ -117,8 +127,8 @@ public class TableStructure extends TransactionHelper implements DatabaseStructu
|
|||
*/
|
||||
public AccessCallback buildCallback(final SessionImplementor session) {
|
||||
return new AccessCallback() {
|
||||
public long getNextValue() {
|
||||
return ( ( Number ) doWorkInNewTransaction( session ) ).longValue();
|
||||
public IntegralDataTypeHolder getNextValue() {
|
||||
return ( IntegralDataTypeHolder ) doWorkInNewTransaction( session );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -152,7 +162,7 @@ public class TableStructure extends TransactionHelper implements DatabaseStructu
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
protected Serializable doWorkInCurrentTransaction(Connection conn, String sql) throws SQLException {
|
||||
long result;
|
||||
IntegralDataTypeHolder value = IdentifierGeneratorHelper.getIntegralDataTypeHolder( numberType );
|
||||
int rows;
|
||||
do {
|
||||
SQL_STATEMENT_LOGGER.logStatement( selectQuery, FormatStyle.BASIC );
|
||||
|
@ -164,7 +174,7 @@ public class TableStructure extends TransactionHelper implements DatabaseStructu
|
|||
log.error( err );
|
||||
throw new IdentifierGenerationException( err );
|
||||
}
|
||||
result = selectRS.getLong( 1 );
|
||||
value.initialize( selectRS, 1 );
|
||||
selectRS.close();
|
||||
}
|
||||
catch ( SQLException sqle ) {
|
||||
|
@ -178,9 +188,10 @@ public class TableStructure extends TransactionHelper implements DatabaseStructu
|
|||
SQL_STATEMENT_LOGGER.logStatement( updateQuery, FormatStyle.BASIC );
|
||||
PreparedStatement updatePS = conn.prepareStatement( updateQuery );
|
||||
try {
|
||||
int increment = applyIncrementSizeToSourceValues ? incrementSize : 1;
|
||||
updatePS.setLong( 1, result + increment );
|
||||
updatePS.setLong( 2, result );
|
||||
final int increment = applyIncrementSizeToSourceValues ? incrementSize : 1;
|
||||
final IntegralDataTypeHolder updateValue = value.copy().add( increment );
|
||||
updateValue.bind( updatePS, 1 );
|
||||
value.bind( updatePS, 2 );
|
||||
rows = updatePS.executeUpdate();
|
||||
}
|
||||
catch ( SQLException sqle ) {
|
||||
|
@ -194,7 +205,7 @@ public class TableStructure extends TransactionHelper implements DatabaseStructu
|
|||
|
||||
accessCounter++;
|
||||
|
||||
return new Long( result );
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -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 @@ package org.hibernate.test.idgen.enhanced;
|
|||
import junit.framework.Test;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
import org.hibernate.id.IdentifierGeneratorHelper;
|
||||
import org.hibernate.id.IntegralDataTypeHolder;
|
||||
import org.hibernate.junit.UnitTestCase;
|
||||
import org.hibernate.id.enhanced.Optimizer;
|
||||
import org.hibernate.id.enhanced.OptimizerFactory;
|
||||
|
@ -88,7 +90,7 @@ public class OptimizerUnitTest extends UnitTestCase {
|
|||
next = ( Long ) optimizer.generate( sequence );
|
||||
assertEquals( i, next.intValue() );
|
||||
}
|
||||
assertEquals( 2, sequence.getTimesCalled() ); // twice to initialze state
|
||||
assertEquals( 2, sequence.getTimesCalled() ); // twice to initialize state
|
||||
assertEquals( 11, sequence.getCurrentValue() );
|
||||
// force a "clock over"
|
||||
next = ( Long ) optimizer.generate( sequence );
|
||||
|
@ -98,7 +100,7 @@ public class OptimizerUnitTest extends UnitTestCase {
|
|||
}
|
||||
|
||||
private static class SourceMock implements AccessCallback {
|
||||
private long value;
|
||||
private IdentifierGeneratorHelper.BasicHolder value = new IdentifierGeneratorHelper.BasicHolder( Long.class );
|
||||
private int increment;
|
||||
private int timesCalled = 0;
|
||||
|
||||
|
@ -108,12 +110,12 @@ public class OptimizerUnitTest extends UnitTestCase {
|
|||
|
||||
public SourceMock(long initialValue, int increment) {
|
||||
this.increment = increment;
|
||||
this.value = initialValue - increment;
|
||||
this.value.initialize( initialValue - increment );
|
||||
}
|
||||
|
||||
public long getNextValue() {
|
||||
public IntegralDataTypeHolder getNextValue() {
|
||||
timesCalled++;
|
||||
return ( value += increment );
|
||||
return value.add( increment ).copy();
|
||||
}
|
||||
|
||||
public int getTimesCalled() {
|
||||
|
@ -121,7 +123,7 @@ public class OptimizerUnitTest extends UnitTestCase {
|
|||
}
|
||||
|
||||
public long getCurrentValue() {
|
||||
return value;
|
||||
return value.getActualLongValue();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,13 +2,15 @@ package org.hibernate.test.idgen.enhanced.forcedtable;
|
|||
|
||||
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.FunctionalTestClassTestSuite;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
||||
import org.hibernate.id.enhanced.TableStructure;
|
||||
import org.hibernate.id.enhanced.OptimizerFactory;
|
||||
import org.hibernate.Session;
|
||||
|
||||
import static org.hibernate.id.IdentifierGeneratorHelper.BasicHolder;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
@ -54,7 +56,7 @@ public class BasicForcedTableSequenceTest extends DatabaseSpecificFunctionalTest
|
|||
long expectedId = i + 1;
|
||||
assertEquals( expectedId, entities[i].getId().longValue() );
|
||||
assertEquals( expectedId, generator.getDatabaseStructure().getTimesAccessed() );
|
||||
assertEquals( expectedId, generator.getOptimizer().getLastSourceValue() );
|
||||
assertEquals( expectedId, ( (BasicHolder) generator.getOptimizer().getLastSourceValue() ).getActualLongValue() );
|
||||
}
|
||||
s.getTransaction().commit();
|
||||
|
||||
|
|
|
@ -2,13 +2,15 @@ package org.hibernate.test.idgen.enhanced.forcedtable;
|
|||
|
||||
import junit.framework.Test;
|
||||
|
||||
import org.hibernate.junit.functional.DatabaseSpecificFunctionalTestCase;
|
||||
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
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.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}
|
||||
|
@ -54,18 +56,18 @@ public class HiLoForcedTableSequenceTest extends DatabaseSpecificFunctionalTestC
|
|||
s.save( entities[i] );
|
||||
long expectedId = i + 1;
|
||||
assertEquals( expectedId, entities[i].getId().longValue() );
|
||||
assertEquals( 1, generator.getOptimizer().getLastSourceValue() );
|
||||
assertEquals( i + 1, optimizer.getLastValue() );
|
||||
assertEquals( increment + 1, optimizer.getHiValue() );
|
||||
assertEquals( 1, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() );
|
||||
assertEquals( i + 1, ( (BasicHolder) optimizer.getLastValue() ).getActualLongValue() );
|
||||
assertEquals( increment + 1, ( (BasicHolder) optimizer.getHiValue() ).getActualLongValue() );
|
||||
}
|
||||
// now force a "clock over"
|
||||
entities[ increment ] = new Entity( "" + increment );
|
||||
s.save( entities[ increment ] );
|
||||
long expectedId = optimizer.getIncrementSize() + 1;
|
||||
assertEquals( expectedId, entities[ optimizer.getIncrementSize() ].getId().longValue() );
|
||||
assertEquals( 2, optimizer.getLastSourceValue() ); // initialization + clokc-over
|
||||
assertEquals( increment + 1, optimizer.getLastValue() );
|
||||
assertEquals( ( increment * 2 ) + 1, optimizer.getHiValue() );
|
||||
assertEquals( 2, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() ); // initialization + clock-over
|
||||
assertEquals( increment + 1, ( (BasicHolder) optimizer.getLastValue() ).getActualLongValue() );
|
||||
assertEquals( ( increment * 2 ) + 1, ( (BasicHolder) optimizer.getHiValue() ).getActualLongValue() );
|
||||
|
||||
s.getTransaction().commit();
|
||||
|
||||
|
|
|
@ -2,13 +2,15 @@ package org.hibernate.test.idgen.enhanced.forcedtable;
|
|||
|
||||
import junit.framework.Test;
|
||||
|
||||
import org.hibernate.junit.functional.DatabaseSpecificFunctionalTestCase;
|
||||
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
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.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}
|
||||
|
@ -54,19 +56,21 @@ public class PooledForcedTableSequenceTest extends DatabaseSpecificFunctionalTes
|
|||
s.save( entities[i] );
|
||||
long expectedId = i + 1;
|
||||
assertEquals( expectedId, entities[i].getId().longValue() );
|
||||
assertEquals( 2, generator.getDatabaseStructure().getTimesAccessed() ); // initialization calls table twice
|
||||
assertEquals( increment + 1, optimizer.getLastSourceValue() ); // initialization calls table twice
|
||||
assertEquals( i + 1, optimizer.getLastValue() );
|
||||
assertEquals( increment + 1, optimizer.getLastSourceValue() );
|
||||
// NOTE : initialization calls table twice
|
||||
assertEquals( 2, generator.getDatabaseStructure().getTimesAccessed() );
|
||||
assertEquals( increment + 1, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() );
|
||||
assertEquals( i + 1, ( (BasicHolder) optimizer.getLastValue() ).getActualLongValue() );
|
||||
assertEquals( increment + 1, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() );
|
||||
}
|
||||
// now force a "clock over"
|
||||
entities[ increment ] = new Entity( "" + increment );
|
||||
s.save( entities[ increment ] );
|
||||
long expectedId = optimizer.getIncrementSize() + 1;
|
||||
assertEquals( expectedId, entities[ optimizer.getIncrementSize() ].getId().longValue() );
|
||||
assertEquals( 3, generator.getDatabaseStructure().getTimesAccessed() ); // initialization (2) + clock over
|
||||
assertEquals( ( increment * 2 ) + 1, optimizer.getLastSourceValue() ); // initialization (2) + clock over
|
||||
assertEquals( increment + 1, optimizer.getLastValue() );
|
||||
// initialization (2) + clock over
|
||||
assertEquals( 3, generator.getDatabaseStructure().getTimesAccessed() );
|
||||
assertEquals( ( increment * 2 ) + 1, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() );
|
||||
assertEquals( increment + 1, ( (BasicHolder) optimizer.getLastValue() ).getActualLongValue() );
|
||||
s.getTransaction().commit();
|
||||
|
||||
s.beginTransaction();
|
||||
|
|
|
@ -8,6 +8,8 @@ import org.hibernate.Session;
|
|||
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
import static org.hibernate.id.IdentifierGeneratorHelper.BasicHolder;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
|
@ -41,7 +43,7 @@ public class BasicSequenceTest extends FunctionalTestCase {
|
|||
long expectedId = i + 1;
|
||||
assertEquals( expectedId, entities[i].getId().longValue() );
|
||||
assertEquals( expectedId, generator.getDatabaseStructure().getTimesAccessed() );
|
||||
assertEquals( expectedId, generator.getOptimizer().getLastSourceValue() );
|
||||
assertEquals( expectedId, ( (BasicHolder) generator.getOptimizer().getLastSourceValue() ).getActualLongValue() );
|
||||
}
|
||||
s.getTransaction().commit();
|
||||
|
||||
|
|
|
@ -9,6 +9,9 @@ import org.hibernate.id.enhanced.OptimizerFactory;
|
|||
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
import static org.hibernate.id.IdentifierGeneratorHelper.BasicHolder;
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
|
@ -42,17 +45,17 @@ public class HiLoSequenceTest extends FunctionalTestCase {
|
|||
entities[i] = new Entity( "" + ( i + 1 ) );
|
||||
s.save( entities[i] );
|
||||
assertEquals( 1, generator.getDatabaseStructure().getTimesAccessed() ); // initialization
|
||||
assertEquals( 1, optimizer.getLastSourceValue() ); // initialization
|
||||
assertEquals( i + 1, optimizer.getLastValue() );
|
||||
assertEquals( increment + 1, optimizer.getHiValue() );
|
||||
assertEquals( 1, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() ); // initialization
|
||||
assertEquals( i + 1, ( (BasicHolder) optimizer.getLastValue() ).getActualLongValue() );
|
||||
assertEquals( increment + 1, ( (BasicHolder) optimizer.getHiValue() ).getActualLongValue() );
|
||||
}
|
||||
// now force a "clock over"
|
||||
entities[ increment ] = new Entity( "" + increment );
|
||||
s.save( entities[ increment ] );
|
||||
assertEquals( 2, generator.getDatabaseStructure().getTimesAccessed() ); // initialization
|
||||
assertEquals( 2, optimizer.getLastSourceValue() ); // initialization
|
||||
assertEquals( increment + 1, optimizer.getLastValue() );
|
||||
assertEquals( ( increment * 2 ) + 1, optimizer.getHiValue() );
|
||||
assertEquals( 2, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() ); // initialization
|
||||
assertEquals( increment + 1, ( (BasicHolder) optimizer.getLastValue() ).getActualLongValue() );
|
||||
assertEquals( ( increment * 2 ) + 1, ( (BasicHolder) optimizer.getHiValue() ).getActualLongValue() );
|
||||
|
||||
s.getTransaction().commit();
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ import org.hibernate.id.enhanced.OptimizerFactory;
|
|||
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
||||
import org.hibernate.Session;
|
||||
|
||||
import static org.hibernate.id.IdentifierGeneratorHelper.BasicHolder;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
|
@ -42,16 +44,16 @@ public class PooledSequenceTest extends FunctionalTestCase {
|
|||
entities[i] = new Entity( "" + ( i + 1 ) );
|
||||
s.save( entities[i] );
|
||||
assertEquals( 2, generator.getDatabaseStructure().getTimesAccessed() ); // initialization calls seq twice
|
||||
assertEquals( increment + 1, optimizer.getLastSourceValue() ); // initialization calls seq twice
|
||||
assertEquals( i + 1, optimizer.getLastValue() );
|
||||
assertEquals( increment + 1, optimizer.getLastSourceValue() );
|
||||
assertEquals( increment + 1, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() ); // initialization calls seq twice
|
||||
assertEquals( i + 1, ( (BasicHolder) optimizer.getLastValue() ).getActualLongValue() );
|
||||
assertEquals( increment + 1, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() );
|
||||
}
|
||||
// now force a "clock over"
|
||||
entities[ increment ] = new Entity( "" + increment );
|
||||
s.save( entities[ increment ] );
|
||||
assertEquals( 3, generator.getDatabaseStructure().getTimesAccessed() ); // initialization (2) + clock over
|
||||
assertEquals( ( increment * 2 ) + 1, optimizer.getLastSourceValue() ); // initialization (2) + clock over
|
||||
assertEquals( increment + 1, optimizer.getLastValue() );
|
||||
assertEquals( ( increment * 2 ) + 1, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() ); // initialization (2) + clock over
|
||||
assertEquals( increment + 1, ( (BasicHolder) optimizer.getLastValue() ).getActualLongValue() );
|
||||
s.getTransaction().commit();
|
||||
|
||||
s.beginTransaction();
|
||||
|
|
|
@ -8,6 +8,8 @@ import org.hibernate.persister.entity.EntityPersister;
|
|||
import org.hibernate.id.enhanced.TableGenerator;
|
||||
import org.hibernate.Session;
|
||||
|
||||
import static org.hibernate.id.IdentifierGeneratorHelper.BasicHolder;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
|
@ -41,7 +43,7 @@ public class BasicTableTest extends FunctionalTestCase {
|
|||
long expectedId = i + 1;
|
||||
assertEquals( expectedId, entities[i].getId().longValue() );
|
||||
assertEquals( expectedId, generator.getTableAccessCount() );
|
||||
assertEquals( expectedId, generator.getOptimizer().getLastSourceValue() );
|
||||
assertEquals( expectedId, ( (BasicHolder) generator.getOptimizer().getLastSourceValue() ).getActualLongValue() );
|
||||
}
|
||||
s.getTransaction().commit();
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ import org.hibernate.id.enhanced.OptimizerFactory;
|
|||
import org.hibernate.id.enhanced.TableGenerator;
|
||||
import org.hibernate.Session;
|
||||
|
||||
import static org.hibernate.id.IdentifierGeneratorHelper.BasicHolder;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
|
@ -42,17 +44,17 @@ public class HiLoTableTest extends FunctionalTestCase {
|
|||
entities[i] = new Entity( "" + ( i + 1 ) );
|
||||
s.save( entities[i] );
|
||||
assertEquals( 1, generator.getTableAccessCount() ); // initialization
|
||||
assertEquals( 1, optimizer.getLastSourceValue() ); // initialization
|
||||
assertEquals( i + 1, optimizer.getLastValue() );
|
||||
assertEquals( increment + 1, optimizer.getHiValue() );
|
||||
assertEquals( 1, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() ); // initialization
|
||||
assertEquals( i + 1, ( (BasicHolder) optimizer.getLastValue() ).getActualLongValue() );
|
||||
assertEquals( increment + 1, ( (BasicHolder) optimizer.getHiValue() ).getActualLongValue() );
|
||||
}
|
||||
// now force a "clock over"
|
||||
entities[ increment ] = new Entity( "" + increment );
|
||||
s.save( entities[ increment ] );
|
||||
assertEquals( 2, generator.getTableAccessCount() ); // initialization
|
||||
assertEquals( 2, optimizer.getLastSourceValue() ); // initialization
|
||||
assertEquals( increment + 1, optimizer.getLastValue() );
|
||||
assertEquals( ( increment * 2 ) + 1, optimizer.getHiValue() );
|
||||
assertEquals( 2, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() ); // initialization
|
||||
assertEquals( increment + 1, ( (BasicHolder) optimizer.getLastValue() ).getActualLongValue() );
|
||||
assertEquals( ( increment * 2 ) + 1, ( (BasicHolder) optimizer.getHiValue() ).getActualLongValue() );
|
||||
|
||||
s.getTransaction().commit();
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ import org.hibernate.id.enhanced.OptimizerFactory;
|
|||
import org.hibernate.id.enhanced.TableGenerator;
|
||||
import org.hibernate.Session;
|
||||
|
||||
import static org.hibernate.id.IdentifierGeneratorHelper.BasicHolder;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
|
@ -42,16 +44,16 @@ public class PooledTableTest extends FunctionalTestCase {
|
|||
entities[i] = new Entity( "" + ( i + 1 ) );
|
||||
s.save( entities[i] );
|
||||
assertEquals( 2, generator.getTableAccessCount() ); // initialization calls seq twice
|
||||
assertEquals( increment + 1, optimizer.getLastSourceValue() ); // initialization calls seq twice
|
||||
assertEquals( i + 1, optimizer.getLastValue() );
|
||||
assertEquals( increment + 1, optimizer.getLastSourceValue() );
|
||||
assertEquals( increment + 1, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() ); // initialization calls seq twice
|
||||
assertEquals( i + 1, ( (BasicHolder) optimizer.getLastValue() ).getActualLongValue() );
|
||||
assertEquals( increment + 1, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() );
|
||||
}
|
||||
// now force a "clock over"
|
||||
entities[ increment ] = new Entity( "" + increment );
|
||||
s.save( entities[ increment ] );
|
||||
assertEquals( 3, generator.getTableAccessCount() ); // initialization (2) + clock over
|
||||
assertEquals( ( increment * 2 ) + 1, optimizer.getLastSourceValue() ); // initialization (2) + clock over
|
||||
assertEquals( increment + 1, optimizer.getLastValue() );
|
||||
assertEquals( ( increment * 2 ) + 1, ( (BasicHolder) optimizer.getLastSourceValue() ).getActualLongValue() ); // initialization (2) + clock over
|
||||
assertEquals( increment + 1, ( (BasicHolder) optimizer.getLastValue() ).getActualLongValue() );
|
||||
s.getTransaction().commit();
|
||||
|
||||
s.beginTransaction();
|
||||
|
|
Loading…
Reference in New Issue