From fb78813259657a71df227168478c9c0b9e5488ae Mon Sep 17 00:00:00 2001 From: Michael Dick Date: Tue, 24 Jun 2008 19:48:23 +0000 Subject: [PATCH] OPENJPA-545 committing patch provided by Jeremy Bauer git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@671319 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/openjpa/kernel/BrokerImpl.java | 4 + .../org/apache/openjpa/kernel/UUIDHexSeq.java | 2 +- .../apache/openjpa/kernel/UUIDStringSeq.java | 2 +- .../openjpa/kernel/UUIDType4HexSeq.java | 66 ++++++++++++++ .../openjpa/kernel/UUIDType4StringSeq.java | 66 ++++++++++++++ .../apache/openjpa/meta/ValueStrategies.java | 12 +++ .../org/apache/openjpa/util/ImplHelper.java | 8 +- .../openjpa/lib/util/UUIDGenerator.java | 87 +++++++++++++++---- .../openjpa/lib/util/TestUUIDGenerator.java | 30 ++++++- .../generationtype/GeneratedValues.java | 51 ++++++++++- .../generationtype/TestGeneratedValues.java | 84 +++++++++++++++++- .../jdbc/annotations/ExtensionsEntity.java | 12 +++ .../annotations/TestExtensionAnnotations.java | 6 ++ .../AnnotationPersistenceMetaDataParser.java | 4 + .../apache/openjpa/persistence/Generator.java | 2 + .../src/doc/manual/jpa_overview_meta.xml | 51 +++++++++-- 16 files changed, 455 insertions(+), 32 deletions(-) create mode 100644 openjpa-kernel/src/main/java/org/apache/openjpa/kernel/UUIDType4HexSeq.java create mode 100644 openjpa-kernel/src/main/java/org/apache/openjpa/kernel/UUIDType4StringSeq.java diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java index 96d3596e9..8526cac12 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java @@ -3545,6 +3545,10 @@ public class BrokerImpl return UUIDHexSeq.getInstance(); case ValueStrategies.UUID_STRING: return UUIDStringSeq.getInstance(); + case ValueStrategies.UUID_TYPE4_HEX: + return UUIDType4HexSeq.getInstance(); + case ValueStrategies.UUID_TYPE4_STRING: + return UUIDType4StringSeq.getInstance(); case ValueStrategies.SEQUENCE: SequenceMetaData smd = (fmd == null) ? meta.getIdentitySequenceMetaData() diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/UUIDHexSeq.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/UUIDHexSeq.java index 332586c95..3051e4b20 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/UUIDHexSeq.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/UUIDHexSeq.java @@ -50,7 +50,7 @@ public class UUIDHexSeq } public synchronized Object next(StoreContext ctx, ClassMetaData meta) { - _last = UUIDGenerator.nextHex(); + _last = UUIDGenerator.nextHex(UUIDGenerator.TYPE1); return _last; } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/UUIDStringSeq.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/UUIDStringSeq.java index f1e855426..69dcbaf7f 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/UUIDStringSeq.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/UUIDStringSeq.java @@ -50,7 +50,7 @@ public class UUIDStringSeq } public synchronized Object next(StoreContext ctx, ClassMetaData meta) { - _last = UUIDGenerator.nextString(); + _last = UUIDGenerator.nextString(UUIDGenerator.TYPE1); return _last; } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/UUIDType4HexSeq.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/UUIDType4HexSeq.java new file mode 100644 index 000000000..60b68a6d9 --- /dev/null +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/UUIDType4HexSeq.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openjpa.kernel; + +import org.apache.openjpa.lib.util.UUIDGenerator; +import org.apache.openjpa.meta.ClassMetaData; + +/** + * Sequence for generating 32-character hex Type 4 UUID strings. + * + * @author Jeremy Bauer + */ +public class UUIDType4HexSeq + implements Seq { + + private static final UUIDType4HexSeq _instance = new UUIDType4HexSeq(); + + private String _last = null; + + /** + * Return the singleton instance. + */ + public static UUIDType4HexSeq getInstance() { + return _instance; + } + + /** + * Hide constructor. + */ + private UUIDType4HexSeq() { + } + + public void setType(int type) { + } + + public synchronized Object next(StoreContext ctx, ClassMetaData meta) { + _last = UUIDGenerator.nextHex(UUIDGenerator.TYPE4); + return _last; + } + + public synchronized Object current(StoreContext ctx, ClassMetaData meta) { + return _last; + } + + public void allocate(int additional, StoreContext ctx, ClassMetaData meta) { + } + + public void close() { + } +} \ No newline at end of file diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/UUIDType4StringSeq.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/UUIDType4StringSeq.java new file mode 100644 index 000000000..c03d0ea1d --- /dev/null +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/UUIDType4StringSeq.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openjpa.kernel; + +import org.apache.openjpa.lib.util.UUIDGenerator; +import org.apache.openjpa.meta.ClassMetaData; + +/** + * Sequence for generating 16-character UUID strings. + * + * @author Jeremy Bauer + */ +public class UUIDType4StringSeq + implements Seq { + + private static final UUIDType4StringSeq _instance = new UUIDType4StringSeq(); + + private String _last = null; + + /** + * Return the singleton instance. + */ + public static UUIDType4StringSeq getInstance() { + return _instance; + } + + /** + * Hide constructor. + */ + private UUIDType4StringSeq() { + } + + public void setType(int type) { + } + + public synchronized Object next(StoreContext ctx, ClassMetaData meta) { + _last = UUIDGenerator.nextString(UUIDGenerator.TYPE4); + return _last; + } + + public synchronized Object current(StoreContext ctx, ClassMetaData meta) { + return _last; + } + + public void allocate(int additional, StoreContext ctx, ClassMetaData meta) { + } + + public void close() { + } +} \ No newline at end of file diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ValueStrategies.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ValueStrategies.java index 25d338326..8704a443a 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ValueStrategies.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ValueStrategies.java @@ -68,6 +68,16 @@ public class ValueStrategies { */ public static final int UUID_HEX = 6; + /** + * "uuid-type4-string" value strategy. + */ + public static final int UUID_TYPE4_STRING = 7; + + /** + * "uuid-type4-hex" value strategy. + */ + public static final int UUID_TYPE4_HEX = 8; + private static final Localizer _loc = Localizer.forPackage (ValueStrategies.class); @@ -82,6 +92,8 @@ public class ValueStrategies { _map.put("increment", Numbers.valueOf(INCREMENT)); _map.put("uuid-string", Numbers.valueOf(UUID_STRING)); _map.put("uuid-hex", Numbers.valueOf(UUID_HEX)); + _map.put("uuid-type4-string", Numbers.valueOf(UUID_TYPE4_STRING)); + _map.put("uuid-type4-hex", Numbers.valueOf(UUID_TYPE4_HEX)); } /** diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java b/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java index f25dfb4f0..7f6b2f25d 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java @@ -160,9 +160,13 @@ public class ImplHelper { return JavaTypes.convert(smd.getInstance(ctx.getClassLoader()). next(ctx, meta), typeCode); case ValueStrategies.UUID_STRING: - return UUIDGenerator.nextString(); + return UUIDGenerator.nextString(UUIDGenerator.TYPE1); case ValueStrategies.UUID_HEX: - return UUIDGenerator.nextHex(); + return UUIDGenerator.nextHex(UUIDGenerator.TYPE1); + case ValueStrategies.UUID_TYPE4_STRING: + return UUIDGenerator.nextString(UUIDGenerator.TYPE4); + case ValueStrategies.UUID_TYPE4_HEX: + return UUIDGenerator.nextHex(UUIDGenerator.TYPE4); default: return null; } diff --git a/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/UUIDGenerator.java b/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/UUIDGenerator.java index af7c203f1..b34191b5e 100644 --- a/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/UUIDGenerator.java +++ b/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/UUIDGenerator.java @@ -22,16 +22,18 @@ import java.io.IOException; import java.net.InetAddress; import java.security.SecureRandom; import java.util.Random; +import java.util.UUID; import org.apache.commons.lang.exception.NestableRuntimeException; /** - * UUID value generator. Based on the time-based generator in the Apache - * Commons Id project: http://jakarta.apache.org/commons/sandbox/id/uuid.html + * UUID value generator. Type 1 generator is based on the time-based generator + * in the Apache Commons Id project: http://jakarta.apache.org/commons/sandbox + * /id/uuid.html The type 4 generator uses the standard Java UUID generator. * - * The code has been vastly simplified and modified to replace the ethernet - * address of the host machine with the IP, since we do not want to require - * native libs and Java cannot access the MAC address directly. + * The type 1 code has been vastly simplified and modified to replace the + * ethernet address of the host machine with the IP, since we do not want to + * require native libs and Java cannot access the MAC address directly. * * In spirit, implements the IETF UUID draft specification, found here:
* http://www1.ics.uci.edu/~ejw/authoring/uuid-guid/draft-leach-uuids-guids-01 @@ -43,6 +45,10 @@ import org.apache.commons.lang.exception.NestableRuntimeException; */ public class UUIDGenerator { + // supported UUID types + public static final int TYPE1 = 1; + public static final int TYPE4 = 4; + // indexes within the uuid array for certain boundaries private static final byte IDX_TIME_HI = 6; private static final byte IDX_TYPE = 6; // multiplexed @@ -68,13 +74,12 @@ public class UUIDGenerator { private final static byte TYPE_TIME_BASED = 0x10; // random number generator used to reduce conflicts with other JVMs, and - // hasher for strings. note that secure random is very slow the first time - // it is used; consider switching to a standard random - private static final Random RANDOM = new SecureRandom(); + // hasher for strings. + private static Random RANDOM; // 4-byte IP address + 2 random bytes to compensate for the fact that // the MAC address is usually 6 bytes - private static final byte[] IP; + private static byte[] IP; // counter is initialized to 0 and is incremented for each uuid request // within the same timestamp window. @@ -88,12 +93,21 @@ public class UUIDGenerator { // when it overflows private static long _lastMillis = 0L; private static final int MAX_14BIT = 0x3FFF; - private static short _seq = (short) RANDOM.nextInt(MAX_14BIT); - + private static short _seq = 0; + /* - * Static initializer to get the IP address of the host machine. + * Initializer for type 1 UUIDs. Creates random generator and genenerates + * the node portion of the UUID using the IP address. */ - static { + private static synchronized void initializeForType1() + { + if (RANDOM != null) + return; + // note that secure random is very slow the first time + // it is used; consider switching to a standard random + RANDOM = new SecureRandom(); + _seq = (short) RANDOM.nextInt(MAX_14BIT); + byte[] ip = null; try { ip = InetAddress.getLocalHost().getAddress(); @@ -103,13 +117,25 @@ public class UUIDGenerator { IP = new byte[6]; RANDOM.nextBytes(IP); - System.arraycopy(ip, 0, IP, 2, ip.length); + System.arraycopy(ip, 0, IP, 2, ip.length); } /** * Return a unique UUID value. */ - public static byte[] next() { + public static byte[] next(int type) { + if (type == TYPE4) { + return createType4(); + } + return createType1(); + } + + /* + * Creates a type 1 UUID + */ + public static byte[] createType1() { + if (RANDOM == null) + initializeForType1(); // set ip addr byte[] uuid = new byte[16]; System.arraycopy(IP, 0, uuid, 10, IP.length); @@ -147,11 +173,32 @@ public class UUIDGenerator { return uuid; } + /* + * Creates a type 4 UUID + */ + private static byte[] createType4() { + UUID type4 = UUID.randomUUID(); + byte[] uuid = new byte[16]; + longToBytes(type4.getMostSignificantBits(), uuid, 0); + longToBytes(type4.getLeastSignificantBits(), uuid, 8); + return uuid; + } + + /* + * Converts a long to byte values, setting them in a byte array + * at a given starting position. + */ + private static void longToBytes(long longVal, byte[] buf, int sPos) { + sPos += 7; + for(int i = 0; i < 8; i++) + buf[sPos-i] = (byte)(longVal >>> (i * 8)); + } + /** * Return the next unique uuid value as a 16-character string. */ - public static String nextString() { - byte[] bytes = next(); + public static String nextString(int type) { + byte[] bytes = next(type); try { return new String(bytes, "ISO-8859-1"); } catch (Exception e) { @@ -162,8 +209,8 @@ public class UUIDGenerator { /** * Return the next unique uuid value as a 32-character hex string. */ - public static String nextHex() { - return Base16Encoder.encode(next()); + public static String nextHex(int type) { + return Base16Encoder.encode(next(type)); } /** @@ -174,6 +221,8 @@ public class UUIDGenerator { */ // package-visibility for testing static long getTime() { + if (RANDOM == null) + initializeForType1(); long newTime = getUUIDTime(); if (newTime <= _lastMillis) { incrementSequence(); diff --git a/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestUUIDGenerator.java b/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestUUIDGenerator.java index 7ae6a33c7..8e8777b59 100644 --- a/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestUUIDGenerator.java +++ b/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestUUIDGenerator.java @@ -33,13 +33,39 @@ public class TestUUIDGenerator extends TestCase { public void testUniqueString() { Set seen = new HashSet(); for (int i = 0; i < 10000; i++) - assertTrue(seen.add(UUIDGenerator.nextString())); + assertTrue(seen.add( + UUIDGenerator.nextString(UUIDGenerator.TYPE1))); } public void testUniqueHex() { Set seen = new HashSet(); for (int i = 0; i < 10000; i++) - assertTrue(seen.add(UUIDGenerator.nextHex())); + assertTrue(seen.add( + UUIDGenerator.nextHex(UUIDGenerator.TYPE1))); + } + + public void testUniqueType4String() { + Set seen = new HashSet(); + for (int i = 0; i < 10000; i++) + assertTrue(seen.add( + UUIDGenerator.nextString(UUIDGenerator.TYPE4))); + } + + public void testUniqueType4Hex() { + Set seen = new HashSet(); + for (int i = 0; i < 10000; i++) + assertTrue(seen.add( + UUIDGenerator.nextHex(UUIDGenerator.TYPE4))); + } + + public void testUniqueMixedTypesHex() { + Set seen = new HashSet(); + for (int i = 0; i < 10000; i++) { + int type = (i % 2 == 0) ? + UUIDGenerator.TYPE4 : UUIDGenerator.TYPE1; + assertTrue(seen.add( + UUIDGenerator.nextHex(type))); + } } public void testGetTime() { diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/GeneratedValues.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/GeneratedValues.java index e8c56da44..27cf5554f 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/GeneratedValues.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/GeneratedValues.java @@ -43,14 +43,31 @@ public class GeneratedValues { sequenceName="org.apache.openjpa.persistence.generationtype.CustomSeq()") private int customSeqWithIndirectionField; + @GeneratedValue(generator="uuid-hex") + private String uuidhex; + + @GeneratedValue(generator="uuid-string") + private String uuidstring; + + @GeneratedValue(generator="uuid-type4-hex") + private String uuidT4hex; + + @GeneratedValue(generator="uuid-type4-string") + private String uuidT4string; + public GeneratedValues() { super(); } - public GeneratedValues(int id, long field) { + public GeneratedValues(int id, long field, String uh, String us, + String ut4h, String ut4s) { super(); this.id = id; this.field = field; + this.uuidhex = uh; + this.uuidstring = us; + this.uuidT4hex = ut4h; + this.uuidT4string = ut4s; } public int getId() { @@ -76,4 +93,36 @@ public class GeneratedValues { public int getCustomSeqWithIndirectionField() { return customSeqWithIndirectionField; } + + public void setUuidhex(String uuidhex) { + this.uuidhex = uuidhex; + } + + public String getUuidhex() { + return uuidhex; + } + + public void setUuidstring(String uuidstring) { + this.uuidstring = uuidstring; + } + + public String getUuidstring() { + return uuidstring; + } + + public void setUuidT4hex(String uuidT4hex) { + this.uuidT4hex = uuidT4hex; + } + + public String getUuidT4hex() { + return uuidT4hex; + } + + public void setUuidT4string(String uuidT4string) { + this.uuidT4string = uuidT4string; + } + + public String getUuidT4string() { + return uuidT4string; + } } diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/TestGeneratedValues.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/TestGeneratedValues.java index 02239445f..7e90cb0e0 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/TestGeneratedValues.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/TestGeneratedValues.java @@ -46,12 +46,16 @@ public class TestGeneratedValues extends SingleEMFTestCase { assertFalse(gv.getId() == gv2.getId()); assertFalse(gv.getField() == gv2.getField()); + assertFalse(gv.getUuidstring().equals(gv2.getUuidstring())); + assertFalse(gv.getUuidhex().equals(gv2.getUuidhex())); + assertFalse(gv.getUuidT4hex().equals(gv2.getUuidT4hex())); + assertFalse(gv.getUuidT4string().equals(gv2.getUuidT4string())); } public void testInitialValues() { EntityManager em = emf.createEntityManager(); - GeneratedValues gv = new GeneratedValues(7, 9); + GeneratedValues gv = new GeneratedValues(7, 9, "a", "b", "c", "d"); try { em.getTransaction().begin(); @@ -133,4 +137,82 @@ public class TestGeneratedValues extends SingleEMFTestCase { assertNotEquals(0, gv.getCustomSeqWithIndirectionField()); } + + public void testUUIDGenerators() { + EntityManager em = emf.createEntityManager(); + + GeneratedValues gv = new GeneratedValues(); + em.getTransaction().begin(); + em.persist(gv); + em.getTransaction().commit(); + + int id = gv.getId(); + + assertTrue(isStringUUID(gv.getUuidT4string(), 4)); + assertTrue(isStringUUID(gv.getUuidstring(), 1)); + assertTrue(isHexUUID(gv.getUuidhex(), 1)); + assertTrue(isHexUUID(gv.getUuidT4hex(), 4)); + + em.clear(); + + GeneratedValues gv2 = em.find(GeneratedValues.class, id); + assertNotNull(gv2); + // The string value could contain null values and such so length + // calculations may be non-deterministic. For string generators, + // simply ensure the fields are populated (not null). + assertNotNull(gv2.getUuidstring()); + assertTrue(isHexUUID(gv2.getUuidhex(), 1)); + assertNotNull(gv2.getUuidT4string()); + assertTrue(isHexUUID(gv2.getUuidT4hex(), 4)); + + // Compare original hex values with new values. They should be equal. + // Note: UUID 'string' values are not compared. In most cases they will + // be the same, but in an environment where data is converted to + // a considerably different character encoding of the database (ex. + // Unicode -> EBCDIC) upon persistence, the uuid string returned by the + // database may not be equal to the original value. This is a common + // issue with string data, but even more likely for a uuids given that + // uuid strings are produced from pseudo-random byte arrays, which yield + // all sorts of variant characters. + assertTrue(gv.getId() == gv2.getId()); + assertTrue(gv.getField() == gv2.getField()); + assertTrue(gv.getUuidhex().equals(gv2.getUuidhex())); + assertTrue(gv.getUuidT4hex().equals(gv2.getUuidT4hex())); + } + + /* + * Verify a uuid string is 16 characters long and is the expected type. + */ + private boolean isStringUUID(String value, int type) { + if (value.length() != 16) + return false; + byte version = (byte)(value.charAt(6) >>> 4); + if (type != version) return false; + return true; + } + + /* + * Verify a uuid hex string value is 32 characters long, consists entirely + * of hex digits and is the correct version. + */ + private boolean isHexUUID(String value, int type) { + if (value.length() != 32) + return false; + char[] chArr = value.toCharArray(); + for (int i = 0; i < 32; i++) + { + char ch = chArr[i]; + if (!(Character.isDigit(ch) || + (ch >= 'a' && ch <= 'f') || + (ch >= 'A' && ch <= 'F'))) + return false; + if (i == 12) { + if (type == 1 && ch != '1') + return false; + if (type == 4 && ch != '4') + return false; + } + } + return true; + } } diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/ExtensionsEntity.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/ExtensionsEntity.java index d788dc3e0..d640e15c1 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/ExtensionsEntity.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/ExtensionsEntity.java @@ -41,6 +41,18 @@ public class ExtensionsEntity { @GeneratedValue(generator = "uuid-hex") @Column(name = "UUID_HEX") private String uuid; + + @GeneratedValue(generator = "uuid-string") + @Column(name = "UUID_STRING") + private String uuidString; + + @GeneratedValue(generator = "uuid-type4-hex") + @Column(name = "UUIDT4_HEX") + private String uuidT4Hex; + + @GeneratedValue(generator = "uuid-type4-string") + @Column(name = "UUIDT4_STRING") + private String uuidT4String; @Basic(fetch = FetchType.LAZY) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "system") diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/TestExtensionAnnotations.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/TestExtensionAnnotations.java index c8a54cb6a..e65be4faa 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/TestExtensionAnnotations.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/TestExtensionAnnotations.java @@ -72,6 +72,12 @@ public class TestExtensionAnnotations public void testValueStrategy() { assertEquals(ValueStrategies.UUID_HEX, _mapping.getField("uuid").getValueStrategy()); + assertEquals(ValueStrategies.UUID_STRING, + _mapping.getField("uuidString").getValueStrategy()); + assertEquals(ValueStrategies.UUID_TYPE4_HEX, + _mapping.getField("uuidT4Hex").getValueStrategy()); + assertEquals(ValueStrategies.UUID_TYPE4_STRING, + _mapping.getField("uuidT4String").getValueStrategy()); FieldMapping seq = _mapping.getFieldMapping("seq"); assertEquals(ValueStrategies.SEQUENCE, seq.getValueStrategy()); assertEquals("system", seq.getValueSequenceName()); diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java index f98f7ec43..b310a3c74 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java @@ -1220,6 +1220,10 @@ public class AnnotationPersistenceMetaDataParser return ValueStrategies.UUID_HEX; if (Generator.UUID_STRING.equals(generator)) return ValueStrategies.UUID_STRING; + if (Generator.UUID_TYPE4_HEX.equals(generator)) + return ValueStrategies.UUID_TYPE4_HEX; + if (Generator.UUID_TYPE4_STRING.equals(generator)) + return ValueStrategies.UUID_TYPE4_STRING; throw new MetaDataException(_loc.get("generator-bad-strategy", context, generator)); } diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/Generator.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/Generator.java index 40a501c18..7c073b57d 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/Generator.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/Generator.java @@ -29,6 +29,8 @@ public interface Generator { public static final String UUID_HEX = "uuid-hex"; public static final String UUID_STRING = "uuid-string"; + public static final String UUID_TYPE4_STRING = "uuid-type4-string"; + public static final String UUID_TYPE4_HEX = "uuid-type4-hex"; /** * The sequence name. diff --git a/openjpa-project/src/doc/manual/jpa_overview_meta.xml b/openjpa-project/src/doc/manual/jpa_overview_meta.xml index 5d90a6f89..6f365021d 100644 --- a/openjpa-project/src/doc/manual/jpa_overview_meta.xml +++ b/openjpa-project/src/doc/manual/jpa_overview_meta.xml @@ -830,7 +830,7 @@ on any field, not just identity fields. Before using the IDENTITY in the Reference Guide. -OpenJPA also offers two additional generator strategies for non-numeric fields, +OpenJPA also offers additional generator strategies for non-numeric fields, which you can access by setting strategy to AUTO (the default), and setting the generator string to: @@ -851,9 +851,9 @@ to: uuid-string -uuid-string: OpenJPA will generate a 128-bit UUID unique -within the network, represented as a 16-character string. For more information -on UUIDs, see the IETF UUID draft specification at: +uuid-string: OpenJPA will generate a 128-bit type 1 UUID +unique within the network, represented as a 16-character string. For more +information on UUIDs, see the IETF UUID draft specification at: http://www1.ics.uci.edu/~ejw/authoring/uuid-guid/ @@ -874,7 +874,48 @@ http://www1.ics.uci.edu/~ejw/authoring/uuid-guid/ uuid-hex: Same as uuid-string, but -represents the UUID as a 32-character hexadecimal string. +represents the type 1 UUID as a 32-character hexadecimal string. + + + + + + + mapping metadata + + + uuid-type4-string + + + + + uuid-type4-string + + +uuid-type4-string: OpenJPA will generate a 128-bit type 4 +pseudo-random UUID, represented as a 16-character string. For more +information on UUIDs, see the IETF UUID draft specification at: + +http://www1.ics.uci.edu/~ejw/authoring/uuid-guid/ + + + + + + + mapping metadata + + + uuid-type4-hex + + + + + uuid-type4-hex + + +uuid-type4-hex: Same as uuid-type4-string +, but represents the type 4 UUID as a 32-character hexadecimal string.