Search in sources :

Example 1 with Transaction

use of org.apache.cayenne.tx.Transaction in project cayenne by apache.

the class DataNode method performQueries.

/**
 * Runs queries using Connection obtained from internal DataSource.
 *
 * @since 1.1
 */
@Override
public void performQueries(Collection<? extends Query> queries, OperationObserver callback) {
    int listSize = queries.size();
    if (listSize == 0) {
        return;
    }
    if (callback.isIteratedResult() && listSize > 1) {
        throw new CayenneRuntimeException("Iterated queries are not allowed in a batch. Batch size: %d", listSize);
    }
    // do this meaningless inexpensive operation to trigger AutoAdapter lazy
    // initialization before opening a connection. Otherwise we may end up
    // with two
    // connections open simultaneously, possibly hitting connection pool
    // upper limit.
    getAdapter().getExtendedTypes();
    Connection connection = null;
    try {
        connection = this.getDataSource().getConnection();
    } catch (Exception globalEx) {
        getJdbcEventLogger().logQueryError(globalEx);
        Transaction transaction = BaseTransaction.getThreadTransaction();
        if (transaction != null) {
            transaction.setRollbackOnly();
        }
        callback.nextGlobalException(globalEx);
        return;
    }
    try {
        DataNodeQueryAction queryRunner = new DataNodeQueryAction(this, callback);
        for (Query nextQuery : queries) {
            // catch exceptions for each individual query
            try {
                queryRunner.runQuery(connection, nextQuery);
            } catch (Exception queryEx) {
                getJdbcEventLogger().logQueryError(queryEx);
                // notify consumer of the exception,
                // stop running further queries
                callback.nextQueryException(nextQuery, queryEx);
                Transaction transaction = BaseTransaction.getThreadTransaction();
                if (transaction != null) {
                    transaction.setRollbackOnly();
                }
                break;
            }
        }
    } finally {
        try {
            connection.close();
        } catch (SQLException e) {
        // ignore closing exceptions...
        }
    }
}
Also used : BaseTransaction(org.apache.cayenne.tx.BaseTransaction) Transaction(org.apache.cayenne.tx.Transaction) SelectQuery(org.apache.cayenne.query.SelectQuery) BatchQuery(org.apache.cayenne.query.BatchQuery) Query(org.apache.cayenne.query.Query) SQLException(java.sql.SQLException) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException) Connection(java.sql.Connection) SQLFeatureNotSupportedException(java.sql.SQLFeatureNotSupportedException) SQLException(java.sql.SQLException) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException)

Example 2 with Transaction

use of org.apache.cayenne.tx.Transaction in project cayenne by apache.

the class DataContextPerformQueryAPIIT method testProcedureQueryStringMapBoolean.

@Test
public void testProcedureQueryStringMapBoolean() throws Exception {
    if (!accessStackAdapter.supportsStoredProcedures()) {
        return;
    }
    if (!accessStackAdapter.canMakeObjectsOutOfProcedures()) {
        return;
    }
    createTwoArtistsAndTwoPaintingsDataSet();
    // fetch artist
    Map<String, String> parameters = Collections.singletonMap("aName", "artist2");
    List<?> artists;
    // Sybase blows whenever a transaction wraps a SP, so turn of
    // transactions
    Transaction t = new ExternalTransaction(jdbcEventLogger);
    BaseTransaction.bindThreadTransaction(t);
    try {
        artists = context.performQuery("ProcedureQuery", parameters, true);
    } finally {
        BaseTransaction.bindThreadTransaction(null);
        t.commit();
    }
    assertNotNull(artists);
    assertEquals(1, artists.size());
    Artist artist = (Artist) artists.get(0);
    assertEquals(11, ((Number) artist.getObjectId().getIdSnapshot().get(Artist.ARTIST_ID_PK_COLUMN)).intValue());
}
Also used : Artist(org.apache.cayenne.testdo.testmap.Artist) BaseTransaction(org.apache.cayenne.tx.BaseTransaction) ExternalTransaction(org.apache.cayenne.tx.ExternalTransaction) Transaction(org.apache.cayenne.tx.Transaction) ExternalTransaction(org.apache.cayenne.tx.ExternalTransaction) Test(org.junit.Test)

Example 3 with Transaction

use of org.apache.cayenne.tx.Transaction in project cayenne by apache.

the class SybasePkGenerator method longPkFromDatabase.

/**
 * @since 3.0
 */
@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.
    // 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?
    Transaction transaction = BaseTransaction.getThreadTransaction();
    BaseTransaction.bindThreadTransaction(null);
    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 %s", entity.getName());
                    }
                }
            } else {
                throw new CayenneRuntimeException("Error generating pk for DbEntity %s" + ", no result set from stored procedure.", entity.getName());
            }
        }
    } finally {
        BaseTransaction.bindThreadTransaction(transaction);
    }
}
Also used : BaseTransaction(org.apache.cayenne.tx.BaseTransaction) Transaction(org.apache.cayenne.tx.Transaction) CallableStatement(java.sql.CallableStatement) Connection(java.sql.Connection) ResultSet(java.sql.ResultSet) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException)

Example 4 with Transaction

use of org.apache.cayenne.tx.Transaction in project cayenne by apache.

the class MySQLPkGenerator method longPkFromDatabase.

/**
 * Overrides superclass's implementation to perform locking of the primary
 * key lookup table.
 *
 * @since 3.0
 */
@Override
protected long longPkFromDatabase(DataNode node, DbEntity entity) throws Exception {
    // must work directly with JDBC connection, since we
    // must unlock the AUTO_PK_SUPPORT table in case of
    // failures.... ah..JDBC is fun...
    // chained SQL exception
    SQLException exception = null;
    long pk = -1L;
    // Start new transaction if needed, can any way lead to problems when
    // using external transaction manager. We can only warn about it.
    // See https://issues.apache.org/jira/browse/CAY-2186 for details.
    Transaction transaction = BaseTransaction.getThreadTransaction();
    if (transaction != null && transaction.isExternal()) {
        logger.warn("Using MysqlPkGenerator with external transaction manager may lead to inconsistent state.");
    }
    BaseTransaction.bindThreadTransaction(null);
    try (Connection con = node.getDataSource().getConnection()) {
        if (con.getAutoCommit()) {
            con.setAutoCommit(false);
        }
        try (Statement st = con.createStatement()) {
            try {
                pk = getLongPrimaryKey(st, entity.getName());
                con.commit();
            } catch (SQLException pkEx) {
                try {
                    con.rollback();
                } catch (SQLException ignored) {
                }
                exception = processSQLException(pkEx, null);
            } finally {
                // THIS MUST BE EXECUTED NO MATTER WHAT, OR WE WILL LOCK THE PRIMARY KEY TABLE!!
                try {
                    String unlockString = "UNLOCK TABLES";
                    adapter.getJdbcEventLogger().log(unlockString);
                    st.execute(unlockString);
                } catch (SQLException unlockEx) {
                    exception = processSQLException(unlockEx, exception);
                }
            }
        }
    } catch (SQLException otherEx) {
        exception = processSQLException(otherEx, null);
    } finally {
        BaseTransaction.bindThreadTransaction(transaction);
    }
    // check errors
    if (exception != null) {
        throw exception;
    }
    return pk;
}
Also used : BaseTransaction(org.apache.cayenne.tx.BaseTransaction) Transaction(org.apache.cayenne.tx.Transaction) SQLException(java.sql.SQLException) Statement(java.sql.Statement) Connection(java.sql.Connection)

Example 5 with Transaction

use of org.apache.cayenne.tx.Transaction in project cayenne by apache.

the class DataContext method performIteratedQuery.

/**
 * Performs a single database select query returning result as a
 * ResultIterator. It is caller's responsibility to explicitly close the
 * ResultIterator. A failure to do so will result in a database connection
 * not being released. Another side effect of an open ResultIterator is that
 * an internal Cayenne transaction that originated in this method stays open
 * until the iterator is closed. So users should normally close the iterator
 * within the same thread that opened it.
 * <p>
 * Note that 'performIteratedQuery' always returns ResultIterator over
 * DataRows. Use
 * {@link #iterate(Select, org.apache.cayenne.ResultIteratorCallback)} to
 * get access to objects.
 */
// TODO: deprecate once all selecting queries start implementing Select<T>
// interface
@SuppressWarnings({ "rawtypes" })
public ResultIterator performIteratedQuery(Query query) {
    if (BaseTransaction.getThreadTransaction() != null) {
        return internalPerformIteratedQuery(query);
    } else {
        // can't use TransactionManger here as it would attempt to commit the transaction at the end...
        // manually manage a transaction, so that a ResultIterator wrapper
        // could close it when it is done.
        Transaction tx = getTransactionFactory().createTransaction();
        BaseTransaction.bindThreadTransaction(tx);
        ResultIterator<?> result;
        try {
            result = internalPerformIteratedQuery(query);
        } catch (Exception e) {
            tx.setRollbackOnly();
            throw new CayenneRuntimeException(e);
        } finally {
            // unbind thread tx before returning to the caller. Transaction will be managed internally by the
            // ResultIterator and should not get in the way of other DB operations that may be performed
            // within the iterator....
            // TODO: there was an older comment about Ingres breaking when we unbind thread transaction
            // before closing the iterator. As we have no test environment for ingres, we can't
            // confirm this here...
            BaseTransaction.bindThreadTransaction(null);
            if (tx.isRollbackOnly()) {
                try {
                    tx.rollback();
                } catch (Exception rollbackEx) {
                }
            }
        }
        return new TransactionResultIteratorDecorator<>(result, tx);
    }
}
Also used : BaseTransaction(org.apache.cayenne.tx.BaseTransaction) Transaction(org.apache.cayenne.tx.Transaction) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException) IOException(java.io.IOException) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException)

Aggregations

BaseTransaction (org.apache.cayenne.tx.BaseTransaction)5 Transaction (org.apache.cayenne.tx.Transaction)5 Connection (java.sql.Connection)3 CayenneRuntimeException (org.apache.cayenne.CayenneRuntimeException)3 SQLException (java.sql.SQLException)2 IOException (java.io.IOException)1 CallableStatement (java.sql.CallableStatement)1 ResultSet (java.sql.ResultSet)1 SQLFeatureNotSupportedException (java.sql.SQLFeatureNotSupportedException)1 Statement (java.sql.Statement)1 BatchQuery (org.apache.cayenne.query.BatchQuery)1 Query (org.apache.cayenne.query.Query)1 SelectQuery (org.apache.cayenne.query.SelectQuery)1 Artist (org.apache.cayenne.testdo.testmap.Artist)1 ExternalTransaction (org.apache.cayenne.tx.ExternalTransaction)1 Test (org.junit.Test)1