Repository: cayenne Updated Branches: refs/heads/master b2957a69d -> 27fb5716a
PkGenerators cleanup Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/27fb5716 Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/27fb5716 Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/27fb5716 Branch: refs/heads/master Commit: 27fb5716a0bd8b690591bc13096d2da6a8873e43 Parents: b2957a6 Author: Nikita Timofeev <stari...@gmail.com> Authored: Wed Feb 8 16:41:46 2017 +0300 Committer: Nikita Timofeev <stari...@gmail.com> Committed: Wed Feb 8 16:41:46 2017 +0300 ---------------------------------------------------------------------- .../org/apache/cayenne/dba/JdbcPkGenerator.java | 51 +++---- .../apache/cayenne/dba/db2/DB2PkGenerator.java | 141 ++----------------- .../cayenne/dba/derby/DerbyPkGenerator.java | 12 +- .../apache/cayenne/dba/h2/H2PkGenerator.java | 64 +-------- .../cayenne/dba/ingres/IngresPkGenerator.java | 64 +-------- .../cayenne/dba/mysql/MySQLPkGenerator.java | 79 ++++------- .../cayenne/dba/oracle/OraclePkGenerator.java | 117 +++++++-------- .../dba/postgres/PostgresPkGenerator.java | 73 +--------- .../cayenne/dba/sybase/SybasePkGenerator.java | 62 +++----- .../apache/cayenne/tx/CayenneTransaction.java | 93 ++++++------ 10 files changed, 207 insertions(+), 549 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cayenne/blob/27fb5716/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcPkGenerator.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcPkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcPkGenerator.java index 0187bf8..553283b 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcPkGenerator.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcPkGenerator.java @@ -116,11 +116,8 @@ public class JdbcPkGenerator implements PkGenerator { } protected String pkTableCreateString() { - StringBuilder buf = new StringBuilder(); - buf.append("CREATE TABLE AUTO_PK_SUPPORT (").append(" TABLE_NAME CHAR(100) NOT NULL,") - .append(" NEXT_ID BIGINT NOT NULL,").append(" PRIMARY KEY(TABLE_NAME)").append(")"); - - return buf.toString(); + return "CREATE TABLE AUTO_PK_SUPPORT " + + "(TABLE_NAME CHAR(100) NOT NULL, NEXT_ID BIGINT NOT NULL, PRIMARY KEY(TABLE_NAME))"; } protected String pkDeleteString(List<DbEntity> dbEntities) { @@ -139,23 +136,15 @@ public class JdbcPkGenerator implements PkGenerator { } protected String pkCreateString(String entName) { - StringBuilder buf = new StringBuilder(); - buf.append("INSERT INTO AUTO_PK_SUPPORT").append(" (TABLE_NAME, NEXT_ID)").append(" VALUES ('").append(entName) - .append("', ").append(pkStartValue).append(")"); - return buf.toString(); + return "INSERT INTO AUTO_PK_SUPPORT (TABLE_NAME, NEXT_ID) VALUES ('" + entName + "', " + pkStartValue + ")"; } protected String pkSelectString(String entName) { - StringBuilder buf = new StringBuilder(); - buf.append("SELECT NEXT_ID FROM AUTO_PK_SUPPORT WHERE TABLE_NAME = '").append(entName).append('\''); - return buf.toString(); + return "SELECT NEXT_ID FROM AUTO_PK_SUPPORT WHERE TABLE_NAME = '" + entName + '\''; } protected String pkUpdateString(String entName) { - StringBuilder buf = new StringBuilder(); - buf.append("UPDATE AUTO_PK_SUPPORT").append(" SET NEXT_ID = NEXT_ID + ").append(pkCacheSize) - .append(" WHERE TABLE_NAME = '").append(entName).append('\''); - return buf.toString(); + return "UPDATE AUTO_PK_SUPPORT SET NEXT_ID = NEXT_ID + " + pkCacheSize + " WHERE TABLE_NAME = '" + entName + '\''; } protected String dropAutoPkString() { @@ -167,10 +156,9 @@ public class JdbcPkGenerator implements PkGenerator { */ protected boolean autoPkTableExists(DataNode node) throws SQLException { - try (Connection con = node.getDataSource().getConnection();) { + try (Connection con = node.getDataSource().getConnection()) { DatabaseMetaData md = con.getMetaData(); - - try (ResultSet tables = md.getTables(null, null, "AUTO_PK_SUPPORT", null);) { + try (ResultSet tables = md.getTables(null, null, "AUTO_PK_SUPPORT", null)) { return tables.next(); } } @@ -186,8 +174,8 @@ public class JdbcPkGenerator implements PkGenerator { public int runUpdate(DataNode node, String sql) throws SQLException { adapter.getJdbcEventLogger().logQuery(sql, Collections.EMPTY_LIST); - try (Connection con = node.getDataSource().getConnection();) { - try (Statement upd = con.createStatement();) { + try (Connection con = node.getDataSource().getConnection()) { + try (Statement upd = con.createStatement()) { return upd.executeUpdate(sql); } } @@ -205,7 +193,7 @@ public class JdbcPkGenerator implements PkGenerator { */ public Object generatePk(DataNode node, DbAttribute pk) throws Exception { - DbEntity entity = (DbEntity) pk.getEntity(); + DbEntity entity = pk.getEntity(); switch (pk.getType()) { case Types.BINARY: @@ -215,10 +203,11 @@ public class JdbcPkGenerator implements PkGenerator { DbKeyGenerator pkGenerator = entity.getPrimaryKeyGenerator(); long cacheSize; - if (pkGenerator != null && pkGenerator.getKeyCacheSize() != null) - cacheSize = pkGenerator.getKeyCacheSize().intValue(); - else + if (pkGenerator != null && pkGenerator.getKeyCacheSize() != null) { + cacheSize = pkGenerator.getKeyCacheSize(); + } else { cacheSize = pkCacheSize; + } Long value; @@ -230,7 +219,7 @@ public class JdbcPkGenerator implements PkGenerator { if (pks == null) { // created exhausted LongPkRange - pks = new ConcurrentLinkedQueue<Long>(); + pks = new ConcurrentLinkedQueue<>(); Queue<Long> previousPks = pkCache.putIfAbsent(entity.getName(), pks); if (previousPks != null) { pks = previousPks; @@ -249,8 +238,7 @@ public class JdbcPkGenerator implements PkGenerator { if (pk.getType() == Types.BIGINT) { return value; } else { - // leaving it up to the user to ensure that PK does not exceed max - // int... + // leaving it up to the user to ensure that PK does not exceed max int... return value.intValue(); } } @@ -268,7 +256,7 @@ public class JdbcPkGenerator implements PkGenerator { * @since 3.0 */ protected long longPkFromDatabase(DataNode node, DbEntity entity) throws Exception { - String select = "SELECT #result('NEXT_ID' 'long' 'NEXT_ID') " + "FROM AUTO_PK_SUPPORT " + String select = "SELECT #result('NEXT_ID' 'long' 'NEXT_ID') FROM AUTO_PK_SUPPORT " + "WHERE TABLE_NAME = '" + entity.getName() + '\''; // run queries via DataNode to utilize its transactional behavior @@ -324,7 +312,7 @@ public class JdbcPkGenerator implements PkGenerator { final class PkRetrieveProcessor implements OperationObserver { Number id; - String entityName; + final String entityName; PkRetrieveProcessor(String entityName) { this.entityName = entityName; @@ -343,7 +331,6 @@ public class JdbcPkGenerator implements PkGenerator { } public void nextRows(Query query, List<?> dataRows) { - // process selected object, issue an update query if (dataRows == null || dataRows.size() == 0) { throw new CayenneRuntimeException("Error generating PK : entity not supported: " + entityName); @@ -375,12 +362,10 @@ public class JdbcPkGenerator implements PkGenerator { } public void nextQueryException(Query query, Exception ex) { - throw new CayenneRuntimeException("Error generating PK for entity '" + entityName + "'.", ex); } public void nextGlobalException(Exception ex) { - throw new CayenneRuntimeException("Error generating PK for entity: " + entityName, ex); } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/27fb5716/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2PkGenerator.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2PkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2PkGenerator.java index 188a4a2..9f5e3da 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2PkGenerator.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2PkGenerator.java @@ -18,26 +18,14 @@ ****************************************************************/ package org.apache.cayenne.dba.db2; -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.DataMap; +import org.apache.cayenne.dba.oracle.OraclePkGenerator; import org.apache.cayenne.map.DbEntity; -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - /** * A sequence-based PK generator used by {@link DB2Adapter}. */ -public class DB2PkGenerator extends JdbcPkGenerator { +public class DB2PkGenerator extends OraclePkGenerator { DB2PkGenerator(JdbcAdapter adapter) { super(adapter); @@ -45,135 +33,34 @@ public class DB2PkGenerator extends JdbcPkGenerator { private static final String _SEQUENCE_PREFIX = "S_"; - /** - * @since 3.0 - */ @Override - protected long longPkFromDatabase(DataNode node, DbEntity entity) throws Exception { - - String pkGeneratingSequenceName = sequenceName(entity); - try (Connection con = node.getDataSource().getConnection()) { - try (Statement st = con.createStatement()) { - String sql = "SELECT NEXTVAL FOR " + pkGeneratingSequenceName + " FROM SYSIBM.SYSDUMMY1"; - adapter.getJdbcEventLogger().logQuery(sql, Collections.EMPTY_LIST); - try (ResultSet rs = st.executeQuery(sql)) { - if (!rs.next()) { - throw new CayenneRuntimeException("Error generating pk for DbEntity " + entity.getName()); - } - return rs.getLong(1); - } - } - } + protected String sequenceName(DbEntity entity) { + return super.sequenceName(entity).toUpperCase(); } @Override - public void createAutoPk(DataNode node, List<DbEntity> dbEntities) throws Exception { - Collection<String> sequences = getExistingSequences(node); - for (DbEntity entity : dbEntities) { - if (!sequences.contains(sequenceName(entity))) { - this.runUpdate(node, createSequenceString(entity)); - } - } + protected String getSequencePrefix() { + return _SEQUENCE_PREFIX; } - /** - * 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 entity : dbEntities) { - list.add(createSequenceString(entity)); - } - return list; + protected String selectNextValQuery(String pkGeneratingSequenceName) { + return "SELECT NEXTVAL FOR " + pkGeneratingSequenceName + " FROM SYSIBM.SYSDUMMY1"; } - /** - * Drops PK sequences for all specified DbEntities. - */ @Override - public void dropAutoPk(DataNode node, List<DbEntity> dbEntities) throws Exception { - Collection<String> sequences = getExistingSequences(node); - - for (DbEntity ent : dbEntities) { - String name; - if (ent.getDataMap().isQuotingSQLIdentifiers()) { - DbEntity tempEnt = new DbEntity(); - DataMap dm = new DataMap(); - dm.setQuotingSQLIdentifiers(false); - tempEnt.setDataMap(dm); - tempEnt.setName(ent.getName()); - name = sequenceName(tempEnt); - } else { - name = sequenceName(ent); - } - if (sequences.contains(name)) { - runUpdate(node, dropSequenceSql(ent)); - } - } + protected String selectAllSequencesQuery() { + return "SELECT SEQNAME FROM SYSCAT.SEQUENCES WHERE SEQNAME LIKE '" + _SEQUENCE_PREFIX + "%'"; } - /** - * 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 entity : dbEntities) { - list.add(dropSequenceSql(entity)); - } - return list; - } - - /** - * Fetches a list of existing sequences that might match Cayenne generated - * ones. - */ - protected List<String> getExistingSequences(DataNode node) throws SQLException { - - // check existing sequences - - try (Connection con = node.getDataSource().getConnection()) { - try (Statement sel = con.createStatement()) { - String sql = "SELECT SEQNAME FROM SYSCAT.SEQUENCES WHERE SEQNAME LIKE '" + _SEQUENCE_PREFIX + "%'"; - adapter.getJdbcEventLogger().logQuery(sql, Collections.EMPTY_LIST); - - try (ResultSet rs = sel.executeQuery(sql)) { - List<String> sequenceList = new ArrayList<>(); - while (rs.next()) { - sequenceList.add(rs.getString(1).toUpperCase()); - } - return sequenceList; - } - } - } - } - - /** - * Returns default sequence name for DbEntity. - */ - protected String sequenceName(DbEntity entity) { - String entName = entity.getName().toUpperCase(); - String seqName = _SEQUENCE_PREFIX + entName; - - return adapter.getQuotingStrategy().quotedIdentifier(entity, entity.getCatalog(), entity.getSchema(), seqName); - } - - /** - * Returns DROP SEQUENCE statement. - */ - protected String dropSequenceSql(DbEntity entity) { + protected String dropSequenceString(DbEntity entity) { return "DROP SEQUENCE " + sequenceName(entity) + " RESTRICT "; } - /** - * Returns CREATE SEQUENCE statement for entity. - */ + @Override protected String createSequenceString(DbEntity entity) { - StringBuilder buf = new StringBuilder(); - buf.append("CREATE SEQUENCE ").append(sequenceName(entity)).append(" AS BIGINT START WITH ").append(pkStartValue) - .append(" INCREMENT BY ").append(getPkCacheSize()).append(" NO MAXVALUE ").append(" NO CYCLE ") - .append(" CACHE ").append(getPkCacheSize()); - return buf.toString(); + return "CREATE SEQUENCE " + sequenceName(entity) + " AS BIGINT START WITH " + pkStartValue + + " INCREMENT BY " + getPkCacheSize() + " NO MAXVALUE NO CYCLE CACHE " + getPkCacheSize(); } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/27fb5716/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyPkGenerator.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyPkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyPkGenerator.java index 4ed7469..e2595ce 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyPkGenerator.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyPkGenerator.java @@ -43,7 +43,7 @@ public class DerbyPkGenerator extends JdbcPkGenerator { super(adapter); } - static final String SELECT_QUERY = "SELECT NEXT_ID FROM AUTO_PK_SUPPORT" + " WHERE TABLE_NAME = ? FOR UPDATE"; + static final String SELECT_QUERY = "SELECT NEXT_ID FROM AUTO_PK_SUPPORT WHERE TABLE_NAME = ? FOR UPDATE"; /** * @since 3.0 @@ -56,13 +56,11 @@ public class DerbyPkGenerator extends JdbcPkGenerator { logger.logQuery(SELECT_QUERY, Collections.singletonList(entity.getName())); } - try (Connection c = node.getDataSource().getConnection();) { - - try (PreparedStatement select = c.prepareStatement(SELECT_QUERY, ResultSet.TYPE_FORWARD_ONLY, - ResultSet.CONCUR_UPDATABLE);) { + try (Connection c = node.getDataSource().getConnection()) { + try (PreparedStatement select = + c.prepareStatement(SELECT_QUERY, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE)) { select.setString(1, entity.getName()); - - try (ResultSet rs = select.executeQuery();) { + try (ResultSet rs = select.executeQuery()) { if (!rs.next()) { throw new CayenneException("PK lookup failed for table: " + entity.getName()); } http://git-wip-us.apache.org/repos/asf/cayenne/blob/27fb5716/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2PkGenerator.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2PkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2PkGenerator.java index 3faf0e3..9e2e4d3 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2PkGenerator.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2PkGenerator.java @@ -19,20 +19,9 @@ package org.apache.cayenne.dba.h2; -import org.apache.cayenne.CayenneRuntimeException; -import org.apache.cayenne.access.DataNode; import org.apache.cayenne.dba.JdbcAdapter; import org.apache.cayenne.dba.oracle.OraclePkGenerator; 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.Collections; -import java.util.List; /** * Default PK generator for H2 that uses sequences for PK generation. @@ -52,57 +41,12 @@ public class H2PkGenerator extends OraclePkGenerator { } @Override - protected long longPkFromDatabase(DataNode node, DbEntity entity) throws Exception { - - DbKeyGenerator pkGenerator = entity.getPrimaryKeyGenerator(); - String pkGeneratingSequenceName; - if (pkGenerator != null && DbKeyGenerator.ORACLE_TYPE.equals(pkGenerator.getGeneratorType()) - && pkGenerator.getGeneratorName() != null) { - pkGeneratingSequenceName = pkGenerator.getGeneratorName(); - } else { - pkGeneratingSequenceName = sequenceName(entity); - } - - try (Connection con = node.getDataSource().getConnection();) { - - try (Statement st = con.createStatement();) { - String sql = "SELECT NEXT VALUE FOR " + pkGeneratingSequenceName; - adapter.getJdbcEventLogger().logQuery(sql, Collections.EMPTY_LIST); - - try (ResultSet rs = st.executeQuery(sql);) { - // Object pk = null; - if (!rs.next()) { - throw new CayenneRuntimeException("Error generating pk for DbEntity " + entity.getName()); - } - return rs.getLong(1); - } - } - } + protected String selectNextValQuery(String sequenceName) { + return "SELECT NEXT VALUE FOR " + sequenceName; } - /** - * Fetches a list of existing sequences that might match Cayenne generated - * ones. - */ @Override - protected List<String> getExistingSequences(DataNode node) throws SQLException { - - // check existing sequences - - try (Connection con = node.getDataSource().getConnection();) { - - try (Statement sel = con.createStatement();) { - String sql = "SELECT LOWER(sequence_name) FROM Information_Schema.Sequences"; - adapter.getJdbcEventLogger().logQuery(sql, Collections.EMPTY_LIST); - - try (ResultSet rs = sel.executeQuery(sql);) { - List<String> sequenceList = new ArrayList<>(); - while (rs.next()) { - sequenceList.add(rs.getString(1)); - } - return sequenceList; - } - } - } + protected String selectAllSequencesQuery() { + return "SELECT LOWER(sequence_name) FROM Information_Schema.Sequences"; } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/27fb5716/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresPkGenerator.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresPkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresPkGenerator.java index 0950e90..59a1183 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresPkGenerator.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresPkGenerator.java @@ -19,20 +19,8 @@ package org.apache.cayenne.dba.ingres; -import org.apache.cayenne.CayenneRuntimeException; -import org.apache.cayenne.access.DataNode; import org.apache.cayenne.dba.JdbcAdapter; import org.apache.cayenne.dba.oracle.OraclePkGenerator; -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.Collections; -import java.util.List; /** * Ingres-specific sequence based PK generator. @@ -46,56 +34,12 @@ public class IngresPkGenerator extends OraclePkGenerator { } @Override - protected long longPkFromDatabase(DataNode node, DbEntity entity) throws Exception { - - DbKeyGenerator pkGenerator = entity.getPrimaryKeyGenerator(); - String pkGeneratingSequenceName; - if (pkGenerator != null && DbKeyGenerator.ORACLE_TYPE.equals(pkGenerator.getGeneratorType()) - && pkGenerator.getGeneratorName() != null) { - pkGeneratingSequenceName = pkGenerator.getGeneratorName(); - } else { - pkGeneratingSequenceName = sequenceName(entity); - } - - try (Connection con = node.getDataSource().getConnection();) { - - try (Statement st = con.createStatement();) { - String sql = "SELECT " + pkGeneratingSequenceName + ".nextval"; - adapter.getJdbcEventLogger().logQuery(sql, Collections.EMPTY_LIST); - - try (ResultSet rs = st.executeQuery(sql);) { - // Object pk = null; - if (!rs.next()) { - throw new CayenneRuntimeException("Error generating pk for DbEntity " + entity.getName()); - } - return rs.getLong(1); - } - } - } + protected String selectNextValQuery(String sequenceName) { + return "SELECT " + sequenceName + ".nextval"; } @Override - protected List<String> getExistingSequences(DataNode node) throws SQLException { - - // check existing sequences - - try (Connection connection = node.getDataSource().getConnection();) { - - try (Statement select = connection.createStatement();) { - String sql = "select seq_name from iisequences where seq_owner != 'DBA'"; - adapter.getJdbcEventLogger().logQuery(sql, Collections.EMPTY_LIST); - - try (ResultSet rs = select.executeQuery(sql);) { - List<String> sequenceList = new ArrayList<>(); - while (rs.next()) { - String name = rs.getString(1); - if (name != null) { - sequenceList.add(name.trim()); - } - } - return sequenceList; - } - } - } + protected String selectAllSequencesQuery() { + return "SELECT seq_name FROM iisequences WHERE seq_owner != 'DBA'"; } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/27fb5716/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLPkGenerator.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLPkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLPkGenerator.java index 180a4c2..9e30749 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLPkGenerator.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLPkGenerator.java @@ -38,11 +38,6 @@ public class MySQLPkGenerator extends JdbcPkGenerator { super(adapter); } - @Override - protected String dropAutoPkString() { - return "DROP TABLE IF EXISTS AUTO_PK_SUPPORT"; - } - /** * Overrides superclass's implementation to perform locking of the primary * key lookup table. @@ -58,50 +53,39 @@ public class MySQLPkGenerator extends JdbcPkGenerator { // chained SQL exception SQLException exception = null; - long pk = -1l; + long pk = -1L; - try (Connection con = node.getDataSource().getConnection();) { + try (Connection con = node.getDataSource().getConnection()) { if (con.getAutoCommit()) { con.setAutoCommit(false); } - Statement st = con.createStatement(); - - try { - pk = getLongPrimaryKey(st, entity.getName()); - con.commit(); - } catch (SQLException pkEx) { - + try(Statement st = con.createStatement()) { try { - con.rollback(); - } catch (SQLException e) { - - } + pk = getLongPrimaryKey(st, entity.getName()); + con.commit(); + } catch (SQLException pkEx) { + try { + con.rollback(); + } catch (SQLException ignored) { + } - exception = processSQLException(pkEx, exception); - } finally { - // UNLOCK! - // THIS MUST BE EXECUTED NO MATTER WHAT, OR WE WILL LOCK THE - // PRIMARY KEY - // TABLE!! - try { - String unlockString = "UNLOCK TABLES"; - adapter.getJdbcEventLogger().logQuery(unlockString, Collections.EMPTY_LIST); - st.execute(unlockString); - } catch (SQLException unlockEx) { - exception = processSQLException(unlockEx, exception); + exception = processSQLException(pkEx, null); } finally { - // close statement + // UNLOCK! + // THIS MUST BE EXECUTED NO MATTER WHAT, OR WE WILL LOCK THE PRIMARY KEY TABLE!! try { - st.close(); - } catch (SQLException stClosingEx) { - // ignoring... + String unlockString = "UNLOCK TABLES"; + adapter.getJdbcEventLogger().logQuery(unlockString, Collections.EMPTY_LIST); + st.execute(unlockString); + } catch (SQLException unlockEx) { + exception = processSQLException(unlockEx, exception); } } } } catch (SQLException otherEx) { - exception = processSQLException(otherEx, exception); + exception = processSQLException(otherEx, null); } // check errors @@ -127,12 +111,14 @@ public class MySQLPkGenerator extends JdbcPkGenerator { } @Override - protected String pkTableCreateString() { - StringBuilder buf = new StringBuilder(); - buf.append("CREATE TABLE IF NOT EXISTS AUTO_PK_SUPPORT (").append(" TABLE_NAME CHAR(100) NOT NULL,") - .append(" NEXT_ID BIGINT NOT NULL, UNIQUE (TABLE_NAME)").append(")"); + protected String dropAutoPkString() { + return "DROP TABLE IF EXISTS AUTO_PK_SUPPORT"; + } - return buf.toString(); + @Override + protected String pkTableCreateString() { + return "CREATE TABLE IF NOT EXISTS AUTO_PK_SUPPORT " + + "(TABLE_NAME CHAR(100) NOT NULL, NEXT_ID BIGINT NOT NULL, UNIQUE (TABLE_NAME))"; } /** @@ -145,27 +131,18 @@ public class MySQLPkGenerator extends JdbcPkGenerator { statement.execute(lockString); // select - String selectString = super.pkSelectString(entityName); adapter.getJdbcEventLogger().logQuery(selectString, Collections.EMPTY_LIST); - ResultSet rs = statement.executeQuery(selectString); - long pk = -1; - try { + long pk; + try(ResultSet rs = statement.executeQuery(selectString)) { if (!rs.next()) { throw new SQLException("No rows for '" + entityName + "'"); } pk = rs.getLong(1); - if (rs.next()) { throw new SQLException("More than one row for '" + entityName + "'"); } - } finally { - try { - rs.close(); - } catch (Exception ex) { - // ignoring... - } } // update http://git-wip-us.apache.org/repos/asf/cayenne/blob/27fb5716/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OraclePkGenerator.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OraclePkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OraclePkGenerator.java index 8cc9c7b..e059a74 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OraclePkGenerator.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OraclePkGenerator.java @@ -33,7 +33,6 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; import java.util.List; /** @@ -61,71 +60,70 @@ public class OraclePkGenerator extends JdbcPkGenerator { private static final String _SEQUENCE_PREFIX = "pk_"; @Override - public void createAutoPk(DataNode node, List dbEntities) throws Exception { - List sequences = getExistingSequences(node); - + public void createAutoPk(DataNode node, List<DbEntity> dbEntities) throws Exception { + List<String> sequences = getExistingSequences(node); // create needed sequences - Iterator it = dbEntities.iterator(); - while (it.hasNext()) { - DbEntity ent = (DbEntity) it.next(); - if (!sequences.contains(sequenceName(ent))) { - runUpdate(node, createSequenceString(ent)); + 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 createAutoPkStatements(List dbEntities) { - List<String> list = new ArrayList<>(); - Iterator it = dbEntities.iterator(); - while (it.hasNext()) { - DbEntity ent = (DbEntity) it.next(); - list.add(createSequenceString(ent)); + 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 dbEntities) throws Exception { - List sequences = getExistingSequences(node); + public void dropAutoPk(DataNode node, List<DbEntity> dbEntities) throws Exception { + List<String> sequences = getExistingSequences(node); // drop obsolete sequences - Iterator it = dbEntities.iterator(); - while (it.hasNext()) { - DbEntity ent = (DbEntity) it.next(); + for (DbEntity dbEntity : dbEntities) { String name; - if (ent.getDataMap().isQuotingSQLIdentifiers()) { + if (dbEntity.getDataMap().isQuotingSQLIdentifiers()) { DbEntity tempEnt = new DbEntity(); DataMap dm = new DataMap(); dm.setQuotingSQLIdentifiers(false); tempEnt.setDataMap(dm); - tempEnt.setName(ent.getName()); + tempEnt.setName(dbEntity.getName()); name = stripSchemaName(sequenceName(tempEnt)); } else { - name = stripSchemaName(sequenceName(ent)); + name = stripSchemaName(sequenceName(dbEntity)); } if (sequences.contains(name)) { - runUpdate(node, dropSequenceString(ent)); + runUpdate(node, dropSequenceString(dbEntity)); } } } + /** + * Creates a list of DROP SEQUENCE statements for the list of DbEntities. + */ @Override - public List dropAutoPkStatements(List dbEntities) { - List<String> list = new ArrayList<>(); - Iterator it = dbEntities.iterator(); - while (it.hasNext()) { - DbEntity ent = (DbEntity) it.next(); - list.add(dropSequenceString(ent)); + 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) { - return "CREATE SEQUENCE " + sequenceName(ent) + " START WITH " + pkStartValue + " INCREMENT BY " - + pkCacheSize(ent); + return "CREATE SEQUENCE " + sequenceName(ent) + " START WITH " + pkStartValue + " INCREMENT BY " + pkCacheSize(ent); } /** @@ -133,10 +131,17 @@ public class OraclePkGenerator extends JdbcPkGenerator { * automatic primary key generation process for a specific DbEntity. */ protected String dropSequenceString(DbEntity ent) { - return "DROP SEQUENCE " + sequenceName(ent); } + protected String selectNextValQuery(String pkGeneratingSequenceName) { + return "SELECT " + pkGeneratingSequenceName + ".nextval FROM DUAL"; + } + + 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: @@ -159,14 +164,12 @@ public class OraclePkGenerator extends JdbcPkGenerator { pkGeneratingSequenceName = sequenceName(entity); } - try (Connection con = node.getDataSource().getConnection();) { - - try (Statement st = con.createStatement();) { - String sql = "SELECT " + pkGeneratingSequenceName + ".nextval FROM DUAL"; + try (Connection con = node.getDataSource().getConnection()) { + try (Statement st = con.createStatement()) { + String sql = selectNextValQuery(pkGeneratingSequenceName); adapter.getJdbcEventLogger().logQuery(sql, Collections.EMPTY_LIST); - try (ResultSet rs = st.executeQuery(sql);) { - // Object pk = null; + try (ResultSet rs = st.executeQuery(sql)) { if (!rs.next()) { throw new CayenneRuntimeException("Error generating pk for DbEntity " + entity.getName()); } @@ -183,13 +186,15 @@ public class OraclePkGenerator extends JdbcPkGenerator { && keyGenerator.getGeneratorName() != null) { Integer size = keyGenerator.getKeyCacheSize(); - return (size != null && size.intValue() >= 1) ? size.intValue() : super.getPkCacheSize(); + return (size != null && size >= 1) ? size : super.getPkCacheSize(); } else { return super.getPkCacheSize(); } } - /** Returns expected primary key sequence name for a DbEntity. */ + /** + * Returns expected primary key sequence name for a DbEntity. + */ protected String sequenceName(DbEntity entity) { // use custom generator if possible @@ -199,15 +204,16 @@ public class OraclePkGenerator extends JdbcPkGenerator { return keyGenerator.getGeneratorName().toLowerCase(); } else { - String entName = entity.getName(); - String seqName = _SEQUENCE_PREFIX + entName.toLowerCase(); - - return adapter.getQuotingStrategy().quotedIdentifier(entity, entity.getCatalog(), entity.getSchema(), - seqName); + String seqName = getSequencePrefix() + entity.getName().toLowerCase(); + return adapter.getQuotingStrategy().quotedIdentifier(entity, entity.getCatalog(), entity.getSchema(), seqName); } } - protected String stripSchemaName(String sequenceName) { + protected String getSequencePrefix() { + return _SEQUENCE_PREFIX; + } + + private String stripSchemaName(String sequenceName) { int ind = sequenceName.indexOf('.'); return ind >= 0 ? sequenceName.substring(ind + 1) : sequenceName; } @@ -216,20 +222,21 @@ public class OraclePkGenerator extends JdbcPkGenerator { * Fetches a list of existing sequences that might match Cayenne generated * ones. */ - protected List getExistingSequences(DataNode node) throws SQLException { + protected List<String> getExistingSequences(DataNode node) throws SQLException { // check existing sequences - - try (Connection con = node.getDataSource().getConnection();) { - - try (Statement sel = con.createStatement();) { - String sql = "SELECT LOWER(SEQUENCE_NAME) FROM ALL_SEQUENCES"; + try (Connection con = node.getDataSource().getConnection()) { + try (Statement sel = con.createStatement()) { + String sql = selectAllSequencesQuery(); adapter.getJdbcEventLogger().logQuery(sql, Collections.EMPTY_LIST); - try (ResultSet rs = sel.executeQuery(sql);) { + try (ResultSet rs = sel.executeQuery(sql)) { List<String> sequenceList = new ArrayList<>(); while (rs.next()) { - sequenceList.add(rs.getString(1)); + String name = rs.getString(1); + if (name != null) { + sequenceList.add(name.trim()); + } } return sequenceList; } http://git-wip-us.apache.org/repos/asf/cayenne/blob/27fb5716/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresPkGenerator.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresPkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresPkGenerator.java index 877fc33..4b5bb1e 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresPkGenerator.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresPkGenerator.java @@ -19,20 +19,9 @@ package org.apache.cayenne.dba.postgres; -import org.apache.cayenne.CayenneRuntimeException; -import org.apache.cayenne.access.DataNode; import org.apache.cayenne.dba.JdbcAdapter; import org.apache.cayenne.dba.oracle.OraclePkGenerator; 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.Collections; -import java.util.List; /** * Default PK generator for PostgreSQL that uses sequences for PK generation. @@ -45,69 +34,19 @@ public class PostgresPkGenerator extends OraclePkGenerator { @Override protected String createSequenceString(DbEntity ent) { - // note that PostgreSQL 7.4 and newer supports INCREMENT BY and START - // WITH + // note that PostgreSQL 7.4 and newer supports INCREMENT BY and START WITH // however 7.3 doesn't like BY and WITH, so using older more neutral - // syntax - // that works with all tested versions. + // syntax that works with all tested versions. return "CREATE SEQUENCE " + sequenceName(ent) + " INCREMENT " + pkCacheSize(ent) + " START " + pkStartValue; } - /** - * @since 3.0 - */ @Override - protected long longPkFromDatabase(DataNode node, DbEntity entity) throws Exception { - - DbKeyGenerator pkGenerator = entity.getPrimaryKeyGenerator(); - String pkGeneratingSequenceName; - if (pkGenerator != null && DbKeyGenerator.ORACLE_TYPE.equals(pkGenerator.getGeneratorType()) - && pkGenerator.getGeneratorName() != null) { - pkGeneratingSequenceName = pkGenerator.getGeneratorName(); - } else { - pkGeneratingSequenceName = sequenceName(entity); - } - - try (Connection con = node.getDataSource().getConnection();) { - - try (Statement st = con.createStatement();) { - String sql = "SELECT nextval('" + pkGeneratingSequenceName + "')"; - adapter.getJdbcEventLogger().logQuery(sql, Collections.EMPTY_LIST); - - try (ResultSet rs = st.executeQuery(sql);) { - // Object pk = null; - if (!rs.next()) { - throw new CayenneRuntimeException("Error generating pk for DbEntity " + entity.getName()); - } - return rs.getLong(1); - } - } - } + protected String selectNextValQuery(String sequenceName) { + return "SELECT nextval('" + sequenceName + "')"; } - /** - * Fetches a list of existing sequences that might match Cayenne generated - * ones. - */ @Override - protected List<String> getExistingSequences(DataNode node) throws SQLException { - - // check existing sequences - - try (Connection con = node.getDataSource().getConnection();) { - - try (Statement sel = con.createStatement();) { - String sql = "SELECT relname FROM pg_class WHERE relkind='S'"; - adapter.getJdbcEventLogger().logQuery(sql, Collections.EMPTY_LIST); - - try (ResultSet rs = sel.executeQuery(sql);) { - List<String> sequenceList = new ArrayList<>(); - while (rs.next()) { - sequenceList.add(rs.getString(1)); - } - return sequenceList; - } - } - } + protected String selectAllSequencesQuery() { + return "SELECT relname FROM pg_class WHERE relkind='S'"; } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/27fb5716/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybasePkGenerator.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybasePkGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybasePkGenerator.java index e08a099..9c24f1a 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybasePkGenerator.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybasePkGenerator.java @@ -46,7 +46,7 @@ public class SybasePkGenerator extends JdbcPkGenerator { @Override protected String pkTableCreateString() { - return "CREATE TABLE AUTO_PK_SUPPORT ( TABLE_NAME CHAR(100) NOT NULL, NEXT_ID DECIMAL(19,0) NOT NULL, PRIMARY KEY(TABLE_NAME))"; + return "CREATE TABLE AUTO_PK_SUPPORT (TABLE_NAME CHAR(100) NOT NULL, NEXT_ID DECIMAL(19,0) NOT NULL, PRIMARY KEY(TABLE_NAME))"; } /** @@ -149,47 +149,34 @@ public class SybasePkGenerator extends JdbcPkGenerator { @Override protected long longPkFromDatabase(DataNode node, DbEntity entity) throws Exception { // handle CAY-588 - get connection that is separate from the connection - // in the - // current transaction. + // in the current transaction. // TODO (andrus, 7/6/2006) Note that this will still work in a pool with - // a single - // connection, as PK generator is invoked early in the transaction, - // before the - // connection is grabbed for commit... So maybe promote this to other - // adapters in - // 3.0? + // a single connection, as PK generator is invoked early in the transaction, + // before the connection is grabbed for commit... + // So maybe promote this to other adapters in 3.0? Transaction transaction = BaseTransaction.getThreadTransaction(); BaseTransaction.bindThreadTransaction(null); - try { - - try (Connection connection = node.getDataSource().getConnection();) { - - try (CallableStatement statement = connection.prepareCall("{call auto_pk_for_table(?, ?)}");) { - statement.setString(1, entity.getName()); - statement.setInt(2, super.getPkCacheSize()); - - // can't use "executeQuery" - // per - // http://jtds.sourceforge.net/faq.html#expectingResultSet - statement.execute(); - if (statement.getMoreResults()) { - - try (ResultSet rs = statement.getResultSet();) { - if (rs.next()) { - return rs.getLong(1); - } else { - throw new CayenneRuntimeException("Error generating pk for DbEntity " - + entity.getName()); - } + try (Connection connection = node.getDataSource().getConnection()) { + try (CallableStatement statement = connection.prepareCall("{call auto_pk_for_table(?, ?)}")) { + statement.setString(1, entity.getName()); + statement.setInt(2, super.getPkCacheSize()); + + // can't use "executeQuery" per http://jtds.sourceforge.net/faq.html#expectingResultSet + statement.execute(); + if (statement.getMoreResults()) { + try (ResultSet rs = statement.getResultSet()) { + if (rs.next()) { + return rs.getLong(1); + } else { + throw new CayenneRuntimeException("Error generating pk for DbEntity " + entity.getName()); } - - } else { - throw new CayenneRuntimeException("Error generating pk for DbEntity " + entity.getName() - + ", no result set from stored procedure."); } + } else { + throw new CayenneRuntimeException("Error generating pk for DbEntity " + entity.getName() + + ", no result set from stored procedure."); } } } finally { @@ -198,11 +185,8 @@ public class SybasePkGenerator extends JdbcPkGenerator { } private String safePkTableDrop() { - StringBuilder buf = new StringBuilder(); - buf.append("if exists (SELECT * FROM sysobjects WHERE name = 'AUTO_PK_SUPPORT')").append(" BEGIN ") - .append(" DROP TABLE AUTO_PK_SUPPORT").append(" END"); - - return buf.toString(); + return "if exists (SELECT * FROM sysobjects WHERE name = 'AUTO_PK_SUPPORT') BEGIN " + + " DROP TABLE AUTO_PK_SUPPORT END"; } private String unsafePkProcCreate() { http://git-wip-us.apache.org/repos/asf/cayenne/blob/27fb5716/cayenne-server/src/main/java/org/apache/cayenne/tx/CayenneTransaction.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/tx/CayenneTransaction.java b/cayenne-server/src/main/java/org/apache/cayenne/tx/CayenneTransaction.java index f0ab5d8..dba12d9 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/tx/CayenneTransaction.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/tx/CayenneTransaction.java @@ -24,7 +24,6 @@ import org.apache.cayenne.log.JdbcEventLogger; import java.sql.Connection; import java.sql.SQLException; -import java.util.Iterator; /** * Represents a Cayenne-managed local Transaction. @@ -74,40 +73,36 @@ public class CayenneTransaction extends BaseTransaction { protected void processCommit() { status = BaseTransaction.STATUS_COMMITTING; - if (connections != null && connections.size() > 0) { - Throwable deferredException = null; - Iterator<?> it = connections.values().iterator(); - while (it.hasNext()) { - Connection connection = (Connection) it.next(); - try { - - if (deferredException == null) { - connection.commit(); - } else { - // we must do a partial rollback if only to cleanup - // uncommitted - // connections. - connection.rollback(); - } - - } catch (Throwable th) { - // there is no such thing as "partial" rollback in real - // transactions, so we can't set any meaningful status. - // status = ?; - setRollbackOnly(); - - // stores last exception - // TODO: chain exceptions... - deferredException = th; + if (connections == null || connections.isEmpty()) { + return; + } + + Throwable deferredException = null; + for (Connection connection : connections.values()) { + try { + if (deferredException == null) { + connection.commit(); + } else { + // we must do a partial rollback if only to cleanup uncommitted connections. + connection.rollback(); } + } catch (Throwable th) { + // there is no such thing as "partial" rollback in real + // transactions, so we can't set any meaningful status. + // status = ?; + setRollbackOnly(); + + // stores last exception + // TODO: chain exceptions... + deferredException = th; } + } - if (deferredException != null) { - logger.logRollbackTransaction("transaction rolledback."); - throw new CayenneRuntimeException(deferredException); - } else { - logger.logCommitTransaction("transaction committed."); - } + if (deferredException != null) { + logger.logRollbackTransaction("transaction rolledback."); + throw new CayenneRuntimeException(deferredException); + } else { + logger.logCommitTransaction("transaction committed."); } } @@ -115,27 +110,25 @@ public class CayenneTransaction extends BaseTransaction { protected void processRollback() { status = BaseTransaction.STATUS_ROLLING_BACK; - if (connections != null && connections.size() > 0) { - Throwable deferredException = null; - - Iterator<?> it = connections.values().iterator(); - while (it.hasNext()) { - Connection connection = (Connection) it.next(); + if (connections == null || connections.isEmpty()) { + return; + } - try { - // continue with rollback even if an exception was thrown - // before - connection.rollback(); - } catch (Throwable th) { - // stores last exception - // TODO: chain exceptions... - deferredException = th; - } + Throwable deferredException = null; + for (Connection connection : connections.values()) { + try { + // continue with rollback even if an exception was thrown + // before + connection.rollback(); + } catch (Throwable th) { + // stores last exception + // TODO: chain exceptions... + deferredException = th; } + } - if (deferredException != null) { - throw new CayenneRuntimeException(deferredException); - } + if (deferredException != null) { + throw new CayenneRuntimeException(deferredException); } } }