This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git

commit 5aff3c51c5a88050eb7e1c95d55e02ca9f0300cb
Author: Andrus Adamchik <[email protected]>
AuthorDate: Thu Jun 25 17:44:01 2026 -0400

    Sequence PkGenerator inheritance hierarchy cleanup
---
 ...lePkGenerator.java => SequencePkGenerator.java} |  63 ++++---
 .../org/apache/cayenne/dba/db2/DB2PkGenerator.java |   4 +-
 .../apache/cayenne/dba/derby/DerbyPkGenerator.java |   4 +-
 .../org/apache/cayenne/dba/h2/H2PkGenerator.java   |   4 +-
 .../cayenne/dba/ingres/IngresPkGenerator.java      |   4 +-
 .../cayenne/dba/oracle/OraclePkGenerator.java      | 197 +--------------------
 .../cayenne/dba/postgres/PostgresPkGenerator.java  |   4 +-
 ...neratorIT.java => SequencePkGeneratorTest.java} |  29 ++-
 8 files changed, 54 insertions(+), 255 deletions(-)

diff --git 
a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OraclePkGenerator.java 
b/cayenne/src/main/java/org/apache/cayenne/dba/SequencePkGenerator.java
similarity index 84%
copy from 
cayenne/src/main/java/org/apache/cayenne/dba/oracle/OraclePkGenerator.java
copy to cayenne/src/main/java/org/apache/cayenne/dba/SequencePkGenerator.java
index aee6bffa3..628638988 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OraclePkGenerator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/SequencePkGenerator.java
@@ -17,12 +17,10 @@
  *  under the License.
  ****************************************************************/
 
-package org.apache.cayenne.dba.oracle;
+package org.apache.cayenne.dba;
 
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.access.DataNode;
-import org.apache.cayenne.dba.JdbcAdapter;
-import org.apache.cayenne.dba.JdbcPkGenerator;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbKeyGenerator;
 
@@ -34,38 +32,37 @@ import java.util.ArrayList;
 import java.util.List;
 
 /**
- * Sequence-based primary key generator implementation for Oracle. Uses Oracle
- * sequences to generate primary key values. This approach is at least 50%
- * faster when tested with Oracle compared to the lookup table approach.
+ * A common superclass for sequence-based primary key generators. Uses database
+ * sequences to generate primary key values, which is generally faster than the
+ * lookup table approach implemented by {@link JdbcPkGenerator}. Concrete
+ * subclasses provide database-specific SQL for selecting the next sequence 
value
+ * and for discovering existing sequences.
  * <p>
- * When using Cayenne key caching mechanism, make sure that sequences in the
- * database have "INCREMENT BY" greater or equal to OraclePkGenerator
- * "pkCacheSize" property value. If this is not the case, you will need to
- * adjust PkGenerator value accordingly. For example when sequence is
- * incremented by 1 each time, use the following code:
+ * When using the Cayenne key caching mechanism, make sure that sequences in 
the
+ * database have "INCREMENT BY" greater or equal to the generator "pkCacheSize"
+ * property value. If this is not the case, you will need to adjust the
+ * PkGenerator value accordingly. For example when a sequence is incremented 
by 1
+ * each time, use the following code:
  * </p>
  *
  * <pre>
  * dataNode.getAdapter().getPkGenerator().setPkCacheSize(1);
  * </pre>
+ *
+ * @since 5.0
  */
-public class OraclePkGenerator extends JdbcPkGenerator {
+public abstract class SequencePkGenerator extends JdbcPkGenerator {
 
-    /**
-     * Used by DI
-     *
-     * @since 4.1
-     */
-    public OraclePkGenerator() {
+    private static final String _SEQUENCE_PREFIX = "pk_";
+
+    public SequencePkGenerator() {
         super();
     }
 
-    protected OraclePkGenerator(JdbcAdapter adapter) {
+    protected SequencePkGenerator(JdbcAdapter adapter) {
         super(adapter);
     }
 
-    private static final String _SEQUENCE_PREFIX = "pk_";
-
     @Override
     public void createAutoPk(DataNode node, List<DbEntity> dbEntities) {
         List<String> sequences = getExistingSequences(node);
@@ -132,21 +129,21 @@ public class OraclePkGenerator extends JdbcPkGenerator {
         return "DROP SEQUENCE " + seqFQN;
     }
 
-    protected String selectNextValQuery(String pkGeneratingSequenceName) {
-        return "SELECT " + pkGeneratingSequenceName + ".nextval FROM DUAL";
-    }
+    /**
+     * Returns a database-specific query to fetch the next value of the named
+     * sequence.
+     */
+    protected abstract String selectNextValQuery(String 
pkGeneratingSequenceName);
 
-    protected String selectAllSequencesQuery() {
-        return "SELECT LOWER(SEQUENCE_NAME) FROM ALL_SEQUENCES";
-    }
+    /**
+     * Returns a database-specific query that lists the names of all existing
+     * sequences.
+     */
+    protected abstract String selectAllSequencesQuery();
 
     /**
-     * Generates primary key by calling Oracle sequence corresponding to the
-     * <code>dbEntity</code>. Executed SQL looks like this:
-     *
-     * <pre>
-     *   SELECT pk_table_name.nextval FROM DUAL
-     * </pre>
+     * Generates a primary key by calling the database sequence corresponding 
to
+     * the <code>dbEntity</code>.
      *
      * @since 3.0
      */
diff --git 
a/cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2PkGenerator.java 
b/cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2PkGenerator.java
index 2a7c5f2c2..d9b513d9d 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2PkGenerator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/db2/DB2PkGenerator.java
@@ -19,13 +19,13 @@
 package org.apache.cayenne.dba.db2;
 
 import org.apache.cayenne.dba.JdbcAdapter;
-import org.apache.cayenne.dba.oracle.OraclePkGenerator;
+import org.apache.cayenne.dba.SequencePkGenerator;
 import org.apache.cayenne.map.DbEntity;
 
 /**
  * A sequence-based PK generator used by {@link DB2Adapter}.
  */
-public class DB2PkGenerator extends OraclePkGenerator {
+public class DB2PkGenerator extends SequencePkGenerator {
 
     /**
      * Used by DI
diff --git 
a/cayenne/src/main/java/org/apache/cayenne/dba/derby/DerbyPkGenerator.java 
b/cayenne/src/main/java/org/apache/cayenne/dba/derby/DerbyPkGenerator.java
index b9e8bd5e1..876f62cd8 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/derby/DerbyPkGenerator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/derby/DerbyPkGenerator.java
@@ -20,7 +20,7 @@
 package org.apache.cayenne.dba.derby;
 
 import org.apache.cayenne.dba.JdbcAdapter;
-import org.apache.cayenne.dba.oracle.OraclePkGenerator;
+import org.apache.cayenne.dba.SequencePkGenerator;
 import org.apache.cayenne.map.DbEntity;
 
 /**
@@ -28,7 +28,7 @@ import org.apache.cayenne.map.DbEntity;
  *
  * @since 4.0 (old one used AUTO_PK_SUPPORT table)
  */
-public class DerbyPkGenerator extends OraclePkGenerator {
+public class DerbyPkGenerator extends SequencePkGenerator {
 
     /**
      * Used by DI
diff --git a/cayenne/src/main/java/org/apache/cayenne/dba/h2/H2PkGenerator.java 
b/cayenne/src/main/java/org/apache/cayenne/dba/h2/H2PkGenerator.java
index 5d3265c4a..ae45d710c 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/h2/H2PkGenerator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/h2/H2PkGenerator.java
@@ -20,7 +20,7 @@
 package org.apache.cayenne.dba.h2;
 
 import org.apache.cayenne.dba.JdbcAdapter;
-import org.apache.cayenne.dba.oracle.OraclePkGenerator;
+import org.apache.cayenne.dba.SequencePkGenerator;
 import org.apache.cayenne.map.DbEntity;
 
 /**
@@ -28,7 +28,7 @@ import org.apache.cayenne.map.DbEntity;
  *
  * @since 4.0
  */
-public class H2PkGenerator extends OraclePkGenerator {
+public class H2PkGenerator extends SequencePkGenerator {
 
     /**
      * Used by DI
diff --git 
a/cayenne/src/main/java/org/apache/cayenne/dba/ingres/IngresPkGenerator.java 
b/cayenne/src/main/java/org/apache/cayenne/dba/ingres/IngresPkGenerator.java
index 304772d20..9fd76cefd 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/ingres/IngresPkGenerator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/ingres/IngresPkGenerator.java
@@ -20,14 +20,14 @@
 package org.apache.cayenne.dba.ingres;
 
 import org.apache.cayenne.dba.JdbcAdapter;
-import org.apache.cayenne.dba.oracle.OraclePkGenerator;
+import org.apache.cayenne.dba.SequencePkGenerator;
 
 /**
  * Ingres-specific sequence based PK generator.
  *
  * @since 1.2
  */
-public class IngresPkGenerator extends OraclePkGenerator {
+public class IngresPkGenerator extends SequencePkGenerator {
 
     /**
      * Used by DI
diff --git 
a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OraclePkGenerator.java 
b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OraclePkGenerator.java
index aee6bffa3..2c050b1d1 100644
--- a/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OraclePkGenerator.java
+++ b/cayenne/src/main/java/org/apache/cayenne/dba/oracle/OraclePkGenerator.java
@@ -19,37 +19,13 @@
 
 package org.apache.cayenne.dba.oracle;
 
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.access.DataNode;
 import org.apache.cayenne.dba.JdbcAdapter;
-import org.apache.cayenne.dba.JdbcPkGenerator;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbKeyGenerator;
-
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.List;
+import org.apache.cayenne.dba.SequencePkGenerator;
 
 /**
- * Sequence-based primary key generator implementation for Oracle. Uses Oracle
- * sequences to generate primary key values. This approach is at least 50%
- * faster when tested with Oracle compared to the lookup table approach.
- * <p>
- * When using Cayenne key caching mechanism, make sure that sequences in the
- * database have "INCREMENT BY" greater or equal to OraclePkGenerator
- * "pkCacheSize" property value. If this is not the case, you will need to
- * adjust PkGenerator value accordingly. For example when sequence is
- * incremented by 1 each time, use the following code:
- * </p>
- *
- * <pre>
- * dataNode.getAdapter().getPkGenerator().setPkCacheSize(1);
- * </pre>
+ * Sequence-based primary key generator implementation for Oracle. Uses Oracle 
sequences to generate primary key values.
  */
-public class OraclePkGenerator extends JdbcPkGenerator {
+public class OraclePkGenerator extends SequencePkGenerator {
 
     /**
      * Used by DI
@@ -64,178 +40,13 @@ public class OraclePkGenerator extends JdbcPkGenerator {
         super(adapter);
     }
 
-    private static final String _SEQUENCE_PREFIX = "pk_";
-
-    @Override
-    public void createAutoPk(DataNode node, List<DbEntity> dbEntities) {
-        List<String> sequences = getExistingSequences(node);
-        // create needed sequences
-        for (DbEntity dbEntity : dbEntities) {
-            if (!sequences.contains(sequenceName(dbEntity))) {
-                runUpdate(node, createSequenceString(dbEntity));
-            }
-        }
-    }
-
-    /**
-     * Creates a list of CREATE SEQUENCE statements for the list of DbEntities.
-     */
-    @Override
-    public List<String> createAutoPkStatements(List<DbEntity> dbEntities) {
-        List<String> list = new ArrayList<>(dbEntities.size());
-        for (DbEntity dbEntity : dbEntities) {
-            list.add(createSequenceString(dbEntity));
-        }
-
-        return list;
-    }
-
-    /**
-     * Drops PK sequences for all specified DbEntities.
-     */
-    @Override
-    public void dropAutoPk(DataNode node, List<DbEntity> dbEntities) {
-        List<String> sequences = getExistingSequences(node);
-
-        // drop obsolete sequences
-        for (DbEntity dbEntity : dbEntities) {
-            if (sequences.contains(sequenceName(dbEntity))) {
-                runUpdate(node, dropSequenceString(dbEntity));
-            }
-        }
-    }
-
-    /**
-     * Creates a list of DROP SEQUENCE statements for the list of DbEntities.
-     */
     @Override
-    public List<String> dropAutoPkStatements(List<DbEntity> dbEntities) {
-        List<String> list = new ArrayList<>(dbEntities.size());
-        for (DbEntity dbEntity : dbEntities) {
-            list.add(dropSequenceString(dbEntity));
-        }
-
-        return list;
-    }
-
-    protected String createSequenceString(DbEntity ent) {
-        String seqFQN = 
adapter.getQuotingStrategy(ent).quotedFQN(ent.getCatalog(), ent.getSchema(), 
sequenceName(ent));
-        return "CREATE SEQUENCE " + seqFQN + " START WITH " + pkStartValue + " 
INCREMENT BY " + pkCacheSize(ent);
-    }
-
-    /**
-     * Returns a SQL string needed to drop any database objects associated with
-     * automatic primary key generation process for a specific DbEntity.
-     */
-    protected String dropSequenceString(DbEntity ent) {
-        String seqFQN = 
adapter.getQuotingStrategy(ent).quotedFQN(ent.getCatalog(), ent.getSchema(), 
sequenceName(ent));
-        return "DROP SEQUENCE " + seqFQN;
-    }
-
     protected String selectNextValQuery(String pkGeneratingSequenceName) {
         return "SELECT " + pkGeneratingSequenceName + ".nextval FROM DUAL";
     }
 
+    @Override
     protected String selectAllSequencesQuery() {
         return "SELECT LOWER(SEQUENCE_NAME) FROM ALL_SEQUENCES";
     }
-
-    /**
-     * Generates primary key by calling Oracle sequence corresponding to the
-     * <code>dbEntity</code>. Executed SQL looks like this:
-     *
-     * <pre>
-     *   SELECT pk_table_name.nextval FROM DUAL
-     * </pre>
-     *
-     * @since 3.0
-     */
-    @Override
-    protected long longPkFromDatabase(DataNode node, DbEntity entity) {
-
-        DbKeyGenerator pkGenerator = entity.getPrimaryKeyGenerator();
-        String pkGeneratingSequenceName;
-        if (pkGenerator != null && 
DbKeyGenerator.ORACLE_TYPE.equals(pkGenerator.getGeneratorType())
-                && pkGenerator.getGeneratorName() != null) {
-            pkGeneratingSequenceName = pkGenerator.getGeneratorName();
-        } else {
-            pkGeneratingSequenceName = 
adapter.getQuotingStrategy(entity).quotedFQN(entity.getCatalog(),
-                    entity.getSchema(), sequenceName(entity));
-        }
-
-        try (Connection con = node.getDataSource().getConnection()) {
-            try (Statement st = con.createStatement()) {
-                String sql = selectNextValQuery(pkGeneratingSequenceName);
-                adapter.getJdbcEventLogger().log(sql);
-
-                try (ResultSet rs = st.executeQuery(sql)) {
-                    if (!rs.next()) {
-                        throw new CayenneRuntimeException("Error generating pk 
for DbEntity %s", entity.getName());
-                    }
-                    return rs.getLong(1);
-                }
-            }
-        } catch (SQLException e) {
-            throw new CayenneRuntimeException("Error generating pk for 
DbEntity %s", e, entity.getName());
-        }
-    }
-
-    protected int pkCacheSize(DbEntity entity) {
-        // use custom generator if possible
-        DbKeyGenerator keyGenerator = entity.getPrimaryKeyGenerator();
-        if (keyGenerator != null && 
DbKeyGenerator.ORACLE_TYPE.equals(keyGenerator.getGeneratorType())
-                && keyGenerator.getGeneratorName() != null) {
-
-            Integer size = keyGenerator.getKeyCacheSize();
-            return (size != null && size >= 1) ? size : getPkCacheSize();
-        } else {
-            return getPkCacheSize();
-        }
-    }
-
-    protected String sequenceName(DbEntity entity) {
-
-        // use custom generator if possible
-        DbKeyGenerator keyGenerator = entity.getPrimaryKeyGenerator();
-        if (keyGenerator != null
-                && 
DbKeyGenerator.ORACLE_TYPE.equals(keyGenerator.getGeneratorType())
-                && keyGenerator.getGeneratorName() != null) {
-
-            return keyGenerator.getGeneratorName().toLowerCase();
-        } else {
-            return getSequencePrefix() + entity.getName().toLowerCase();
-        }
-    }
-
-    protected String getSequencePrefix() {
-        return _SEQUENCE_PREFIX;
-    }
-
-    /**
-     * Fetches a list of existing sequences that might match Cayenne generated
-     * ones.
-     */
-    protected List<String> getExistingSequences(DataNode node) {
-
-        // check existing sequences
-        try (Connection con = node.getDataSource().getConnection()) {
-            try (Statement sel = con.createStatement()) {
-                String sql = selectAllSequencesQuery();
-                adapter.getJdbcEventLogger().log(sql);
-
-                try (ResultSet rs = sel.executeQuery(sql)) {
-                    List<String> sequenceList = new ArrayList<>();
-                    while (rs.next()) {
-                        String name = rs.getString(1);
-                        if (name != null) {
-                            sequenceList.add(name.trim());
-                        }
-                    }
-                    return sequenceList;
-                }
-            }
-        } catch (SQLException e) {
-            throw new CayenneRuntimeException("Error fetching existing 
sequences", e);
-        }
-    }
 }
diff --git 
a/cayenne/src/main/java/org/apache/cayenne/dba/postgres/PostgresPkGenerator.java
 
b/cayenne/src/main/java/org/apache/cayenne/dba/postgres/PostgresPkGenerator.java
index c8b9fbbf9..1a863b473 100644
--- 
a/cayenne/src/main/java/org/apache/cayenne/dba/postgres/PostgresPkGenerator.java
+++ 
b/cayenne/src/main/java/org/apache/cayenne/dba/postgres/PostgresPkGenerator.java
@@ -20,13 +20,13 @@
 package org.apache.cayenne.dba.postgres;
 
 import org.apache.cayenne.dba.JdbcAdapter;
-import org.apache.cayenne.dba.oracle.OraclePkGenerator;
+import org.apache.cayenne.dba.SequencePkGenerator;
 import org.apache.cayenne.map.DbEntity;
 
 /**
  * Default PK generator for PostgreSQL that uses sequences for PK generation.
  */
-public class PostgresPkGenerator extends OraclePkGenerator {
+public class PostgresPkGenerator extends SequencePkGenerator {
 
     /**
      * Used by DI
diff --git 
a/cayenne/src/test/java/org/apache/cayenne/dba/oracle/OraclePkGeneratorIT.java 
b/cayenne/src/test/java/org/apache/cayenne/dba/SequencePkGeneratorTest.java
similarity index 69%
rename from 
cayenne/src/test/java/org/apache/cayenne/dba/oracle/OraclePkGeneratorIT.java
rename to 
cayenne/src/test/java/org/apache/cayenne/dba/SequencePkGeneratorTest.java
index a5a07d090..f760fdedb 100644
--- 
a/cayenne/src/test/java/org/apache/cayenne/dba/oracle/OraclePkGeneratorIT.java
+++ b/cayenne/src/test/java/org/apache/cayenne/dba/SequencePkGeneratorTest.java
@@ -17,43 +17,34 @@
  *  under the License.
  ****************************************************************/
 
-package org.apache.cayenne.dba.oracle;
+package org.apache.cayenne.dba;
 
-import org.apache.cayenne.di.AdhocObjectFactory;
+import org.apache.cayenne.dba.oracle.OraclePkGenerator;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbKeyGenerator;
-import org.apache.cayenne.unit.CayenneProjects;
-import org.apache.cayenne.unit.CayenneTestsEnv;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.RegisterExtension;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
-public class OraclePkGeneratorIT {
+public class SequencePkGeneratorTest {
 
-    @RegisterExtension
-    static final CayenneTestsEnv env = 
CayenneTestsEnv.forProject(CayenneProjects.TESTMAP_PROJECT);
-
-    protected AdhocObjectFactory objectFactory;
-
-    private OraclePkGenerator pkGenerator;
+    private SequencePkGenerator pkGenerator;
 
     @BeforeEach
-    public void setUp() throws Exception {
-        objectFactory = env.adhocObjectFactory();
-        OracleAdapter adapter = objectFactory.newInstance(OracleAdapter.class, 
OracleAdapter.class.getName());
-        pkGenerator = new OraclePkGenerator(adapter);
+    public void setUp() {
+        // use a concrete subclass to exercise the shared sequence naming logic
+        pkGenerator = new OraclePkGenerator();
     }
 
     @Test
-    public void sequenceNameDefault() throws Exception {
+    public void sequenceNameDefault() {
         DbEntity entity = new DbEntity("TEST_ENTITY");
         assertEquals("pk_test_entity", pkGenerator.sequenceName(entity));
     }
 
     @Test
-    public void sequenceNameCustom1() throws Exception {
+    public void sequenceNameCustom1() {
         DbEntity entity = new DbEntity("TEST_ENTITY");
         DbKeyGenerator customGenerator = new DbKeyGenerator();
         customGenerator.setGeneratorType(DbKeyGenerator.ORACLE_TYPE);
@@ -63,7 +54,7 @@ public class OraclePkGeneratorIT {
     }
 
     @Test
-    public void sequenceNameCustom2() throws Exception {
+    public void sequenceNameCustom2() {
         DbEntity entity = new DbEntity("TEST_ENTITY");
         DbKeyGenerator customGenerator = new DbKeyGenerator();
         
customGenerator.setGeneratorType(DbKeyGenerator.NAMED_SEQUENCE_TABLE_TYPE);

Reply via email to