JPA 3.1.0 new features implementation (UUID) (#1418)

* JPA 3.1.0 new features implementation
- @GeneratedValue(strategy = GenerationType.UUID)
- java.util.UUID as a new supported datatype

Signed-off-by: Radek Felcman <radek.felcman@oracle.com>
diff --git a/foundation/eclipselink.core.test/src/it/java/org/eclipse/persistence/testing/tests/types/TypeTestModel.java b/foundation/eclipselink.core.test/src/it/java/org/eclipse/persistence/testing/tests/types/TypeTestModel.java
index a7545ac..a3e9f2f 100644
--- a/foundation/eclipselink.core.test/src/it/java/org/eclipse/persistence/testing/tests/types/TypeTestModel.java
+++ b/foundation/eclipselink.core.test/src/it/java/org/eclipse/persistence/testing/tests/types/TypeTestModel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2022 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0 which is available at
@@ -52,6 +52,7 @@
         addTest(getNumericTestSuite());
         addTest(getBLOBTestSuite());
         addTest(getCLOBTestSuite());
+        addTest(getUUIDTestSuite());
     }
 
     public static TestSuite getBLOBTestSuite() {
@@ -132,6 +133,19 @@
         return suite;
     }
 
+    public static TestSuite getUUIDTestSuite() {
+        TestSuite suite = new TestSuite();
+        Enumeration examples = UUIDTester.testInstances().elements();
+
+        suite.setName("UUID Types Test Suite");
+        suite.setDescription("Tests the use of UUID with EclipseLink");
+
+        while (examples.hasMoreElements()) {
+            suite.addTest(new WriteTypeObjectTest((TypeTester)examples.nextElement()));
+        }
+        return suite;
+    }
+
     @Override
     public void setup() {
         DatabaseSession session = (DatabaseSession)getSession();
@@ -142,6 +156,7 @@
             session.addDescriptor(StringTester.descriptorWithAccessors());
             session.addDescriptor(CLOBTester.descriptorWithAccessors());
             session.addDescriptor(BLOBTester.descriptorWithAccessors());
+            session.addDescriptor(UUIDTester.descriptorWithAccessors());
         } else {
             session.addDescriptor(BooleanTester.descriptor());
             session.addDescriptor(TimeDateTester.descriptor());
@@ -149,6 +164,7 @@
             session.addDescriptor(StringTester.descriptor());
             session.addDescriptor(CLOBTester.descriptor());
             session.addDescriptor(BLOBTester.descriptor());
+            session.addDescriptor(UUIDTester.descriptor());
         }
     }
 
diff --git a/foundation/eclipselink.core.test/src/it/java/org/eclipse/persistence/testing/tests/types/TypeTestSystem.java b/foundation/eclipselink.core.test/src/it/java/org/eclipse/persistence/testing/tests/types/TypeTestSystem.java
index a6f4036..45cea0e 100644
--- a/foundation/eclipselink.core.test/src/it/java/org/eclipse/persistence/testing/tests/types/TypeTestSystem.java
+++ b/foundation/eclipselink.core.test/src/it/java/org/eclipse/persistence/testing/tests/types/TypeTestSystem.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2022 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0 which is available at
@@ -34,6 +34,7 @@
         schemaManager.replaceObject(NumericTester.tableDefinition(session));
         schemaManager.replaceObject(CLOBTester.tableDefinition(session));
         schemaManager.replaceObject(BLOBTester.tableDefinition(session));
+        schemaManager.replaceObject(UUIDTester.tableDefinition(session));
     }
 
     @Override
diff --git a/foundation/eclipselink.core.test/src/it/java/org/eclipse/persistence/testing/tests/types/UUIDTester.java b/foundation/eclipselink.core.test/src/it/java/org/eclipse/persistence/testing/tests/types/UUIDTester.java
new file mode 100644
index 0000000..50bfc6a
--- /dev/null
+++ b/foundation/eclipselink.core.test/src/it/java/org/eclipse/persistence/testing/tests/types/UUIDTester.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0,
+ * or the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+
+// Contributors:
+//     Oracle - initial API and implementation
+package org.eclipse.persistence.testing.tests.types;
+
+import org.eclipse.persistence.descriptors.RelationalDescriptor;
+import org.eclipse.persistence.exceptions.DescriptorException;
+import org.eclipse.persistence.sessions.Session;
+import org.eclipse.persistence.tools.schemaframework.FieldDefinition;
+import org.eclipse.persistence.tools.schemaframework.TableDefinition;
+
+import java.util.UUID;
+import java.util.Vector;
+
+/**
+ *  Tests java.util.UUID access to the database.
+ */
+public class UUIDTester extends TypeTester {
+
+    private static final String UUID_TEST_VALUE = "4ae8976b-635f-46dc-937a-6016db49bd96";
+
+    public UUID uuidValue;
+
+    public UUIDTester() {
+        this(UUID.fromString(UUID_TEST_VALUE));
+    }
+
+    public UUIDTester(UUID testValue) {
+        super("uuidTest");
+        uuidValue = testValue;
+    }
+
+    public static RelationalDescriptor descriptor() {
+        RelationalDescriptor descriptor = new RelationalDescriptor();
+
+        /* First define the class, table and descriptor properties. */
+        descriptor.setJavaClass(UUIDTester.class);
+        descriptor.setTableName("UUIDS");
+        descriptor.setPrimaryKeyFieldName("NAME");
+
+        /* Next define the attribute mappings. */
+        descriptor.addDirectMapping("testName", "getTestName", "setTestName", "NAME");
+        descriptor.addDirectMapping("uuidValue", "UUIDV");
+        return descriptor;
+    }
+
+    public static RelationalDescriptor descriptorWithAccessors() {
+        RelationalDescriptor descriptor = new RelationalDescriptor();
+
+        /* First define the class, table and descriptor properties. */
+        descriptor.setJavaClass(UUIDTester.class);
+        descriptor.setTableName("UUIDS");
+        descriptor.setPrimaryKeyFieldName("NAME");
+
+        /* Next define the attribute mappings. */
+        try {
+            descriptor.addDirectMapping("testName", "getTestName", "setTestName", "NAME");
+            descriptor.addDirectMapping("uuidValue", "getUuidValue", "setUuidValue", "UUIDV");
+        } catch (DescriptorException exception) {
+        }
+        return descriptor;
+    }
+
+    public UUID getUuidValue() {
+        return uuidValue;
+    }
+
+    public void setUuidValue(UUID uuidValue) {
+        this.uuidValue = uuidValue;
+    }
+
+    /**
+     *Return a platform independent definition of the database table.
+     */
+    public static TableDefinition tableDefinition(Session session) {
+        TableDefinition definition = TypeTester.tableDefinition();
+        FieldDefinition fieldDef;
+
+        definition.setName("UUIDS");
+        fieldDef = new FieldDefinition("UUIDV", String.class, 50);
+        fieldDef.setShouldAllowNull(false);
+        definition.addField(fieldDef);
+
+        return definition;
+    }
+
+    public static Vector testInstances() {
+        Vector tests = new Vector(1);
+
+        tests.addElement(new UUIDTester(UUID.fromString(UUID_TEST_VALUE)));
+        return tests;
+    }
+
+    public String toString() {
+        return "UUIDTester(" + getUuidValue() + ")";
+    }
+}
diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/core/helper/CoreClassConstants.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/core/helper/CoreClassConstants.java
index b322eb3..955eb12 100644
--- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/core/helper/CoreClassConstants.java
+++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/core/helper/CoreClassConstants.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0 which is available at
@@ -28,6 +28,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.UUID;
 
 import javax.xml.datatype.Duration;
 import javax.xml.datatype.XMLGregorianCalendar;
@@ -77,6 +78,7 @@
     public static final Class<String> STRING = String.class;
     public static final Class<Time> TIME = Time.class;
     public static final Class<Timestamp> TIMESTAMP = Timestamp.class;
+    public static final Class<UUID> UUID = UUID.class;
     public static final Class<URL> URL_Class = URL.class;
     public static final Class<java.util.Date> UTILDATE = java.util.Date.class;
     public static final Class<XMLGregorianCalendar> XML_GREGORIAN_CALENDAR = XMLGregorianCalendar.class;
diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/databaseaccess/DatabasePlatform.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/databaseaccess/DatabasePlatform.java
index 4b28acd..1cf20de 100644
--- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/databaseaccess/DatabasePlatform.java
+++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/databaseaccess/DatabasePlatform.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2022 Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2019 IBM Corporation. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
@@ -60,6 +60,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.UUID;
 import java.util.Vector;
 
 // EclipseLink imports
@@ -2607,6 +2608,8 @@
             StructConverter converter = typeConverters.get(parameter.getClass());
             parameter = converter.convertToStruct(parameter, getConnection(session, statement.getConnection()));
             statement.setObject(index, parameter);
+        } else if (parameter instanceof UUID) {
+            statement.setString(index, convertObject(parameter, ClassConstants.STRING));
         } else {
             statement.setObject(index, parameter);
         }
diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/databaseaccess/DatasourcePlatform.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/databaseaccess/DatasourcePlatform.java
index 6b114d1..4ddb7c1 100644
--- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/databaseaccess/DatasourcePlatform.java
+++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/databaseaccess/DatasourcePlatform.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2022 Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2019, 2020 IBM Corporation. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
@@ -70,6 +70,9 @@
     /** Store the query use to query the current server time. */
     protected ValueReadQuery timestampQuery;
 
+    /** Store the query use to query the current server UUID. */
+    protected ValueReadQuery uuidQuery;
+
     /** Operators specific to this platform */
     protected transient Map<Integer, ExpressionOperator> platformOperators;
 
@@ -239,6 +242,7 @@
         DatasourcePlatform datasourcePlatform = (DatasourcePlatform)platform;
         datasourcePlatform.setTableQualifier(getTableQualifier());
         datasourcePlatform.setTimestampQuery(this.timestampQuery);
+        datasourcePlatform.setUUIDQuery(this.uuidQuery);
         datasourcePlatform.setConversionManager(getConversionManager());
         if (hasDefaultSequence()) {
             datasourcePlatform.setDefaultSequence(getDefaultSequence());
@@ -385,6 +389,16 @@
     }
 
     /**
+     * This method can be overridden by subclasses to return a
+     * query that will return the UUID from the server.
+     * return null if UUID can't be generated by platform.
+     */
+    @Override
+    public ValueReadQuery getUUIDQuery() {
+        return uuidQuery;
+    }
+
+    /**
      * OBSOLETE:
      * This method lazy initializes the update sequence number query.  It
      * allows for other queries to be used instead of the default one.
@@ -694,6 +708,14 @@
     }
 
     /**
+     * Can override the default query for returning a UUID from the server.
+     */
+    @Override
+    public void setUUIDQuery(ValueReadQuery uuidQuery) {
+        this.uuidQuery = uuidQuery;
+    }
+
+    /**
      * This method sets the update sequence number query.  It
      * allows for other queries to be used instead of the default one.
      */
diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/databaseaccess/Platform.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/databaseaccess/Platform.java
index 2b31561..29674e4 100644
--- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/databaseaccess/Platform.java
+++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/databaseaccess/Platform.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2022 Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2019 IBM Corporation. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
@@ -86,6 +86,13 @@
      */
     ValueReadQuery getTimestampQuery();
 
+    /**
+     * This method can be overridden by subclasses to return a
+     * query that will return the UUID from the server.
+     * return null if UUID generation is not available at the server.
+     */
+    ValueReadQuery getUUIDQuery();
+
     boolean isH2();
 
     boolean isAccess();
@@ -154,6 +161,11 @@
     void setTimestampQuery(ValueReadQuery tsQuery);
 
     /**
+     * Can override the default query for returning a UUID from the server.
+     */
+    void setUUIDQuery(ValueReadQuery uuidQuery);
+
+    /**
      * Add the parameter.
      * Convert the parameter to a string and write it.
      */
diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/ConversionManager.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/ConversionManager.java
index 0b5a801..ff1228b 100644
--- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/ConversionManager.java
+++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/ConversionManager.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2022 Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 1998, 2021 IBM Corporation and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
@@ -39,6 +39,7 @@
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
+import java.util.UUID;
 import java.util.concurrent.CopyOnWriteArrayList;
 
 import org.eclipse.persistence.config.SystemProperties;
@@ -231,6 +232,8 @@
                 return (T) convertObjectToClass(sourceObject);
             } else if(javaClass == ClassConstants.URL_Class) {
                 return (T) convertObjectToUrl(sourceObject);
+            } else if(javaClass == ClassConstants.UUID) {
+                return (T) convertObjectToUUID(sourceObject);
             }
         } catch (ConversionException ce) {
             throw ce;
@@ -1065,6 +1068,25 @@
 
     /**
      * INTERNAL:
+     * Build a valid instance of java.util.UUID from the given source object.
+     * @param sourceObject    Valid instance of java.util.UUID, or String
+     */
+    protected UUID convertObjectToUUID(Object sourceObject) throws ConversionException {
+        if(sourceObject.getClass() == ClassConstants.UUID) {
+            return (UUID) sourceObject;
+        } else if (sourceObject.getClass() == ClassConstants.STRING) {
+            try {
+                return UUID.fromString((String) sourceObject);
+            } catch(Exception e) {
+                throw ConversionException.couldNotBeConverted(sourceObject, ClassConstants.UUID, e);
+            }
+        } else {
+            throw ConversionException.couldNotBeConverted(sourceObject, ClassConstants.UUID);
+        }
+    }
+
+    /**
+     * INTERNAL:
      * Build a valid instance of java.util.Date from the given source object.
      * @param sourceObject    Valid instance of java.util.Date, String, java.sql.Timestamp, or Long
      */
diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/mappings/converters/UUIDConverter.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/mappings/converters/UUIDConverter.java
new file mode 100644
index 0000000..104df5f
--- /dev/null
+++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/mappings/converters/UUIDConverter.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0,
+ * or the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+
+// Contributors:
+//     Oracle - initial API and implementation
+package org.eclipse.persistence.mappings.converters;
+
+import org.eclipse.persistence.mappings.DatabaseMapping;
+import org.eclipse.persistence.mappings.foundation.AbstractDirectMapping;
+import org.eclipse.persistence.sessions.Session;
+
+import java.util.UUID;
+
+/**
+ * Default UUID field value to JDBC data type converter.
+ */
+public class UUIDConverter implements Converter {
+
+    /**
+     * Creates an instance of default UUID field value to JDBC data type converter.
+     */
+    public UUIDConverter() {
+    }
+
+    /**
+     * Converts UUID field value to String.
+     *
+     * @param uuidValue source UUID field value
+     * @param session current database session
+     * @return target String to be stored as JDBC VARCHAR
+     */
+    @Override
+    public Object convertObjectValueToDataValue(Object uuidValue, Session session) {
+        if (uuidValue instanceof UUID) {
+            return uuidValue.toString();
+        }
+        throw new IllegalArgumentException("Source object is not an instance of java.util.UUID");
+    }
+
+    /**
+     * Converts String from JDBC VARCHAR parameter to UUID field value.
+     *
+     * @param jdbcValue source String from JDBC VARCHAR
+     * @param session current database session
+     * @return target UUID field value
+     */
+    @Override
+    public Object convertDataValueToObjectValue(Object jdbcValue, Session session) {
+        return UUID.fromString(jdbcValue.toString());
+    }
+
+    /**
+     * UUID values and String are immutable.
+     *
+     * @return value of {@code false}
+     */
+    @Override
+    public boolean isMutable() {
+        return false;
+    }
+
+    /**
+     * Initialize mapping for JDBC data type.
+     *
+     * @param mapping field database mapping
+     * @param session current database session
+     */
+    @Override
+    public void initialize(DatabaseMapping mapping, Session session) {
+        if (mapping.isDirectToFieldMapping()) {
+            if (((AbstractDirectMapping)mapping).getFieldClassification() == null) {
+                final AbstractDirectMapping directMapping = AbstractDirectMapping.class.cast(mapping);
+                final Class<?> attributeClassification = mapping.getAttributeClassification();
+                if (attributeClassification.isInstance(UUID.class)) {
+                    directMapping.setFieldClassification(UUID.class);
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/platform/database/MySQLPlatform.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/platform/database/MySQLPlatform.java
index 1e98eb2..e7f855b 100644
--- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/platform/database/MySQLPlatform.java
+++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/platform/database/MySQLPlatform.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2022 Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 1998, 2018 IBM Corporation. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
@@ -838,4 +838,18 @@
         }
     }
 
+    /**
+     * INTERNAL:
+     * This method returns the query to select the UUID
+     * from the server for MySQL.
+     */
+    @Override
+    public ValueReadQuery getUUIDQuery() {
+        if (uuidQuery == null) {
+            uuidQuery = new ValueReadQuery();
+            uuidQuery.setSQLString("SELECT UUID()");
+            uuidQuery.setAllowNativeSQLQuery(true);
+        }
+        return uuidQuery;
+    }
 }
diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/sequencing/UUIDSequence.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/sequencing/UUIDSequence.java
index 586d4e1..afaf253 100644
--- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/sequencing/UUIDSequence.java
+++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/sequencing/UUIDSequence.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2022 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0 which is available at
@@ -19,6 +19,7 @@
 
 import org.eclipse.persistence.internal.databaseaccess.Accessor;
 import org.eclipse.persistence.internal.sessions.AbstractSession;
+import org.eclipse.persistence.queries.ValueReadQuery;
 
 public class UUIDSequence extends Sequence {
 
@@ -32,7 +33,12 @@
 
     @Override
     public Object getGeneratedValue(Accessor accessor, AbstractSession writeSession, String seqName) {
-        return UUID.randomUUID().toString().toUpperCase();
+        ValueReadQuery query = getDatasourcePlatform().getUUIDQuery();
+        if (query != null) {
+            return writeSession.executeQuery(query);
+        } else {
+            return UUID.randomUUID().toString();
+        }
     }
 
     @Override
diff --git a/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/platform/database/oracle/Oracle12Platform.java b/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/platform/database/oracle/Oracle12Platform.java
index d2299f7..d25a54e 100644
--- a/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/platform/database/oracle/Oracle12Platform.java
+++ b/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/platform/database/oracle/Oracle12Platform.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2022 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0 which is available at
@@ -197,4 +197,19 @@
     public Struct createStruct(String structTypeName, Object[] attributes, Connection connection) throws SQLException {
         return connection.createStruct(structTypeName, attributes);
     }
+
+    /**
+     * INTERNAL:
+     * This method returns the query to select the UUID
+     * from the server for Oracle.
+     */
+    @Override
+    public ValueReadQuery getUUIDQuery() {
+        if (uuidQuery == null) {
+            uuidQuery = new ValueReadQuery();
+            uuidQuery.setSQLString("SELECT LOWER(REGEXP_REPLACE(RAWTOHEX(SYS_GUID()), '([A-F0-9]{8})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{12})', '\\1-\\2-\\3-\\4-\\5')) AS uuid FROM dual");
+            uuidQuery.setAllowNativeSQLQuery(true);
+        }
+        return uuidQuery;
+    }
 }
diff --git a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/uuid/TestStringUUID.java b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/uuid/TestStringUUID.java
new file mode 100644
index 0000000..995b025
--- /dev/null
+++ b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/uuid/TestStringUUID.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0,
+ * or the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+
+// Contributors:
+//     Oracle - initial API and implementation
+package org.eclipse.persistence.jpa.test.uuid;
+
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.EntityManagerFactory;
+import jakarta.persistence.Query;
+import org.eclipse.persistence.jpa.test.framework.DDLGen;
+import org.eclipse.persistence.jpa.test.framework.Emf;
+import org.eclipse.persistence.jpa.test.framework.EmfRunner;
+import org.eclipse.persistence.jpa.test.uuid.model.UUIDStringEntity;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+import java.util.UUID;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(EmfRunner.class)
+public class TestStringUUID {
+
+    private static final String NAME_String = "Persist UUID String 1";
+
+    @Emf(name = "uuidStringEmf", createTables = DDLGen.DROP_CREATE, classes = { UUIDStringEntity.class })
+    private EntityManagerFactory uuidEmf;
+
+    /**
+     * Tests GenerationType.UUID with field based on String type.
+     */
+    @Test
+    public void testUuid() {
+        String uuid = persistUUIDStringEntity();
+        queryAllUUIDStringEntity();
+        queryWithParameterUUIDStringEntity(uuid);
+        findUUIDStringEntityTest(uuid);
+    }
+
+    private String persistUUIDStringEntity() {
+        EntityManager em = uuidEmf.createEntityManager();
+        String uuidResult = null;
+        try {
+            em.getTransaction().begin();
+            UUIDStringEntity entity = new UUIDStringEntity();
+            entity.setName(NAME_String);
+            em.persist(entity);
+            uuidResult = entity.getId();
+            assertNotNull(uuidResult);
+            em.getTransaction().commit();
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException();
+        }
+        finally {
+            if (em.getTransaction().isActive()) {
+                em.getTransaction().rollback();
+            }
+            em.close();
+        }
+        return uuidResult;
+    }
+
+    public void queryAllUUIDStringEntity() {
+        EntityManager em = uuidEmf.createEntityManager();
+        try {
+            List<UUIDStringEntity> testEntities = em.createQuery("SELECT e FROM UUIDStringEntity AS e").getResultList();
+            assertTrue(testEntities.size() > 0);
+            for (UUIDStringEntity entity: testEntities) {
+                assertNotNull(UUID.fromString(entity.getId()));
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException();
+        }
+        finally {
+            if (em.getTransaction().isActive()) {
+                em.getTransaction().rollback();
+            }
+            em.close();
+        }
+    }
+
+    public void queryWithParameterUUIDStringEntity(String id) {
+        EntityManager em = uuidEmf.createEntityManager();
+        try {
+            Query query = em.createQuery("SELECT e FROM UUIDStringEntity AS e WHERE e.id = :id");
+            query.setParameter("id", id);
+            List<UUIDStringEntity> testEntities = query.getResultList();
+            assertTrue(testEntities.size() > 0);
+            for (UUIDStringEntity entity: testEntities) {
+                assertNotNull(entity);
+                assertNotNull(UUID.fromString(entity.getId()));
+                assertEquals(id, entity.getId());
+                assertEquals(NAME_String, entity.getName());
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException();
+        }
+        finally {
+            if (em.getTransaction().isActive()) {
+                em.getTransaction().rollback();
+            }
+            em.close();
+        }
+    }
+
+    public void findUUIDStringEntityTest(String id) {
+        EntityManager em = uuidEmf.createEntityManager();
+        try {
+            UUIDStringEntity entity = em.find(UUIDStringEntity.class, id);
+            assertNotNull(entity);
+            assertEquals(id, entity.getId());
+            assertEquals(NAME_String, entity.getName());
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException();
+        }
+        finally {
+            if (em.getTransaction().isActive()) {
+                em.getTransaction().rollback();
+            }
+            em.close();
+        }
+    }
+}
diff --git a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/uuid/TestUUIDUUID.java b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/uuid/TestUUIDUUID.java
new file mode 100644
index 0000000..61e35e6
--- /dev/null
+++ b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/uuid/TestUUIDUUID.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0,
+ * or the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+
+// Contributors:
+//     Oracle - initial API and implementation
+package org.eclipse.persistence.jpa.test.uuid;
+
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.EntityManagerFactory;
+import jakarta.persistence.Query;
+import org.eclipse.persistence.jpa.test.framework.DDLGen;
+import org.eclipse.persistence.jpa.test.framework.Emf;
+import org.eclipse.persistence.jpa.test.framework.EmfRunner;
+import org.eclipse.persistence.jpa.test.uuid.model.UUIDUUIDEntity;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+import java.util.UUID;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(EmfRunner.class)
+public class TestUUIDUUID {
+
+    private static final String NAME_UUID = "Persist UUID UUID 1";
+
+    @Emf(name = "uuidUUIDEmf", createTables = DDLGen.DROP_CREATE, classes = { UUIDUUIDEntity.class })
+    private EntityManagerFactory uuidEmf;
+
+    /**
+     * Tests GenerationType.UUID with field based on java.util.UUID type.
+     */
+    @Test
+    public void testUuid() {
+        UUID uuid = persistUUIDUUIDEntity();
+        queryAllUUIDUUIDEntity();
+        queryWithParameterUUIDUUIDEntity(uuid);
+        findUUIDUUIDEntityTest(uuid);
+    }
+
+    private UUID persistUUIDUUIDEntity() {
+        EntityManager em = uuidEmf.createEntityManager();
+        UUID uuidResult = null;
+        try {
+            em.getTransaction().begin();
+            UUIDUUIDEntity entity = new UUIDUUIDEntity();
+            entity.setName(NAME_UUID);
+            em.persist(entity);
+            uuidResult = entity.getId();
+            assertNotNull(uuidResult);
+            em.getTransaction().commit();
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException();
+        }
+        finally {
+            if (em.getTransaction().isActive()) {
+                em.getTransaction().rollback();
+            }
+            em.close();
+        }
+        return uuidResult;
+    }
+
+    public void queryAllUUIDUUIDEntity() {
+        EntityManager em = uuidEmf.createEntityManager();
+        try {
+            List<UUIDUUIDEntity> testEntities = em.createQuery("SELECT e FROM UUIDUUIDEntity AS e").getResultList();
+            assertTrue(testEntities.size() > 0);
+            for (UUIDUUIDEntity entity: testEntities) {
+                assertNotNull(entity.getId());
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException();
+        }
+        finally {
+            if (em.getTransaction().isActive()) {
+                em.getTransaction().rollback();
+            }
+            em.close();
+        }
+    }
+
+    public void queryWithParameterUUIDUUIDEntity(UUID id) {
+        EntityManager em = uuidEmf.createEntityManager();
+        try {
+            Query query = em.createQuery("SELECT e FROM UUIDUUIDEntity AS e WHERE e.id = :id");
+            query.setParameter("id", id);
+            List<UUIDUUIDEntity> testEntities = query.getResultList();
+            assertTrue(testEntities.size() > 0);
+            for (UUIDUUIDEntity entity: testEntities) {
+                assertNotNull(entity);
+                assertNotNull(entity.getId());
+                assertEquals(id, entity.getId());
+                assertEquals(NAME_UUID, entity.getName());
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException();
+        }
+        finally {
+            if (em.getTransaction().isActive()) {
+                em.getTransaction().rollback();
+            }
+            em.close();
+        }
+    }
+
+    public void findUUIDUUIDEntityTest(UUID id) {
+        EntityManager em = uuidEmf.createEntityManager();
+        try {
+            UUIDUUIDEntity entity = em.find(UUIDUUIDEntity.class, id);
+            assertNotNull(entity);
+            assertEquals(id, entity.getId());
+            assertEquals(NAME_UUID, entity.getName());
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException();
+        }
+        finally {
+            if (em.getTransaction().isActive()) {
+                em.getTransaction().rollback();
+            }
+            em.close();
+        }
+    }
+}
diff --git a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/uuid/model/UUIDStringEntity.java b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/uuid/model/UUIDStringEntity.java
new file mode 100644
index 0000000..f936d28
--- /dev/null
+++ b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/uuid/model/UUIDStringEntity.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0,
+ * or the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+
+// Contributors:
+//     Oracle - initial API and implementation
+package org.eclipse.persistence.jpa.test.uuid.model;
+
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+
+@Entity
+@Table(name = "UUID_STRING")
+public class UUIDStringEntity {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.UUID)
+    private String id;
+
+    private String name;
+
+    public UUIDStringEntity() {
+    }
+
+    public UUIDStringEntity(String id) {
+        this.id = id;
+    }
+
+    public UUIDStringEntity(String id, String name) {
+        this.id = id;
+        this.name = name;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public String toString() {
+        return "UUIDStringEntity{" +
+                "id='" + id + '\'' +
+                ", name='" + name + '\'' +
+                '}';
+    }
+}
diff --git a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/uuid/model/UUIDUUIDEntity.java b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/uuid/model/UUIDUUIDEntity.java
new file mode 100644
index 0000000..dbade10
--- /dev/null
+++ b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/uuid/model/UUIDUUIDEntity.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0,
+ * or the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+
+// Contributors:
+//     Oracle - initial API and implementation
+package org.eclipse.persistence.jpa.test.uuid.model;
+
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+
+import java.util.UUID;
+
+@Entity
+@Table(name = "UUID_UUID")
+public class UUIDUUIDEntity {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.UUID)
+    private UUID id;
+
+    private String name;
+
+    public UUIDUUIDEntity() {
+    }
+
+    public UUIDUUIDEntity(UUID id) {
+        this.id = id;
+    }
+
+    public UUIDUUIDEntity(UUID id, String name) {
+        this.id = id;
+        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;
+    }
+
+    @Override
+    public String toString() {
+        return "UUIDUUIDEntity{" +
+                "id=" + id +
+                ", name='" + name + '\'' +
+                '}';
+    }
+}
diff --git a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/metadata/MetadataConstants.java b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/metadata/MetadataConstants.java
index bca6a31..d6a4cba 100644
--- a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/metadata/MetadataConstants.java
+++ b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/metadata/MetadataConstants.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2022 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0 which is available at
@@ -180,6 +180,7 @@
     public static final String JPA_GENERATION_SEQUENCE = "SEQUENCE";
     public static final String JPA_GENERATION_IDENTITY = "IDENTITY";
     public static final String JPA_GENERATION_AUTO = "AUTO";
+    public static final String JPA_GENERATION_UUID = "UUID";
 
     /**
      * Metamodel processing for MappedSuperclasses non-functional names.
diff --git a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/metadata/MetadataProject.java b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/metadata/MetadataProject.java
index 60c6700..8a58d32 100644
--- a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/metadata/MetadataProject.java
+++ b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/metadata/MetadataProject.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2022 Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 1998, 2018 IBM Corporation. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
@@ -195,6 +195,7 @@
     public static final String DEFAULT_TABLE_GENERATOR = "SEQ_GEN_TABLE";
     public static final String DEFAULT_SEQUENCE_GENERATOR = "SEQ_GEN_SEQUENCE";
     public static final String DEFAULT_IDENTITY_GENERATOR = "SEQ_GEN_IDENTITY";
+    public static final String DEFAULT_UUID_GENERATOR = "SEQ_GEN_UUID";
 
     // Boolean to specify if we should weave fetch groups.
     private boolean m_isWeavingFetchGroupsEnabled;
@@ -1763,6 +1764,10 @@
                 sequences.put(DEFAULT_IDENTITY_GENERATOR, new SequenceGeneratorMetadata(DEFAULT_IDENTITY_GENERATOR, 1, getPersistenceUnitDefaultCatalog(), getPersistenceUnitDefaultSchema(), true).process(m_logger));
             }
 
+            if (! sequences.containsKey(DEFAULT_UUID_GENERATOR)) {
+                sequences.put(DEFAULT_UUID_GENERATOR, new UuidGeneratorMetadata().process(m_logger));
+            }
+
             // Use a temporary sequence generator to build a qualifier to set on
             // the default generator. Don't use this generator as the default
             // auto generator though.
diff --git a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/metadata/accessors/mappings/MappingAccessor.java b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/metadata/accessors/mappings/MappingAccessor.java
index 40dc51a..8380875 100644
--- a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/metadata/accessors/mappings/MappingAccessor.java
+++ b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/metadata/accessors/mappings/MappingAccessor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2022 Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 1998, 2018 IBM Corporation. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
@@ -153,6 +153,7 @@
 import org.eclipse.persistence.internal.jpa.metadata.converters.LobMetadata;
 import org.eclipse.persistence.internal.jpa.metadata.converters.SerializedMetadata;
 import org.eclipse.persistence.internal.jpa.metadata.converters.TemporalMetadata;
+import org.eclipse.persistence.internal.jpa.metadata.converters.UUIDMetadata;
 import org.eclipse.persistence.internal.jpa.metadata.converters.XMLMetadata;
 import org.eclipse.persistence.internal.jpa.metadata.mappings.MapKeyMetadata;
 import org.eclipse.persistence.internal.jpa.metadata.xml.XMLEntityMappings;
@@ -1410,6 +1411,14 @@
 
     /**
      * INTERNAL:
+     * Return true if this represents a UUID type mapping.
+     */
+    protected boolean isUUID(MetadataClass referenceClass, boolean isForMapKey) {
+        return UUIDMetadata.isValidUUIDType(referenceClass);
+    }
+
+    /**
+     * INTERNAL:
      * Return true if this accessor represents a transient mapping.
      */
     public boolean isTransient() {
@@ -1852,6 +1861,8 @@
                 processLob(getLob(isForMapKey), mapping, referenceClass, isForMapKey);
             } else if (isTemporal(referenceClass, isForMapKey)) {
                 processTemporal(getTemporal(isForMapKey), mapping, referenceClass, isForMapKey);
+            } else if (isUUID(referenceClass, isForMapKey)) {
+                processUUID(mapping, referenceClass, isForMapKey);
             } else if (isSerialized(referenceClass, isForMapKey)) {
                 processSerialized(mapping, referenceClass, isForMapKey);
             }
@@ -2070,6 +2081,14 @@
 
     /**
      * INTERNAL:
+     * Process a UUID attribute.
+     */
+    protected void processUUID(DatabaseMapping mapping, MetadataClass referenceClass, boolean isForMapKey) {
+        new UUIDMetadata().process(mapping, this, referenceClass, isForMapKey);
+    }
+
+    /**
+     * INTERNAL:
      * Set the getter and setter access methods for this accessor.
      */
     protected void setAccessorMethods(DatabaseMapping mapping) {
diff --git a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/metadata/converters/UUIDMetadata.java b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/metadata/converters/UUIDMetadata.java
new file mode 100644
index 0000000..f795efa
--- /dev/null
+++ b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/metadata/converters/UUIDMetadata.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0,
+ * or the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+
+// Contributors:
+//     Oracle - initial API and implementation
+package org.eclipse.persistence.internal.jpa.metadata.converters;
+
+import org.eclipse.persistence.exceptions.ValidationException;
+import org.eclipse.persistence.internal.jpa.metadata.accessors.MetadataAccessor;
+import org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.MappingAccessor;
+import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataAnnotation;
+import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataClass;
+import org.eclipse.persistence.mappings.DatabaseMapping;
+import org.eclipse.persistence.mappings.converters.UUIDConverter;
+
+/**
+ * INTERNAL:
+ * Abstract converter class that parents both the JPA and Eclipselink
+ * converters.
+ *
+ * Key notes:
+ * - any metadata mapped from XML to this class must be compared in the
+ *   equals method.
+ * - when loading from annotations, the constructor accepts the metadata
+ *   accessor this metadata was loaded from. Used it to look up any
+ *   'companion' annotation needed for processing.
+ * - methods should be preserved in alphabetical order.
+ *
+ * @author Radek Felcman
+ * @since EclipseLink 4.0
+ */
+public class UUIDMetadata extends MetadataConverter {
+
+    /**
+     * INTERNAL:
+     * Used for XML loading.
+     */
+    public UUIDMetadata() {
+        super("<uuid>");
+    }
+
+    /**
+     * INTERNAL:
+     * Used for annotation loading.
+     */
+    public UUIDMetadata(MetadataAnnotation uuid, MetadataAccessor accessor) {
+        super(uuid, accessor);
+    }
+
+    /**
+     * INTERNAL:
+     */
+    @Override
+    public boolean equals(Object objectToCompare) {
+        return super.equals(objectToCompare) && objectToCompare instanceof UUIDMetadata;
+    }
+
+    @Override
+    public int hashCode() {
+        return super.hashCode();
+    }
+
+    /**
+     * INTERNAL:
+     * Returns true if the given class is a valid UUID type and must be
+     * marked UUID.
+     */
+    public static boolean isValidUUIDType(MetadataClass cls) {
+        return cls.isClass(java.util.UUID.class);
+    }
+
+    /**
+     * INTERNAL:
+     * Every converter needs to be able to process themselves.
+     */
+    @Override
+    public void process(DatabaseMapping mapping, MappingAccessor accessor, MetadataClass referenceClass, boolean isForMapKey) {
+        if (isValidUUIDType(referenceClass)) {
+            setFieldClassification(mapping, java.util.UUID.class, isForMapKey);
+            setConverter(mapping, new UUIDConverter(), isForMapKey);
+        } else {
+            throw ValidationException.invalidTypeForSerializedAttribute(mapping.getAttributeName(), accessor.getReferenceClass(), accessor.getJavaClass());
+        }
+    }
+}
diff --git a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/metadata/sequencing/GeneratedValueMetadata.java b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/metadata/sequencing/GeneratedValueMetadata.java
index bd603cf..fb6c834 100644
--- a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/metadata/sequencing/GeneratedValueMetadata.java
+++ b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/metadata/sequencing/GeneratedValueMetadata.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2022 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0 which is available at
@@ -36,6 +36,7 @@
 import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_GENERATION_IDENTITY;
 import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_GENERATION_SEQUENCE;
 import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_GENERATION_TABLE;
+import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_GENERATION_UUID;
 
 /**
  * Metadata object to hold generated value information.
@@ -152,6 +153,13 @@
                     sequence = (Sequence) sequences.get(MetadataProject.DEFAULT_IDENTITY_GENERATOR).clone();
                     sequence.setName(m_generator);
                 }
+            } else if (m_strategy.equals(JPA_GENERATION_UUID)) {
+                if (m_generator.equals("")) {
+                    sequence = sequences.get(MetadataProject.DEFAULT_UUID_GENERATOR);
+                } else {
+                    sequence = (Sequence) sequences.get(MetadataProject.DEFAULT_UUID_GENERATOR).clone();
+                    sequence.setName(m_generator);
+                }
             }
        }