Skip to content

Commit 6f4cf5b

Browse files
authored
OPENJPA-2930 Implements UUID and GenerationType.UUID strategy (#124)
* [OPENJPA-2930] Implemented JPA 3.1 UUID support * added basic support for UUID as string or uuid field, per db support * added GenerationStrategy.UUID support using UUID-4 random * [OPENJPA-2930] Implements UUID support * Allows usage of UUID as a basic type * Allows usage of UUID as identity type * Allows GenerationType.AUTO and GenerationType.UUID usage on String and UUID fields * Generates type 4 UUID for @GeneratedValue String and UUID fields * Storage UUID fields as binary data on supporting pair db/jdbc driver * Storage UUID fields as canonical string representation when database or jdbc driver does not support UUID binary usage. * Updates manual * [OPENJPA-2930] Fixing issues found on review
1 parent 141bcd6 commit 6f4cf5b

File tree

21 files changed

+641
-8
lines changed

21 files changed

+641
-8
lines changed

openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
import org.apache.openjpa.util.OpenJPAId;
8383
import org.apache.openjpa.util.StoreException;
8484
import org.apache.openjpa.util.UserException;
85+
import org.apache.openjpa.util.UuidId;
8586

8687
/**
8788
* StoreManager plugin that uses JDBC to store persistent data in a

openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingRepository.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,6 +1360,7 @@ protected ValueHandler defaultHandler(ValueMapping val, boolean adapting) {
13601360
case JavaTypes.LOCAL_DATETIME:
13611361
case JavaTypes.OFFSET_TIME:
13621362
case JavaTypes.OFFSET_DATETIME:
1363+
case JavaTypes.UUID_OBJ:
13631364
return ImmutableValueHandler.getInstance();
13641365
case JavaTypes.STRING:
13651366
if (isClob(val, true))

openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ImmutableValueHandler.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ public Column[] map(ValueMapping vm, DBIdentifier name, ColumnIO io,
6565
col.setIdentifier(name);
6666
if (vm.getTypeCode() == JavaTypes.DATE)
6767
col.setJavaType(JavaSQLTypes.getDateTypeCode(vm.getType()));
68+
else if (vm.getTypeCode() == JavaTypes.UUID_OBJ)
69+
updateUUIDColumn(vm, col);
6870
else
6971
col.setJavaType(vm.getTypeCode());
7072
return new Column[]{ col };
@@ -94,6 +96,7 @@ public boolean isVersionable(ValueMapping vm) {
9496
case JavaTypes.OFFSET_DATETIME:
9597
case JavaTypes.BIGINTEGER:
9698
case JavaTypes.LOCALE:
99+
case JavaTypes.UUID_OBJ:
97100
return true;
98101
default:
99102
return false;
@@ -117,4 +120,15 @@ public Object toDataStoreValue(ValueMapping vm, Object val,
117120
// honor the user's null-value=default
118121
return JavaSQLTypes.getEmptyValue(vm.getTypeCode());
119122
}
123+
124+
private void updateUUIDColumn(ValueMapping vm, Column col) {
125+
DBDictionary dict = vm.getMappingRepository().getDBDictionary();
126+
if (dict.supportsUuidType) {
127+
col.setJavaType(vm.getTypeCode());
128+
col.setSize(-1);
129+
} else {
130+
col.setJavaType(JavaTypes.STRING);
131+
col.setSize(36);
132+
}
133+
}
120134
}

openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
import java.util.Map;
6868
import java.util.Set;
6969
import java.util.TreeMap;
70+
import java.util.UUID;
7071

7172
import javax.sql.DataSource;
7273

@@ -397,6 +398,7 @@ public enum DateMillisecondBehaviors { DROP, ROUND, RETAIN }
397398
public String varcharTypeName = "VARCHAR";
398399
public String xmlTypeName = "XML";
399400
public String xmlTypeEncoding = "UTF-8";
401+
public String uuidTypeName = "UUID";
400402
public String getStringVal = "";
401403

402404
// schema metadata
@@ -493,6 +495,8 @@ public enum DateMillisecondBehaviors { DROP, ROUND, RETAIN }
493495
protected String defaultSchemaName = null;
494496
private String conversionKey = null;
495497

498+
public boolean supportsUuidType = false;
499+
496500
// Naming utility and naming rules
497501
private DBIdentifierUtil namingUtil = null;
498502
private Map<String, IdentifierRule> namingRules = new HashMap<>();
@@ -1628,6 +1632,9 @@ public void setTyped(PreparedStatement stmnt, int idx, Object val, Column col, i
16281632
} else
16291633
setTimestamp(stmnt, idx, (Timestamp) val, null, col);
16301634
break;
1635+
case JavaTypes.UUID_OBJ:
1636+
setObject(stmnt, idx, val, Types.OTHER, col);
1637+
break;
16311638
default:
16321639
if (col != null && (col.getType() == Types.BLOB
16331640
|| col.getType() == Types.VARBINARY))
@@ -1733,6 +1740,10 @@ else if (val instanceof OffsetDateTime) {
17331740
else if (val instanceof Reader)
17341741
setCharacterStream(stmnt, idx, (Reader) val,
17351742
(sized == null) ? 0 : sized.size, col);
1743+
else if (val instanceof UUID && supportsUuidType)
1744+
setObject(stmnt, idx, (UUID) val, Types.OTHER, col);
1745+
else if (val instanceof UUID && !supportsUuidType)
1746+
setString(stmnt, idx, ((UUID) val).toString(), col);
17361747
else
17371748
throw new UserException(_loc.get("bad-param", val.getClass()));
17381749
}
@@ -1956,6 +1967,14 @@ public String getTypeName(Column col) {
19561967
if (col.isAutoAssigned() && autoAssignTypeName != null)
19571968
return appendSize(col, autoAssignTypeName);
19581969

1970+
if (col.getJavaType() == JavaTypes.UUID_OBJ) {
1971+
if (supportsUuidType)
1972+
return appendSize(col, uuidTypeName);
1973+
else {
1974+
return appendSize(col, getTypeName(Types.VARCHAR));
1975+
}
1976+
}
1977+
19591978
return appendSize(col, getTypeName(col.getType()));
19601979
}
19611980

openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/H2Dictionary.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ public class H2Dictionary extends DBDictionary {
144144
"UNKNOWN",
145145
"USER",
146146
"USING",
147+
"UUID",
147148
"VALUE",
148149
"VALUES",
149150
"WHEN",
@@ -238,6 +239,7 @@ public H2Dictionary() {
238239
"IS", "JOIN", "LIKE", "LIMIT", "MINUS", "NATURAL", "NOT", "NULL", "OFFSET", "ON", "ORDER", "PRIMARY", "ROWNUM",
239240
"SELECT", "SYSDATE", "TRUE", "UNION", "UNIQUE", "WHERE", "WITH",
240241
}));
242+
supportsUuidType = true;
241243
}
242244

243245
@Override

openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/HSQLDictionary.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,9 @@ public void connectedConfiguration(Connection conn) throws SQLException {
145145
packageName = "org.hsqldb.Trace";
146146
fieldName = "VIOLATION_OF_UNIQUE_INDEX";
147147
}
148+
if (dbMajorVersion > 2 || (dbMajorVersion == 2 && dbMinorVersion >= 4)) {
149+
supportsUuidType = true;
150+
}
148151
try {
149152
Class<?> cls = Class.forName(packageName);
150153
Field fld = cls.getField(fieldName);

openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/PostgresDictionary.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,8 @@ public PostgresDictionary() {
216216

217217
// PostgreSQL requires to escape search strings
218218
requiresSearchStringEscapeForLike = true;
219+
supportsUuidType = true;
220+
uuidTypeName = "UUID";
219221
}
220222

221223

@@ -305,7 +307,7 @@ public long getLong(ResultSet rs, int column)
305307
public void setNull(PreparedStatement stmnt, int idx, int colType,
306308
Column col)
307309
throws SQLException {
308-
if (col != null && col.isXML()) {
310+
if (col != null && (col.isXML() || col.getJavaType() == JavaTypes.UUID_OBJ)) {
309311
stmnt.setNull(idx, Types.OTHER);
310312
return;
311313
}

openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4927,6 +4927,7 @@ private void readExternal(ClassNode classNode, InsnList instructions, String fie
49274927
case JavaTypes.MAP:
49284928
case JavaTypes.OBJECT:
49294929
case JavaTypes.CALENDAR:
4930+
case JavaTypes.UUID_OBJ:
49304931
// if (sm != null)
49314932
// sm.proxyDetachedDeserialized (<index>);
49324933
instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this

openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import java.util.List;
3737
import java.util.Objects;
3838
import java.util.TimeZone;
39+
import java.util.UUID;
3940
import java.util.concurrent.locks.ReentrantLock;
4041

4142
import org.apache.openjpa.conf.OpenJPAConfiguration;
@@ -2905,6 +2906,13 @@ private void storeField(int field, Object val, FieldManager fm) {
29052906
case JavaTypes.STRING:
29062907
fm.storeStringField(field, (String) val);
29072908
break;
2909+
case JavaTypes.UUID_OBJ:
2910+
if (val instanceof String) {
2911+
fm.storeObjectField(field, (UUID) UUID.fromString((String) val));
2912+
} else if (val instanceof UUID) {
2913+
fm.storeObjectField(field, (UUID) val);
2914+
}
2915+
break;
29082916
default:
29092917
fm.storeObjectField(field, val);
29102918
}

openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
import org.apache.openjpa.util.ShortId;
7272
import org.apache.openjpa.util.StringId;
7373
import org.apache.openjpa.util.UnsupportedException;
74+
import org.apache.openjpa.util.UuidId;
7475

7576

7677
/**
@@ -559,6 +560,9 @@ public Class<?> getObjectIdType() {
559560
case JavaTypes.BOOLEAN_OBJ:
560561
_objectId = BooleanId.class;
561562
break;
563+
case JavaTypes.UUID_OBJ:
564+
_objectId = UuidId.class;
565+
break;
562566
}
563567
return _objectId;
564568
}

0 commit comments

Comments
 (0)