Author: tv
Date: Sun Jan 6 18:46:35 2019
New Revision: 1850586
URL: http://svn.apache.org/viewvc?rev=1850586&view=rev
Log:
TORQUE-357: Add feature to use JDBC-3.0-Statement.getGeneratedKeys() if the
driver supports it.
Modified:
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/TorqueInstance.java
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/adapter/AbstractAdapter.java
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/adapter/Adapter.java
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/adapter/AdapterFactory.java
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/AbstractIdGenerator.java
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/AutoIncrementIdGenerator.java
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/IDBroker.java
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/IDGeneratorFactory.java
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/IdGenerator.java
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/SequenceIdGenerator.java
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/util/BasePeerImpl.java
db/torque/torque4/trunk/torque-runtime/src/test/java/org/apache/torque/util/BasePeerImplTest.java
Modified:
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/TorqueInstance.java
URL:
http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/TorqueInstance.java?rev=1850586&r1=1850585&r2=1850586&view=diff
==============================================================================
---
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/TorqueInstance.java
(original)
+++
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/TorqueInstance.java
Sun Jan 6 18:46:35 2019
@@ -372,6 +372,17 @@ public class TorqueInstance
log.debug("Adding " + adapterKey + " -> "
+ handle + " as Adapter");
+ // try to get additional meta data from the driver
+ try (Connection con = database.getDataSourceFactory()
+ .getDataSource().getConnection())
+ {
+ AdapterFactory.setCapabilities(con, adapter);
+ }
+ catch (SQLException e)
+ {
+ log.debug("Could not get database meta data from
JDBC");
+ }
+
// add Id generators
for (IDMethod idMethod :
IDGeneratorFactory.ID_GENERATOR_METHODS)
{
Modified:
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/adapter/AbstractAdapter.java
URL:
http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/adapter/AbstractAdapter.java?rev=1850586&r1=1850585&r2=1850586&view=diff
==============================================================================
---
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/adapter/AbstractAdapter.java
(original)
+++
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/adapter/AbstractAdapter.java
Sun Jan 6 18:46:35 2019
@@ -20,6 +20,7 @@ package org.apache.torque.adapter;
*/
import java.sql.Connection;
+import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import org.apache.torque.TorqueException;
@@ -51,6 +52,9 @@ public abstract class AbstractAdapter im
/** Serial version UID. */
private static final long serialVersionUID = 1L;
+ /** A flag to determine whether Statement#getGeneratedKeys() should be
used. */
+ private boolean useGetGeneratedKeys = false;
+
/**
* Empty constructor.
*/
@@ -280,4 +284,26 @@ public abstract class AbstractAdapter im
{
return false;
}
+
+ /**
+ * whether Statement#getGeneratedKeys() should be used.
+ *
+ * @return a <code>boolean</code> value
+ */
+ public boolean useGetGeneratedKeys()
+ {
+ return this.useGetGeneratedKeys;
+ }
+
+ /**
+ * Update static capabilities of the adapter with actual
+ * readings based on the JDBC meta-data
+ *
+ * @param dmd database meta data
+ * @throws SQLException if there are problems getting the JDBC meta data
+ */
+ public void setCapabilities(DatabaseMetaData dmd) throws SQLException
+ {
+ this.useGetGeneratedKeys = dmd.supportsGetGeneratedKeys();
+ }
}
Modified:
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/adapter/Adapter.java
URL:
http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/adapter/Adapter.java?rev=1850586&r1=1850585&r2=1850586&view=diff
==============================================================================
---
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/adapter/Adapter.java
(original)
+++
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/adapter/Adapter.java
Sun Jan 6 18:46:35 2019
@@ -21,6 +21,7 @@ package org.apache.torque.adapter;
import java.io.Serializable;
import java.sql.Connection;
+import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import org.apache.torque.TorqueException;
@@ -226,4 +227,20 @@ public interface Adapter extends Seriali
* @return whether to use the MINUS operator instead of the EXCEPT
operator.
*/
boolean useMinusForExcept();
+
+ /**
+ * whether Statement#getGeneratedKeys() should be used.
+ *
+ * @return a <code>boolean</code> value
+ */
+ boolean useGetGeneratedKeys();
+
+ /**
+ * Update static capabilities of the adapter with actual
+ * readings based on the JDBC meta-data
+ *
+ * @param dmd database meta data
+ * @throws SQLException if there are problems getting the JDBC meta data
+ */
+ void setCapabilities(DatabaseMetaData dmd) throws SQLException;
}
Modified:
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/adapter/AdapterFactory.java
URL:
http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/adapter/AdapterFactory.java?rev=1850586&r1=1850585&r2=1850586&view=diff
==============================================================================
---
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/adapter/AdapterFactory.java
(original)
+++
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/adapter/AdapterFactory.java
Sun Jan 6 18:46:35 2019
@@ -128,6 +128,21 @@ public final class AdapterFactory
}
/**
+ * Update static capabilities of the Torque database adapter with actual
+ * readings based on the JDBC meta-data
+ *
+ * @param con a database connection
+ * @param adapter an adapter
+ * @throws SQLException if there are problems getting the JDBC meta data
+ */
+ public static void setCapabilities(Connection con, Adapter adapter)
+ throws SQLException
+ {
+ DatabaseMetaData dmd = con.getMetaData();
+ adapter.setCapabilities(dmd);
+ }
+
+ /**
* Creates a new instance of the Torque database adapter associated
* with the specified JDBC driver or adapter key.
*
Modified:
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/AbstractIdGenerator.java
URL:
http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/AbstractIdGenerator.java?rev=1850586&r1=1850585&r2=1850586&view=diff
==============================================================================
---
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/AbstractIdGenerator.java
(original)
+++
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/AbstractIdGenerator.java
Sun Jan 6 18:46:35 2019
@@ -21,6 +21,9 @@ package org.apache.torque.oid;
import java.math.BigDecimal;
import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
import java.util.List;
import org.apache.torque.TorqueException;
@@ -158,6 +161,15 @@ public abstract class AbstractIdGenerato
public abstract boolean isConnectionRequired();
/**
+ * A flag to determine whether Statement#getGeneratedKeys()
+ * should be used.
+ *
+ * @return a <code>boolean</code> value
+ */
+ @Override
+ public abstract boolean isGetGeneratedKeysSupported();
+
+ /**
* Returns the last ID used by this connection.
*
* @param connection A Connection.
@@ -174,11 +186,32 @@ public abstract class AbstractIdGenerato
final RecordMapper<T> mapper)
throws TorqueException
{
- String idSql = getIdSql(keyInfo);
-
- BasePeerImpl<T> peer = new BasePeerImpl<>(mapper, null, databaseName);
- List<T> result = peer.doSelect(idSql, connection);
- return result.get(0);
+ if (isGetGeneratedKeysSupported() && keyInfo instanceof Statement)
+ {
+ try (ResultSet generatedKeys = ((Statement)
keyInfo).getGeneratedKeys())
+ {
+ if (generatedKeys.next())
+ {
+ return mapper.processRow(generatedKeys, 0, null);
+ }
+ else
+ {
+ throw new SQLException("Could not obtain ID from
statement, result set is empty");
+ }
+ }
+ catch (SQLException e)
+ {
+ throw new TorqueException("Error getting ID", e);
+ }
+ }
+ else
+ {
+ String idSql = getIdSql(keyInfo);
+
+ BasePeerImpl<T> peer = new BasePeerImpl<>(mapper, null,
databaseName);
+ List<T> result = peer.doSelect(idSql, connection);
+ return result.get(0);
+ }
}
/**
Modified:
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/AutoIncrementIdGenerator.java
URL:
http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/AutoIncrementIdGenerator.java?rev=1850586&r1=1850585&r2=1850586&view=diff
==============================================================================
---
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/AutoIncrementIdGenerator.java
(original)
+++
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/AutoIncrementIdGenerator.java
Sun Jan 6 18:46:35 2019
@@ -78,4 +78,16 @@ public class AutoIncrementIdGenerator ex
{
return true;
}
+
+ /**
+ * A flag to determine whether Statement#getGeneratedKeys()
+ * should be used.
+ *
+ * @return a <code>boolean</code> value
+ */
+ @Override
+ public boolean isGetGeneratedKeysSupported()
+ {
+ return adapter.useGetGeneratedKeys();
+ }
}
Modified:
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/IDBroker.java
URL:
http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/IDBroker.java?rev=1850586&r1=1850585&r2=1850586&view=diff
==============================================================================
---
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/IDBroker.java
(original)
+++
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/IDBroker.java
Sun Jan 6 18:46:35 2019
@@ -374,6 +374,18 @@ public class IDBroker implements Runnabl
}
/**
+ * A flag to determine whether Statement#getGeneratedKeys()
+ * should be used.
+ *
+ * @return a <code>boolean</code> value
+ */
+ @Override
+ public boolean isGetGeneratedKeysSupported()
+ {
+ return false;
+ }
+
+ /**
* Returns whether the idbroker thread is running.
*
* @return true if the thread is running, false otherwise.
Modified:
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/IDGeneratorFactory.java
URL:
http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/IDGeneratorFactory.java?rev=1850586&r1=1850585&r2=1850586&view=diff
==============================================================================
---
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/IDGeneratorFactory.java
(original)
+++
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/IDGeneratorFactory.java
Sun Jan 6 18:46:35 2019
@@ -19,9 +19,10 @@ package org.apache.torque.oid;
* under the License.
*/
-import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import org.apache.torque.adapter.Adapter;
import org.apache.torque.adapter.IDMethod;
@@ -39,16 +40,12 @@ public final class IDGeneratorFactory
* The list of ID generation method types which have associated
* {@link org.apache.torque.oid.IdGenerator} implementations.
*/
- public static final List<IDMethod> ID_GENERATOR_METHODS;
-
- static
- {
- List<IDMethod> idGeneratorMethods = new ArrayList<>();
- idGeneratorMethods.add(IDMethod.NATIVE);
- idGeneratorMethods.add(IDMethod.AUTO_INCREMENT);
- idGeneratorMethods.add(IDMethod.SEQUENCE);
- ID_GENERATOR_METHODS =
Collections.unmodifiableList(idGeneratorMethods);
- }
+ public static final List<IDMethod> ID_GENERATOR_METHODS =
+ Collections.unmodifiableList(Stream.of(
+ IDMethod.NATIVE,
+ IDMethod.AUTO_INCREMENT,
+ IDMethod.SEQUENCE
+ ).collect(Collectors.toList()));
/**
* Private constructor to prevent initialisation.
@@ -74,18 +71,16 @@ public final class IDGeneratorFactory
*/
public static IdGenerator create(Adapter adapter, String name)
{
- IDMethod idMethod = adapter.getIDMethodType();
- if (IDMethod.AUTO_INCREMENT == idMethod)
- {
- return new AutoIncrementIdGenerator(adapter, name);
- }
- else if (IDMethod.SEQUENCE == idMethod)
+ switch (adapter.getIDMethodType())
{
- return new SequenceIdGenerator(adapter, name);
- }
- else
- {
- return null;
+ case AUTO_INCREMENT:
+ return new AutoIncrementIdGenerator(adapter, name);
+
+ case SEQUENCE:
+ return new SequenceIdGenerator(adapter, name);
+
+ default:
+ return null;
}
}
}
Modified:
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/IdGenerator.java
URL:
http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/IdGenerator.java?rev=1850586&r1=1850585&r2=1850586&view=diff
==============================================================================
---
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/IdGenerator.java
(original)
+++
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/IdGenerator.java
Sun Jan 6 18:46:35 2019
@@ -113,4 +113,12 @@ public interface IdGenerator
* @return a <code>boolean</code> value
*/
boolean isConnectionRequired();
+
+ /**
+ * A flag to determine whether Statement#getGeneratedKeys()
+ * should be used.
+ *
+ * @return a <code>boolean</code> value
+ */
+ boolean isGetGeneratedKeysSupported();
}
Modified:
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/SequenceIdGenerator.java
URL:
http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/SequenceIdGenerator.java?rev=1850586&r1=1850585&r2=1850586&view=diff
==============================================================================
---
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/SequenceIdGenerator.java
(original)
+++
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/oid/SequenceIdGenerator.java
Sun Jan 6 18:46:35 2019
@@ -75,4 +75,16 @@ public class SequenceIdGenerator extends
{
return true;
}
+
+ /**
+ * A flag to determine whether Statement#getGeneratedKeys()
+ * should be used.
+ *
+ * @return a <code>boolean</code> value
+ */
+ @Override
+ public boolean isGetGeneratedKeysSupported()
+ {
+ return false;
+ }
}
Modified:
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/util/BasePeerImpl.java
URL:
http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/util/BasePeerImpl.java?rev=1850586&r1=1850585&r2=1850586&view=diff
==============================================================================
---
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/util/BasePeerImpl.java
(original)
+++
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/util/BasePeerImpl.java
Sun Jan 6 18:46:35 2019
@@ -391,8 +391,7 @@ public class BasePeerImpl<T> implements
// primaryKey will be null if there is no primary key
// defined for the table we're inserting into.
if (keyGen.isPriorToInsert() && primaryKey != null
- && !insertValues.containsKey(
- primaryKey))
+ && !insertValues.containsKey(primaryKey))
{
id = getId(primaryKey, keyGen, connection, keyInfo);
insertValues.put(
@@ -401,21 +400,20 @@ public class BasePeerImpl<T> implements
}
}
- List<String> columnNames = new ArrayList<>();
- insertValues.keySet().forEach((column) ->
columnNames.add(column.getColumnName()));
+ String columnNamesList = insertValues.keySet().stream()
+ .map((column) -> column.getColumnName())
+ .collect(Collectors.joining(",", "(", ")"));
String fullTableName = SqlBuilder.getFullTableName(
getTableMap().getFullyQualifiedTableName(),
databaseNameFromInsertValues);
StringBuilder query = new StringBuilder("INSERT INTO ")
.append(fullTableName)
- .append("(")
- .append(StringUtils.join(columnNames, ","))
- .append(") VALUES (");
+ .append(columnNamesList)
+ .append(" VALUES (");
boolean first = true;
- List<JdbcTypedValue> replacementObjects
- = new ArrayList<>();
+ List<JdbcTypedValue> replacementObjects = new ArrayList<>();
for (Map.Entry<Column, JdbcTypedValue> columnValue
: insertValues.entrySet())
{
@@ -430,15 +428,21 @@ public class BasePeerImpl<T> implements
}
else
{
- Column sqlExpression
- = columnValue.getValue().getSqlExpression();
+ Column sqlExpression =
columnValue.getValue().getSqlExpression();
query.append(sqlExpression.getSqlExpression());
}
first = false;
}
query.append(")");
- try (PreparedStatement preparedStatement =
connection.prepareStatement(query.toString()))
+ boolean useGetGeneratedKeys = keyGen != null
+ && keyGen.isGetGeneratedKeysSupported()
+ && primaryKey != null && !insertValues.containsKey(primaryKey);
+
+ try (PreparedStatement preparedStatement = useGetGeneratedKeys ?
+ connection.prepareStatement(query.toString(),
+ Statement.RETURN_GENERATED_KEYS) :
+ connection.prepareStatement(query.toString()))
{
int position = 1;
for (JdbcTypedValue replacementObject : replacementObjects)
@@ -477,22 +481,30 @@ public class BasePeerImpl<T> implements
stopWatch.start();
preparedStatement.executeUpdate();
log.trace("Insert took " + stopWatch.getTime() + " milliseconds");
+
+ if (keyGen != null && keyGen.isPostInsert()
+ && primaryKey != null
+ && !insertValues.containsKey(primaryKey))
+ {
+ if (keyGen.isGetGeneratedKeysSupported())
+ {
+ // If the id-generator supports getGeneratedKeys(), get id
+ // now.
+ id = getId(primaryKey, keyGen, connection,
preparedStatement);
+ }
+ else
+ {
+ // If the primary key column is auto-incremented, get the
id
+ // now.
+ id = getId(primaryKey, keyGen, connection, keyInfo);
+ }
+ }
}
catch (SQLException e)
{
throw ExceptionMapper.getInstance().toTorqueException(e);
}
- // If the primary key column is auto-incremented, get the id
- // now.
- if (keyGen != null && keyGen.isPostInsert()
- && primaryKey != null
- && !insertValues.containsKey(
- primaryKey))
- {
- id = getId(primaryKey, keyGen, connection, keyInfo);
- }
-
return id;
}
Modified:
db/torque/torque4/trunk/torque-runtime/src/test/java/org/apache/torque/util/BasePeerImplTest.java
URL:
http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/test/java/org/apache/torque/util/BasePeerImplTest.java?rev=1850586&r1=1850585&r2=1850586&view=diff
==============================================================================
---
db/torque/torque4/trunk/torque-runtime/src/test/java/org/apache/torque/util/BasePeerImplTest.java
(original)
+++
db/torque/torque4/trunk/torque-runtime/src/test/java/org/apache/torque/util/BasePeerImplTest.java
Sun Jan 6 18:46:35 2019
@@ -111,6 +111,7 @@ public class BasePeerImplTest extends Ba
.thenReturn(DEFAULT_GENERATED_ID);
when(idGenerator.isPriorToInsert()).thenReturn(true);
when(idGenerator.isPostInsert()).thenReturn(false);
+ when(idGenerator.isGetGeneratedKeysSupported()).thenReturn(false);
Transaction.setTransactionManager(transactionManager);
}
@@ -519,6 +520,7 @@ public class BasePeerImplTest extends Ba
verify(transactionManager).commit(connection);
verify(idGenerator).isPriorToInsert();
verify(idGenerator).isPostInsert();
+ verify(idGenerator).isGetGeneratedKeysSupported();
verify(idGenerator).getIdAsBigDecimal(connection, null);
verifyNoMoreInteractions(connection, preparedStatement, resultSet,
transactionManager, idGenerator);
// verify result
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]