From 4611bf9e43f0782f13216ea14f763e4e5c39a86e Mon Sep 17 00:00:00 2001 From: Patrick Linskey Date: Sat, 30 Dec 2006 01:20:55 +0000 Subject: [PATCH] Code changes for OPENJPA-93: sequence maintainance in JTA env without non-JTA datasource. This has been nominally tested in WebLogic Server. git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@491147 13f79535-47bb-0310-9956-ffa450edef68 --- .../openjpa/jdbc/kernel/AbstractJDBCSeq.java | 73 +++++++++++++++---- .../openjpa/jdbc/kernel/NativeJDBCSeq.java | 4 + .../openjpa/jdbc/kernel/TableJDBCSeq.java | 7 +- 3 files changed, 68 insertions(+), 16 deletions(-) diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractJDBCSeq.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractJDBCSeq.java index e2e207fb1..f98c0d1c6 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractJDBCSeq.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractJDBCSeq.java @@ -18,6 +18,8 @@ package org.apache.openjpa.jdbc.kernel; import java.sql.Connection; import java.sql.SQLException; import javax.sql.DataSource; +import javax.transaction.Transaction; +import javax.transaction.TransactionManager; import org.apache.openjpa.jdbc.conf.JDBCConfiguration; import org.apache.openjpa.jdbc.meta.ClassMapping; @@ -40,6 +42,7 @@ public abstract class AbstractJDBCSeq protected int type = TYPE_DEFAULT; protected Object current = null; + private transient Transaction _outerTransaction; /** * Records the sequence type. @@ -106,6 +109,11 @@ public abstract class AbstractJDBCSeq protected abstract Object nextInternal(JDBCStore store, ClassMapping mapping) throws Exception; + + /** + * Return the {@link JDBCConfiguration} for this sequence. + */ + public abstract JDBCConfiguration getConfiguration(); /** * Return the current sequence object. By default returns the last @@ -140,13 +148,24 @@ public abstract class AbstractJDBCSeq throws SQLException { if (type == TYPE_TRANSACTIONAL || type == TYPE_CONTIGUOUS) return store.getConnection(); - - JDBCConfiguration conf = store.getConfiguration(); - DataSource ds = conf.getDataSource2(store.getContext()); - Connection conn = ds.getConnection(); - if (conn.getAutoCommit()) - conn.setAutoCommit(false); - return conn; + else if (suspendInJTA()) { + try { + TransactionManager tm = getConfiguration() + .getManagedRuntimeInstance().getTransactionManager(); + _outerTransaction = tm.suspend(); + tm.begin(); + return store.getConnection(); + } catch (Exception e) { + throw new StoreException(e); + } + } else { + JDBCConfiguration conf = store.getConfiguration(); + DataSource ds = conf.getDataSource2(store.getContext()); + Connection conn = ds.getConnection(); + if (conn.getAutoCommit()) + conn.setAutoCommit(false); + return conn; + } } /** @@ -156,13 +175,41 @@ public abstract class AbstractJDBCSeq if (conn == null) return; - try { - if (type != TYPE_TRANSACTIONAL && type != TYPE_CONTIGUOUS) + if (type == TYPE_TRANSACTIONAL || type == TYPE_CONTIGUOUS) { + // do nothing; this seq is part of the business transaction + return; + } else if (suspendInJTA()) { + try { + TransactionManager tm = getConfiguration() + .getManagedRuntimeInstance().getTransactionManager(); + tm.commit(); + try { conn.close(); } catch (SQLException se) {} + + if (_outerTransaction != null) + tm.resume(_outerTransaction); + + } catch (Exception e) { + throw new StoreException(e); + } finally { + _outerTransaction = null; + } + } else { + try { conn.commit(); - } catch (SQLException se) { - throw SQLExceptions.getStore(se); - } finally { - try { conn.close(); } catch (SQLException se) {} + } catch (SQLException se) { + throw SQLExceptions.getStore(se); + } finally { + try { conn.close(); } catch (SQLException se) {} + } } } + + /** + * Detect whether or not OpenJPA should suspend the transaction in + * a managed environment. + */ + protected boolean suspendInJTA() { + return getConfiguration().isConnectionFactoryModeManaged() && + getConfiguration().getConnectionFactory2() == null; + } } diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/NativeJDBCSeq.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/NativeJDBCSeq.java index 59b638679..9fabb6d15 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/NativeJDBCSeq.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/NativeJDBCSeq.java @@ -172,6 +172,10 @@ public class NativeJDBCSeq schema.importSequence(_seq); } + public JDBCConfiguration getConfiguration() { + return _conf; + } + public void setConfiguration(Configuration conf) { _conf = (JDBCConfiguration) conf; } diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java index ca9fa2c91..3bc45dd5f 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java @@ -330,7 +330,8 @@ public class TableJDBCSeq try { // possible that we might get errors when inserting if // another thread/process is inserting same pk at same time - SQLException err = null; + SQLException err = null; + // ### why does this not call getConnection() / closeConnection()? conn = _conf.getDataSource2(store.getContext()).getConnection(); try { insertSequence(mapping, conn); @@ -377,7 +378,7 @@ public class TableJDBCSeq appendValue(Numbers.valueOf(1), _seqColumn).append(")"); boolean wasAuto = conn.getAutoCommit(); - if (!wasAuto) + if (!wasAuto && !suspendInJTA()) conn.setAutoCommit(true); PreparedStatement stmnt = null; @@ -387,7 +388,7 @@ public class TableJDBCSeq } finally { if (stmnt != null) try { stmnt.close(); } catch (SQLException se) {} - if (!wasAuto) + if (!wasAuto && !suspendInJTA()) conn.setAutoCommit(false); } }