/**
* License Agreement for OpenSearchServer Pojodbc
*
* Copyright 2008-2013 Emmanuel Keller / Jaeksoft
* Copyright 2014-2015 OpenSearchServer Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jaeksoft.pojodbc;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashSet;
import com.jaeksoft.pojodbc.connection.ConnectionManager;
/**
* <p>
* Represents a new database transaction. Currently, a transaction represents a
* database connection. Further implementation could share same connection.
* </p>
* <p>
* Transaction automatically closed every Query used.
* </p>
* <p>
* That source code is our recommended way to use it. You have close the
* transaction in a finally statement to be sure that the database connection
* will be released.
* </p>
*
* <pre>
* Transaction transaction = null;
* try {
* transaction = connectionManager.getNewTransaction(false, javax.sql.Connection.TRANSACTION_READ_COMMITTED);
* // ... do everything you need ...
* } finally {
* if (transaction != null)
* transaction.close();
* }
*
* </pre>
*
*/
public class Transaction {
private Connection cnx;
private HashSet<Query> queries;
public Transaction(Connection cnx, boolean autoCommit, Integer transactionIsolation) throws SQLException {
this.cnx = cnx;
if (transactionIsolation != null)
cnx.setTransactionIsolation(transactionIsolation);
cnx.setAutoCommit(autoCommit);
}
void closeQuery(Query query) {
synchronized (this) {
query.closeAll();
queries.remove(query);
}
}
private void closeQueries() {
synchronized (this) {
if (queries == null)
return;
for (Query query : queries)
query.closeAll();
queries.clear();
}
}
/**
* Close all queries and the transaction. No commit or rollback are
* performed.
*/
public void close() {
synchronized (this) {
if (cnx == null)
return;
synchronized (cnx) {
closeQueries();
ConnectionManager.close(null, null, cnx);
cnx = null;
}
}
}
/**
* Usual JDBC/SQL transaction rollback
*
* @throws SQLException
* if any JDBC error occurs
*/
public void rollback() throws SQLException {
synchronized (cnx) {
cnx.rollback();
}
}
/**
* Usual JDBC/SQL transaction commit
*
* @throws SQLException
* if any JDBC error occurs
*/
public void commit() throws SQLException {
synchronized (cnx) {
cnx.commit();
}
}
private void addQuery(Query query) {
synchronized (this) {
if (queries == null)
queries = new HashSet<Query>();
queries.add(query);
}
}
/**
* Create a new Query
*
* @param sql
* The native SQL query
* @return a new Query instance
* @throws SQLException
* if any JDBC error occurs
*/
public Query prepare(String sql) throws SQLException {
Query query = new Query(cnx.prepareStatement(sql));
addQuery(query);
return query;
}
/**
* Create a new Query with autogeneratedkey flag
*
* @param sql
* The native SQL query
* @return a new Query instance
* @throws SQLException
* if any JDBC error occurs
*/
public Query prepareWithKeys(String sql) throws SQLException {
Query query = new Query(cnx.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS));
addQuery(query);
return query;
}
/**
* Create a new Query with standard JDBC properties.
* <p>
* ResultSetType and ResultSetConcureny are JDBC standard parameters like
* ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.TYPE_FORWARD_ONLY,
* ResultSet.CONCUR_READ_ONLY, ResultSet.CONCUR_UPDATABLE, ...
* </p>
*
* @param sql
* The native SQL query
* @param resultSetType
* A standard JDBC ResultSet type
* @param resultSetConcurency
* A standard JDBC Result concurency property
* @return a new Query instance
* @throws SQLException
* if any JDBC error occurs
*/
public Query prepare(String sql, int resultSetType, int resultSetConcurency) throws SQLException {
Query query = new Query(cnx.prepareStatement(sql, resultSetType, resultSetConcurency));
addQuery(query);
return query;
}
/**
* A convenient way to directly execute an INSERT/UPDATE/DELETE SQL
* statement.
*
* @param sql
* The native SQL query
* @return the row count
* @throws SQLException
* if any JDBC error occurs
*/
public int update(String sql) throws SQLException {
return prepare(sql).update();
}
}