HHH-5268 - Support for java.util.UUID properties/generators

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@19646 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Steve Ebersole 2010-06-01 18:34:12 +00:00
parent 41b2416be4
commit 7aa8449788
25 changed files with 1595 additions and 71 deletions

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * Hibernate, Relational Persistence for Idiomatic Java
* *
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC. * distributed under license by Red Hat Inc.
* *
* This copyrighted material is made available to anyone wishing to use, modify, * This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,7 +20,6 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.id; package org.hibernate.id;
@ -41,8 +40,19 @@ import org.hibernate.exception.JDBCExceptionHelper;
* @author Joseph Fifield * @author Joseph Fifield
*/ */
public class GUIDGenerator implements IdentifierGenerator { public class GUIDGenerator implements IdentifierGenerator {
private static final Logger log = LoggerFactory.getLogger(GUIDGenerator.class); private static final Logger log = LoggerFactory.getLogger(GUIDGenerator.class);
private static boolean warned = false;
public GUIDGenerator() {
if ( ! warned ) {
warned = true;
log.warn(
"DEPRECATED : use {} instead with custom {} implementation",
UUIDGenerator.class.getName(),
UUIDGenerationStrategy.class.getName()
);
}
}
public Serializable generate(SessionImplementor session, Object obj) public Serializable generate(SessionImplementor session, Object obj)
throws HibernateException { throws HibernateException {

View File

@ -0,0 +1,64 @@
/*
* 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.util.UUID;
import org.hibernate.engine.SessionImplementor;
/**
* A strategy for generating a variant 2 {@link UUID} value.
*
* @author Steve Ebersole
*/
public interface UUIDGenerationStrategy extends Serializable {
/**
* Which variant, according to IETF RFC 4122, of UUID does this strategy generate? RFC 4122 defines
* 5 variants (though it only describes algorithms to generate 4):<ul>
* <li>1 = time based</li>
* <li>2 = DCE based using POSIX UIDs</li>
* <li>3 = name based (md5 hash)</li>
* <li>4 = random numbers based</li>
* <li>5 = name based (sha-1 hash)</li>
* </ul>
* Returning the values above should be reserved to those generators creating variants compliant with the
* corresponding RFC definition; others can feel free to return other values as they see fit.
* <p/>
* Informational only, and not used at this time.
*
* @return The supported generation version
*/
public int getGeneratedVersion();
/**
* Generate the UUID.
*
* @param session The session asking for the generation
*
* @return The generated UUID.
*/
public UUID generateUUID(SessionImplementor session);
}

View File

@ -0,0 +1,112 @@
/*
* 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.util.Properties;
import java.util.UUID;
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;
import org.hibernate.id.uuid.StandardRandomStrategy;
import org.hibernate.type.Type;
import org.hibernate.type.descriptor.java.UUIDTypeDescriptor;
import org.hibernate.util.ReflectHelper;
/**
* An {@link IdentifierGenerator} which generates {@link UUID} values using a pluggable
* {@link UUIDGenerationStrategy generation strategy}. The values this generator can return
* include {@link UUID}, {@link String} and byte[16]
* <p/>
* Supports 2 config parameters:<ul>
* <li>{@link #UUID_GEN_STRATEGY} - names the {@link UUIDGenerationStrategy} instance to use</li>
* <li>{@link #UUID_GEN_STRATEGY_CLASS} - names the {@link UUIDGenerationStrategy} class to use</li>
* </ul>
* <p/>
* Currently there are 2 standard implementations of {@link UUIDGenerationStrategy}:<ul>
* <li>{@link StandardRandomStrategy} (the default, if none specified)</li>
* <li>{@link org.hibernate.id.uuid.CustomVersionOneStrategy}</li>
* </ul>
*
* @author Steve Ebersole
*/
public class UUIDGenerator implements IdentifierGenerator, Configurable {
public static final String UUID_GEN_STRATEGY = "uuid_gen_strategy";
public static final String UUID_GEN_STRATEGY_CLASS = "uuid_gen_strategy_class";
private static final Logger log = LoggerFactory.getLogger( UUIDGenerator.class );
private UUIDGenerationStrategy strategy;
private UUIDTypeDescriptor.ValueTransformer valueTransformer;
public void configure(Type type, Properties params, Dialect d) throws MappingException {
// check first for the strategy instance
strategy = (UUIDGenerationStrategy) params.get( UUID_GEN_STRATEGY );
if ( strategy == null ) {
// next check for the strategy class
final String strategyClassName = params.getProperty( UUID_GEN_STRATEGY_CLASS );
if ( strategyClassName != null ) {
try {
final Class strategyClass = ReflectHelper.classForName( strategyClassName );
try {
strategy = (UUIDGenerationStrategy) strategyClass.newInstance();
}
catch ( Exception ignore ) {
log.warn( "Unable to instantiate UUID generation strategy class : {}", ignore );
}
}
catch ( ClassNotFoundException ignore ) {
log.warn( "Unable to locate requested UUID generation strategy class : {}", strategyClassName );
}
}
}
if ( strategy == null ) {
// lastly use the standard random generator
strategy = StandardRandomStrategy.INSTANCE;
}
if ( UUID.class.isAssignableFrom( type.getReturnedClass() ) ) {
valueTransformer = UUIDTypeDescriptor.PassThroughTransformer.INSTANCE;
}
else if ( String.class.isAssignableFrom( type.getReturnedClass() ) ) {
valueTransformer = UUIDTypeDescriptor.ToStringTransformer.INSTANCE;
}
else if ( byte[].class.isAssignableFrom( type.getReturnedClass() ) ) {
valueTransformer = UUIDTypeDescriptor.ToBytesTransformer.INSTANCE;
}
else {
throw new HibernateException( "Unanticipated return type [" + type.getReturnedClass().getName() + "] for UUID conversion" );
}
}
public Serializable generate(SessionImplementor session, Object object) throws HibernateException {
return valueTransformer.transform( strategy.generateUUID( session ) );
}
}

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * Hibernate, Relational Persistence for Idiomatic Java
* *
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC. * distributed under license by Red Hat Inc.
* *
* This copyrighted material is made available to anyone wishing to use, modify, * This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,14 +20,15 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.id; package org.hibernate.id;
import java.io.Serializable; import java.io.Serializable;
import java.util.Properties; import java.util.Properties;
import org.hibernate.Hibernate; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.SessionImplementor; import org.hibernate.engine.SessionImplementor;
import org.hibernate.type.Type; import org.hibernate.type.Type;
@ -45,54 +46,54 @@ import org.hibernate.util.PropertiesHelper;
* *
* @author Gavin King * @author Gavin King
*/ */
public class UUIDHexGenerator extends AbstractUUIDGenerator implements Configurable { public class UUIDHexGenerator extends AbstractUUIDGenerator implements Configurable {
private static final Logger log = LoggerFactory.getLogger( UUIDHexGenerator.class );
private static boolean warned = false;
private String sep = ""; private String sep = "";
protected String format(int intval) { public UUIDHexGenerator() {
String formatted = Integer.toHexString(intval); if ( ! warned ) {
StringBuffer buf = new StringBuffer("00000000"); warned = true;
buf.replace( 8-formatted.length(), 8, formatted ); log.warn(
return buf.toString(); "Using {} which does not generate IETF RFC 4122 compliant UUID values; consider using {} instead",
this.getClass().getName(),
UUIDGenerator.class.getName()
);
}
} }
protected String format(short shortval) { /**
String formatted = Integer.toHexString(shortval); * {@inheritDoc}
StringBuffer buf = new StringBuffer("0000"); */
buf.replace( 4-formatted.length(), 4, formatted ); public void configure(Type type, Properties params, Dialect d) {
return buf.toString(); sep = PropertiesHelper.getString( "separator", params, "" );
} }
/**
* {@inheritDoc}
*/
public Serializable generate(SessionImplementor session, Object obj) { public Serializable generate(SessionImplementor session, Object obj) {
return new StringBuffer(36) return new StringBuffer( 36 )
.append( format( getIP() ) ).append(sep) .append( format( getIP() ) ).append( sep )
.append( format( getJVM() ) ).append(sep) .append( format( getJVM() ) ).append( sep )
.append( format( getHiTime() ) ).append(sep) .append( format( getHiTime() ) ).append( sep )
.append( format( getLoTime() ) ).append(sep) .append( format( getLoTime() ) ).append( sep )
.append( format( getCount() ) ) .append( format( getCount() ) )
.toString(); .toString();
} }
public void configure(Type type, Properties params, Dialect d) { protected String format(int intValue) {
sep = PropertiesHelper.getString("separator", params, ""); String formatted = Integer.toHexString( intValue );
StringBuffer buf = new StringBuffer( "00000000" );
buf.replace( 8 - formatted.length(), 8, formatted );
return buf.toString();
} }
public static void main( String[] args ) throws Exception { protected String format(short shortValue) {
Properties props = new Properties(); String formatted = Integer.toHexString( shortValue );
props.setProperty("separator", "/"); StringBuffer buf = new StringBuffer( "0000" );
IdentifierGenerator gen = new UUIDHexGenerator(); buf.replace( 4 - formatted.length(), 4, formatted );
( (Configurable) gen ).configure(Hibernate.STRING, props, null); return buf.toString();
IdentifierGenerator gen2 = new UUIDHexGenerator();
( (Configurable) gen2 ).configure(Hibernate.STRING, props, null);
for ( int i=0; i<10; i++) {
String id = (String) gen.generate(null, null);
System.out.println(id);
String id2 = (String) gen2.generate(null, null);
System.out.println(id2);
} }
}
} }

View File

@ -31,6 +31,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.hibernate.id.IdentifierGenerator; import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.UUIDGenerator;
import org.hibernate.id.UUIDHexGenerator; import org.hibernate.id.UUIDHexGenerator;
import org.hibernate.id.TableHiLoGenerator; import org.hibernate.id.TableHiLoGenerator;
import org.hibernate.id.Assigned; import org.hibernate.id.Assigned;
@ -65,7 +66,10 @@ public class DefaultIdentifierGeneratorFactory implements IdentifierGeneratorFac
* Constructs a new DefaultIdentifierGeneratorFactory. * Constructs a new DefaultIdentifierGeneratorFactory.
*/ */
public DefaultIdentifierGeneratorFactory() { public DefaultIdentifierGeneratorFactory() {
register( "uuid", UUIDHexGenerator.class ); register( "uuid2", UUIDGenerator.class );
register( "guid", GUIDGenerator.class ); // can be done with UUIDGenerator + strategy
register( "uuid", UUIDHexGenerator.class ); // "deprecated" for new use
register( "uuid.hex", UUIDHexGenerator.class ); // uuid.hex is deprecated
register( "hilo", TableHiLoGenerator.class ); register( "hilo", TableHiLoGenerator.class );
register( "assigned", Assigned.class ); register( "assigned", Assigned.class );
register( "identity", IdentityGenerator.class ); register( "identity", IdentityGenerator.class );
@ -74,8 +78,6 @@ public class DefaultIdentifierGeneratorFactory implements IdentifierGeneratorFac
register( "seqhilo", SequenceHiLoGenerator.class ); register( "seqhilo", SequenceHiLoGenerator.class );
register( "increment", IncrementGenerator.class ); register( "increment", IncrementGenerator.class );
register( "foreign", ForeignGenerator.class ); register( "foreign", ForeignGenerator.class );
register( "guid", GUIDGenerator.class );
register( "uuid.hex", UUIDHexGenerator.class ); // uuid.hex is deprecated
register( "sequence-identity", SequenceIdentityGenerator.class ); register( "sequence-identity", SequenceIdentityGenerator.class );
register( "enhanced-sequence", SequenceStyleGenerator.class ); register( "enhanced-sequence", SequenceStyleGenerator.class );
register( "enhanced-table", TableGenerator.class ); register( "enhanced-table", TableGenerator.class );

View File

@ -0,0 +1,125 @@
/*
* 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.uuid;
import java.util.UUID;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.id.UUIDGenerationStrategy;
import org.hibernate.util.BytesHelper;
/**
* Applies a version 1 (time-based) generation strategy (using ip address rather than mac address) but applies them in a
* different layout. The strategy is very similar to the legacy {@link org.hibernate.id.UUIDHexGenerator} id generator
* but uses a RFC 4122 compliant layout (variant 2).
* <p/>
* NOTE : Can be a bottle neck due to the need to synchronize in order to increment an
* internal count as part of the algorithm.
*
* @author Steve Ebersole
*/
public class CustomVersionOneStrategy implements UUIDGenerationStrategy {
public int getGeneratedVersion() {
return 1;
}
private final long mostSignificantBits;
public CustomVersionOneStrategy() {
// generate the "most significant bits" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
byte[] hiBits = new byte[8];
// use address as first 32 bits (8 * 4 bytes)
System.arraycopy( Helper.getAddressBytes(), 0, hiBits, 0, 4 );
// use the "jvm identifier" as the next 32 bits
System.arraycopy( Helper.getJvmIdentifierBytes(), 0, hiBits, 4, 4 );
// set the version (rfc term) appropriately
hiBits[6] &= 0x0f;
hiBits[6] |= 0x10;
mostSignificantBits = BytesHelper.asLong( hiBits );
}
public UUID generateUUID(SessionImplementor session) {
long leastSignificantBits = generateLeastSignificantBits( System.currentTimeMillis() );
return new UUID( mostSignificantBits, leastSignificantBits );
}
public long getMostSignificantBits() {
return mostSignificantBits;
}
public static long generateLeastSignificantBits(long seed) {
byte[] loBits = new byte[8];
short hiTime = (short) ( seed >>> 32 );
int loTime = (int) seed;
System.arraycopy( BytesHelper.fromShort( hiTime ), 0, loBits, 0, 2 );
System.arraycopy( BytesHelper.fromInt( loTime ), 0, loBits, 2, 4 );
System.arraycopy( Helper.getCountBytes(), 0, loBits, 6, 2 );
loBits[0] &= 0x3f;
loBits[0] |= ((byte)2 << (byte)6);
return BytesHelper.asLong( loBits );
}
public static void main(String[] args) {
CustomVersionOneStrategy strategy = new CustomVersionOneStrategy();
for ( int i = 0; i < 1000; i++ ) {
System.out.println( "Generation # " + i + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" );
byte[] loBits = new byte[8];
long sysTime = System.currentTimeMillis();
short hiTime = (short) ( System.currentTimeMillis() >>> 32 );
int loTime = (int) sysTime;
System.arraycopy( BytesHelper.fromShort( hiTime ), 0, loBits, 0, 2 );
System.arraycopy( BytesHelper.fromInt( loTime ), 0, loBits, 2, 4 );
System.arraycopy( Helper.getCountBytes(), 0, loBits, 6, 2 );
System.out.println( " before bit setting ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" );
System.out.println( " loBits[0] : " + BytesHelper.toBinaryString( loBits[0] ) );
System.out.println( " lsb : " + BytesHelper.toBinaryString( BytesHelper.asLong( loBits ) ) );
System.out.println( " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" );
loBits[0] &= 0x3f;
loBits[0] |= ((byte)2 << (byte)6);
System.out.println( " after bit setting ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" );
System.out.println( " loBits[0] : " + BytesHelper.toBinaryString( loBits[0] ) );
long leastSignificantBits = BytesHelper.asLong( loBits );
System.out.println( " lsb : " + BytesHelper.toBinaryString( leastSignificantBits ) );
System.out.println( " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" );
UUID uuid = new UUID( strategy.mostSignificantBits, leastSignificantBits );
System.out.println( " uuid : " + uuid.toString() );
System.out.println( " variant : " + uuid.variant() );
System.out.println( " version : " + uuid.version() );
if ( uuid.variant() != 2 ) {
throw new RuntimeException( "bad variant" );
}
System.out.println( "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" );
}
}
}

View File

@ -0,0 +1,147 @@
/*
* 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.uuid;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.hibernate.util.BytesHelper;
/**
* TODO : javadoc
*
* @author Steve Ebersole
*/
public class Helper {
// IP ADDRESS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private static final byte[] ADDRESS_BYTES;
private static final int ADDRESS_INT;
private static final String ADDRESS_HEX_STRING;
static {
byte[] address;
try {
address = InetAddress.getLocalHost().getAddress();
}
catch ( Exception e ) {
address = new byte[4];
}
ADDRESS_BYTES = address;
ADDRESS_INT = BytesHelper.toInt( ADDRESS_BYTES );
ADDRESS_HEX_STRING = format( ADDRESS_INT );
}
public static byte[] getAddressBytes() {
return ADDRESS_BYTES;
}
public static int getAddressInt() {
return ADDRESS_INT;
}
public static String getAddressHexString() {
return ADDRESS_HEX_STRING;
}
// JVM identifier ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private static final byte[] JVM_IDENTIFIER_BYTES;
private static final int JVM_IDENTIFIER_INT;
private static final String JVM_IDENTIFIER_HEX_STRING;
static {
JVM_IDENTIFIER_INT = (int) ( System.currentTimeMillis() >>> 8 );
JVM_IDENTIFIER_BYTES = BytesHelper.fromInt( JVM_IDENTIFIER_INT );
JVM_IDENTIFIER_HEX_STRING = format( JVM_IDENTIFIER_INT );
}
public static byte[] getJvmIdentifierBytes() {
return JVM_IDENTIFIER_BYTES;
}
public static int getJvmIdentifierInt() {
return JVM_IDENTIFIER_INT;
}
public static String getJvmIdentifierHexString() {
return JVM_IDENTIFIER_HEX_STRING;
}
// counter ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private static short counter = (short) 0;
/**
* Unique in a millisecond for this JVM instance (unless there are > Short.MAX_VALUE instances created in a
* millisecond)
*/
public static short getCountShort() {
synchronized ( Helper.class ) {
if ( counter < 0 ) {
counter = 0;
}
return counter++;
}
}
public static byte[] getCountBytes() {
return BytesHelper.fromShort( getCountShort() );
}
// Helper methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public static String format(int value) {
final String formatted = Integer.toHexString( value );
StringBuffer buf = new StringBuffer( "00000000".intern() );
buf.replace( 8 - formatted.length(), 8, formatted );
return buf.toString();
}
public static String format(short value) {
String formatted = Integer.toHexString( value );
StringBuffer buf = new StringBuffer( "0000" );
buf.replace( 4 - formatted.length(), 4, formatted );
return buf.toString();
}
public static void main(String[] args) throws UnknownHostException {
byte[] addressBytes = InetAddress.getLocalHost().getAddress();
System.out.println( "Raw ip address bytes : " + addressBytes.toString() );
int addressInt = BytesHelper.toInt( addressBytes );
System.out.println( "ip address int : " + addressInt );
String formatted = Integer.toHexString( addressInt );
StringBuffer buf = new StringBuffer( "00000000" );
buf.replace( 8 - formatted.length(), 8, formatted );
String addressHex = buf.toString();
System.out.println( "ip address hex : " + addressHex );
}
}

View File

@ -0,0 +1,53 @@
/*
* 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.uuid;
import java.util.UUID;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.id.UUIDGenerationStrategy;
/**
* Implements a "random" UUID generation strategy as defined by the {@link UUID#randomUUID()} method.
*
* @author Steve Ebersole
*/
public class StandardRandomStrategy implements UUIDGenerationStrategy {
public static final StandardRandomStrategy INSTANCE = new StandardRandomStrategy();
/**
* A variant 4 (random) strategy
*/
public int getGeneratedVersion() {
// a "random" strategy
return 4;
}
/**
* Delegates to {@link UUID#randomUUID()}
*/
public UUID generateUUID(SessionImplementor session) {
return UUID.randomUUID();
}
}

View File

@ -73,6 +73,8 @@ public class BasicTypeRegistry implements Serializable {
register( CurrencyType.INSTANCE ); register( CurrencyType.INSTANCE );
register( TimeZoneType.INSTANCE ); register( TimeZoneType.INSTANCE );
register( ClassType.INSTANCE ); register( ClassType.INSTANCE );
register( UUIDBinaryType.INSTANCE );
register( UUIDCharType.INSTANCE );
register( BinaryType.INSTANCE ); register( BinaryType.INSTANCE );
register( WrapperBinaryType.INSTANCE ); register( WrapperBinaryType.INSTANCE );

View File

@ -0,0 +1,51 @@
/*
* 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.type;
import java.util.UUID;
import org.hibernate.type.descriptor.java.UUIDTypeDescriptor;
import org.hibernate.type.descriptor.sql.BinaryTypeDescriptor;
/**
* A type mapping {@link java.sql.Types#BINARY} and {@link UUID}
*
* @author Steve Ebersole
*/
public class UUIDBinaryType extends AbstractSingleColumnStandardBasicType<UUID> {
public static final UUIDBinaryType INSTANCE = new UUIDBinaryType();
public UUIDBinaryType() {
super( BinaryTypeDescriptor.INSTANCE, UUIDTypeDescriptor.INSTANCE );
}
public String getName() {
return "uuid-binary";
}
@Override
protected boolean registerUnderJavaType() {
return true;
}
}

View File

@ -0,0 +1,51 @@
/*
* 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.type;
import java.util.UUID;
import org.hibernate.dialect.Dialect;
import org.hibernate.type.descriptor.java.UUIDTypeDescriptor;
import org.hibernate.type.descriptor.sql.CharTypeDescriptor;
/**
* A type mapping {@link java.sql.Types#CHAR} (or {@link java.sql.Types#VARCHAR}) and {@link java.util.UUID}
*
* @author Steve Ebersole
*/
public class UUIDCharType extends AbstractSingleColumnStandardBasicType<UUID> implements LiteralType<UUID> {
public static final UUIDCharType INSTANCE = new UUIDCharType();
public UUIDCharType() {
super( CharTypeDescriptor.INSTANCE, UUIDTypeDescriptor.INSTANCE );
}
public String getName() {
return "uuid-char";
}
public String objectToSQLString(UUID value, Dialect dialect) throws Exception {
return StringType.INSTANCE.objectToSQLString( value.toString(), dialect );
}
}

View File

@ -29,7 +29,7 @@ import java.util.TimeZone;
import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.WrapperOptions;
/** /**
* TODO : javadoc * Descriptor for {@link TimeZone} handling.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@ -79,6 +79,6 @@ public class TimeZoneTypeDescriptor extends AbstractTypeDescriptor<TimeZone> {
if ( String.class.isInstance( value ) ) { if ( String.class.isInstance( value ) ) {
return fromString( (String) value ); return fromString( (String) value );
} }
throw unknownUnwrap( value.getClass() ); throw unknownWrap( value.getClass() );
} }
} }

View File

@ -0,0 +1,132 @@
/*
* 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.type.descriptor.java;
import java.io.Serializable;
import java.util.UUID;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.util.BytesHelper;
/**
* Descriptor for {@link UUID} handling.
*
* @author Steve Ebersole
*/
public class UUIDTypeDescriptor extends AbstractTypeDescriptor<UUID> {
public static final UUIDTypeDescriptor INSTANCE = new UUIDTypeDescriptor();
public UUIDTypeDescriptor() {
super( UUID.class );
}
public String toString(UUID value) {
return ToStringTransformer.INSTANCE.transform( value );
}
public UUID fromString(String string) {
return ToStringTransformer.INSTANCE.parse( string );
}
@SuppressWarnings({ "unchecked" })
public <X> X unwrap(UUID value, Class<X> type, WrapperOptions options) {
if ( value == null ) {
return null;
}
if ( UUID.class.isAssignableFrom( type ) ) {
return (X) PassThroughTransformer.INSTANCE.transform( value );
}
if ( String.class.isAssignableFrom( type ) ) {
return (X) ToStringTransformer.INSTANCE.transform( value );
}
if ( byte[].class.isAssignableFrom( type ) ) {
return (X) ToBytesTransformer.INSTANCE.transform( value );
}
throw unknownUnwrap( type );
}
public <X> UUID wrap(X value, WrapperOptions options) {
if ( value == null ) {
return null;
}
if ( UUID.class.isInstance( value ) ) {
return PassThroughTransformer.INSTANCE.parse( value );
}
if ( String.class.isInstance( value ) ) {
return ToStringTransformer.INSTANCE.parse( value );
}
if ( byte[].class.isInstance( value ) ) {
return ToBytesTransformer.INSTANCE.parse( value );
}
throw unknownWrap( value.getClass() );
}
public static interface ValueTransformer {
public Serializable transform(UUID uuid);
public UUID parse(Object value);
}
public static class PassThroughTransformer implements ValueTransformer {
public static final PassThroughTransformer INSTANCE = new PassThroughTransformer();
public UUID transform(UUID uuid) {
return uuid;
}
public UUID parse(Object value) {
return (UUID)value;
}
}
public static class ToStringTransformer implements ValueTransformer {
public static final ToStringTransformer INSTANCE = new ToStringTransformer();
public String transform(UUID uuid) {
return uuid.toString();
}
public UUID parse(Object value) {
return UUID.fromString( (String) value );
}
}
public static class ToBytesTransformer implements ValueTransformer {
public static final ToBytesTransformer INSTANCE = new ToBytesTransformer();
public byte[] transform(UUID uuid) {
byte[] bytes = new byte[16];
System.arraycopy( BytesHelper.fromLong( uuid.getMostSignificantBits() ), 0, bytes, 0, 8 );
System.arraycopy( BytesHelper.fromLong( uuid.getLeastSignificantBits() ), 0, bytes, 8, 8 );
return bytes;
}
public UUID parse(Object value) {
byte[] msb = new byte[8];
byte[] lsb = new byte[8];
System.arraycopy( value, 0, msb, 0, 8 );
System.arraycopy( value, 8, lsb, 0, 8 );
return new UUID( BytesHelper.asLong( msb ), BytesHelper.asLong( lsb ) );
}
}
}

View File

@ -0,0 +1,77 @@
/*
* 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.type.descriptor.java;
import java.net.MalformedURLException;
import java.net.URL;
import org.hibernate.HibernateException;
import org.hibernate.type.descriptor.WrapperOptions;
/**
* Descriptor for {@link URL} handling.
*
* @author Steve Ebersole
*/
public class UrlTypeDescriptor extends AbstractTypeDescriptor<URL> {
public static final UrlTypeDescriptor INSTANCE = new UrlTypeDescriptor();
public UrlTypeDescriptor() {
super( URL.class );
}
public String toString(URL value) {
return value.toExternalForm();
}
public URL fromString(String string) {
try {
return new URL( string );
}
catch ( MalformedURLException e ) {
throw new HibernateException( "Unable to convert string [" + string + "] to URL : " + e );
}
}
@SuppressWarnings({ "unchecked" })
public <X> X unwrap(URL value, Class<X> type, WrapperOptions options) {
if ( value == null ) {
return null;
}
if ( String.class.isAssignableFrom( type ) ) {
return (X) toString( value );
}
throw unknownUnwrap( type );
}
public <X> URL wrap(X value, WrapperOptions options) {
if ( value == null ) {
return null;
}
if ( String.class.isInstance( value ) ) {
return fromString( (String) value );
}
throw unknownWrap( value.getClass() );
}
}

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * Hibernate, Relational Persistence for Idiomatic Java
* *
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC. * distributed under license by Red Hat Inc.
* *
* This copyrighted material is made available to anyone wishing to use, modify, * This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,26 +20,123 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.util; package org.hibernate.util;
public final class BytesHelper { public final class BytesHelper {
private BytesHelper() {} private BytesHelper() {
}
public static int toInt( byte[] bytes ) { /**
* Custom algorithm used to generate an int from a series of bytes.
* <p/>
* NOTE : this is different than interpreting the incoming bytes as an int value!
*
* @param bytes The bytes to use in generating the int.
*
* @return The generated int.
*/
public static int toInt(byte[] bytes) {
int result = 0; int result = 0;
for (int i=0; i<4; i++) { for ( int i = 0; i < 4; i++ ) {
result = ( result << 8 ) - Byte.MIN_VALUE + (int) bytes[i]; result = ( result << 8 ) - Byte.MIN_VALUE + (int) bytes[i];
} }
return result; return result;
} }
/**
* Interpret a short as its binary form
*
* @param shortValue The short to interpret to binary
*
* @return The binary
*/
public static byte[] fromShort(int shortValue) {
byte[] bytes = new byte[2];
bytes[0] = (byte) ( shortValue >> 8 );
bytes[1] = (byte) ( ( shortValue << 8 ) >> 8 );
return bytes;
}
/**
* Interpret an int as its binary form
*
* @param intValue The int to interpret to binary
*
* @return The binary
*/
public static byte[] fromInt(int intValue) {
byte[] bytes = new byte[4];
bytes[0] = (byte) ( intValue >> 24 );
bytes[1] = (byte) ( ( intValue << 8 ) >> 24 );
bytes[2] = (byte) ( ( intValue << 16 ) >> 24 );
bytes[3] = (byte) ( ( intValue << 24 ) >> 24 );
return bytes;
}
/**
* Interpret a long as its binary form
*
* @param longValue The long to interpret to binary
*
* @return The binary
*/
public static byte[] fromLong(long longValue) {
byte[] bytes = new byte[8];
bytes[0] = (byte) ( longValue >> 56 );
bytes[1] = (byte) ( ( longValue << 8 ) >> 56 );
bytes[2] = (byte) ( ( longValue << 16 ) >> 56 );
bytes[3] = (byte) ( ( longValue << 24 ) >> 56 );
bytes[4] = (byte) ( ( longValue << 32 ) >> 56 );
bytes[5] = (byte) ( ( longValue << 40 ) >> 56 );
bytes[6] = (byte) ( ( longValue << 48 ) >> 56 );
bytes[7] = (byte) ( ( longValue << 56 ) >> 56 );
return bytes;
}
/**
* Interpret the binary representation of a long.
*
* @param bytes The bytes to interpret.
*
* @return The long
*/
public static long asLong(byte[] bytes) {
if ( bytes == null ) {
return 0;
}
if ( bytes.length != 8 ) {
throw new IllegalArgumentException( "Expecting 8 byte values to construct a long" );
}
long value = 0;
for (int i=0; i<8; i++) {
value = (value << 8) | (bytes[i] & 0xff);
}
return value;
}
public static String toBinaryString(byte value) {
String formatted = Integer.toBinaryString( value );
if ( formatted.length() > 8 ) {
formatted = formatted.substring( formatted.length() - 8 );
}
StringBuffer buf = new StringBuffer( "00000000" );
buf.replace( 8 - formatted.length(), 8, formatted );
return buf.toString();
}
public static String toBinaryString(int value) {
String formatted = Long.toBinaryString( value );
StringBuffer buf = new StringBuffer( StringHelper.repeat( '0', 32 ) );
buf.replace( 64 - formatted.length(), 64, formatted );
return buf.toString();
}
public static String toBinaryString(long value) {
String formatted = Long.toBinaryString( value );
StringBuffer buf = new StringBuffer( StringHelper.repeat( '0', 64 ) );
buf.replace( 64 - formatted.length(), 64, formatted );
return buf.toString();
}
} }

View File

@ -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.id.uuid;
import java.util.UUID;
import junit.framework.TestCase;
/**
* TODO : javadoc
*
* @author Steve Ebersole
*/
public class CustomVersionOneStrategyTest extends TestCase {
public static void main(String[] args) {
System.out.println( System.currentTimeMillis() );
System.out.println( Long.MAX_VALUE );
}
public void testUniqueCounter() {
CustomVersionOneStrategy strategy = new CustomVersionOneStrategy();
long now = System.currentTimeMillis();
UUID uuid1 = new UUID(
strategy.getMostSignificantBits(),
CustomVersionOneStrategy.generateLeastSignificantBits( now )
);
assertEquals( 2, uuid1.variant() );
assertEquals( 1, uuid1.version() );
for ( int i = 0; i < 100; i++ ) {
UUID uuidX = new UUID(
strategy.getMostSignificantBits(),
CustomVersionOneStrategy.generateLeastSignificantBits( now )
);
assertEquals( 2, uuidX.variant() );
assertEquals( 1, uuidX.version() );
assertFalse( uuid1.equals( uuidX ) );
assertEquals( uuid1.getMostSignificantBits(), uuidX.getMostSignificantBits() );
}
}
public void testRangeOfValues() {
CustomVersionOneStrategy strategy = new CustomVersionOneStrategy();
UUID uuid = new UUID(
strategy.getMostSignificantBits(),
CustomVersionOneStrategy.generateLeastSignificantBits( 0 )
);
assertEquals( 2, uuid.variant() );
assertEquals( 1, uuid.version() );
uuid = new UUID(
strategy.getMostSignificantBits(),
CustomVersionOneStrategy.generateLeastSignificantBits( Long.MAX_VALUE )
);
assertEquals( 2, uuid.variant() );
assertEquals( 1, uuid.version() );
}
}

View File

@ -0,0 +1,86 @@
/*
* 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.type;
import java.net.URL;
import java.util.UUID;
import junit.framework.TestCase;
import org.hibernate.type.descriptor.java.UrlTypeDescriptor;
import org.hibernate.type.descriptor.sql.VarcharTypeDescriptor;
/**
* TODO : javadoc
*
* @author Steve Ebersole
*/
public class BasicTypeRegistryTest extends TestCase {
private final BasicTypeRegistry registry = new BasicTypeRegistry();
public void testOverriding() {
BasicType type = registry.getRegisteredType( "uuid-binary" );
assertSame( UUIDBinaryType.INSTANCE, type );
type = registry.getRegisteredType( UUID.class.getName() );
assertSame( UUIDBinaryType.INSTANCE, type );
BasicType override = new UUIDCharType() {
@Override
protected boolean registerUnderJavaType() {
return true;
}
};
registry.register( override );
type = registry.getRegisteredType( UUID.class.getName() );
assertNotSame( UUIDBinaryType.INSTANCE, type );
assertSame( override, type );
}
public void testExpanding() {
BasicType type = registry.getRegisteredType( URL.class.getName() );
assertNull( type );
registry.register( UrlType.INSTANCE );
type = registry.getRegisteredType( URL.class.getName() );
assertNotNull( type );
assertSame( UrlType.INSTANCE, type );
}
public static class UrlType extends AbstractSingleColumnStandardBasicType<URL> {
public static final UrlType INSTANCE = new UrlType();
public UrlType() {
super( VarcharTypeDescriptor.INSTANCE, UrlTypeDescriptor.INSTANCE );
}
public String getName() {
return "url";
}
@Override
protected boolean registerUnderJavaType() {
return true;
}
}
}

View File

@ -583,8 +583,37 @@
</varlistentry> </varlistentry>
</variablelist> </variablelist>
</section> </section>
<section id="types.basic.value.uuid">
<title><classname>java.util.UUID</classname></title>
<variablelist>
<varlistentry>
<term><classname>org.hibernate.type.UUIDBinaryType</classname></term>
<listitem>
<para>
Maps a java.util.UUID to a JDBC BINARY
</para>
<para>
Registered under <literal>uuid-binary</literal> and <literal>java.util.UUID</literal>
in the type registry (see <xref linkend="types.registry"/>).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><classname>org.hibernate.type.UUIDCharType</classname></term>
<listitem>
<para>
Maps a java.util.UUID to a JDBC CHAR (though VARCHAR is fine too for existing schemas)
</para>
<para>
Registered under <literal>uuid-char</literal> in the type registry (see
<xref linkend="types.registry"/>).
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section id="types.basic.value.serializable"> <section id="types.basic.value.serializable">
<title>java.io.Serializable</title> <title><classname>java.io.Serializable</classname></title>
<variablelist> <variablelist>
<varlistentry> <varlistentry>
<term><classname>org.hibernate.type.SerializableType</classname></term> <term><classname>org.hibernate.type.SerializableType</classname></term>

View File

@ -0,0 +1,40 @@
<?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">
<hibernate-mapping package="org.hibernate.test.id.uuid.sqlrep">
<class name="Node">
<id name="id">
<generator class="uuid2"/>
</id>
<property name="name"/>
<many-to-one name="parent"/>
</class>
</hibernate-mapping>

View File

@ -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.id.uuid.sqlrep;
import java.util.UUID;
/**
* TODO : javadoc
*
* @author Steve Ebersole
*/
public class Node {
private UUID id;
private String name;
private Node parent;
public Node() {
}
public Node(String name) {
this.name = name;
}
public Node(String name, Node parent) {
this.name = name;
this.parent = parent;
}
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Node getParent() {
return parent;
}
public void setParent(Node parent) {
this.parent = parent;
}
}

View File

@ -0,0 +1,81 @@
/*
* 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.id.uuid.sqlrep.sqlbinary;
import org.hibernate.Session;
import org.hibernate.junit.functional.FunctionalTestCase;
import org.hibernate.test.id.uuid.sqlrep.Node;
/**
* TODO : javadoc
*
* @author Steve Ebersole
*/
public class UUIDBinaryTest extends FunctionalTestCase {
public UUIDBinaryTest(String string) {
super( string );
}
public String[] getMappings() {
return new String[] { "id/uuid/sqlrep/Node.hbm.xml" };
}
public void testUsage() {
Session session = openSession();
session.beginTransaction();
Node root = new Node( "root" );
session.save( root );
assertNotNull( root.getId() );
Node child = new Node( "child", root );
session.save( child );
assertNotNull( child.getId() );
session.getTransaction().commit();
session.close();
session = openSession();
session.beginTransaction();
Node node = (Node) session.get( Node.class, root.getId() );
assertNotNull( node );
node = (Node) session.get( Node.class, child.getId() );
assertNotNull( node );
session.getTransaction().commit();
session.close();
session = openSession();
session.beginTransaction();
// test joining
node = (Node) session.createQuery( "from Node n join fetch n.parent where n.parent is not null" ).uniqueResult();
assertNotNull( node );
assertNotNull( node.getParent() );
session.getTransaction().commit();
session.close();
session = openSession();
session.beginTransaction();
session.delete( child );
session.delete( root );
session.getTransaction().commit();
session.close();
}
}

View File

@ -0,0 +1,51 @@
/*
* 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.id.uuid.sqlrep.sqlchar;
import org.hibernate.cfg.Configuration;
import org.hibernate.test.id.uuid.sqlrep.sqlbinary.UUIDBinaryTest;
import org.hibernate.type.UUIDCharType;
/**
* TODO : javadoc
*
* @author Steve Ebersole
*/
public class UUIDCharTest extends UUIDBinaryTest {
public UUIDCharTest(String string) {
super( string );
}
@Override
public void configure(Configuration cfg) {
cfg.registerTypeOverride(
new UUIDCharType() {
@Override
protected boolean registerUnderJavaType() {
return true;
}
}
);
}
}

View File

@ -0,0 +1,60 @@
/*
* 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.id.uuid.strategy;
import org.hibernate.Session;
import org.hibernate.junit.functional.FunctionalTestCase;
/**
* TODO : javadoc
*
* @author Steve Ebersole
*/
public class CustomStrategyTest extends FunctionalTestCase {
public CustomStrategyTest(String string) {
super( string );
}
public String[] getMappings() {
return new String[] { "id/uuid/strategy/Node.hbm.xml" };
}
public void testUsage() {
Session session = openSession();
session.beginTransaction();
Node node = new Node();
session.save( node );
assertNotNull( node.getId() );
assertEquals( 2, node.getId().variant() );
assertEquals( 1, node.getId().version() );
session.getTransaction().commit();
session.close();
session = openSession();
session.beginTransaction();
session.delete( node );
session.getTransaction().commit();
session.close();
}
}

View File

@ -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">
<hibernate-mapping package="org.hibernate.test.id.uuid.strategy">
<class name="Node">
<id name="id">
<generator class="uuid2">
<!-- the "standard random" strategy gets tested in the other id.uuid tests -->
<param name="uuid_gen_strategy_class">org.hibernate.id.uuid.CustomVersionOneStrategy</param>
</generator>
</id>
<property name="name"/>
</class>
</hibernate-mapping>

View File

@ -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.id.uuid.strategy;
import java.util.UUID;
/**
* TODO : javadoc
*
* @author Steve Ebersole
*/
public class Node {
private UUID id;
private String name;
public Node() {
}
public Node(String name) {
this.name = name;
}
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}