/* * This file is part of aion-emu <aion-emu.com>. * * aion-emu is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * aion-emu is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with aion-emu. If not, see <http://www.gnu.org/licenses/>. */ package com.aionemu.commons.database; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Savepoint; import org.apache.log4j.Logger; /** * This class allows easy manipulations with transactions, it should be used when critical or synchronized data should * be commited to two or more tables. This class allows us to avoid data synchronization problems in db. * <p/> * Class is not designed to be thread-safe, should be synchronized externally.<br> * Class is not fail-safe, if error happens - exception will be thrown. * * @author SoulKeeper */ public class Transaction { /** * Logger for transactions */ private static final Logger log = Logger.getLogger(Transaction.class); /** * Connection that is allocated for this transaction */ private Connection connection; /** * Package private constructor, should be instantiated via * {@link com.aionemu.commons.database.DB#beginTransaction()} class * * @param con * Connection that will be used for this transaction * @throws java.sql.SQLException * if can't disable autocommit mode */ Transaction(Connection con) throws SQLException { this.connection = con; connection.setAutoCommit(false); } /** * Adds Insert / Update Query to the transaction * * @param sql * SQL string * @throws SQLException * if something went wrong */ public void insertUpdate(String sql) throws SQLException { insertUpdate(sql, null); } /** * Adds Insert / Update Query to this transaction. Utilizes IUSth for Batching and Query Editing. MUST MANUALLY * EXECUTE QUERY / BATACH IN IUSth (No need to close Statement after execution) * * @param sql * Sql query * @param iusth * query helper * @throws SQLException * if something went wrong */ public void insertUpdate(String sql, IUStH iusth) throws SQLException { PreparedStatement statement = connection.prepareStatement(sql); if(iusth != null) { iusth.handleInsertUpdate(statement); } else { statement.executeUpdate(); } } /** * Creates new savepoint * * @param name * name of savepoint * @return created savepoint * @throws SQLException * if can't create save point */ public Savepoint setSavepoint(String name) throws SQLException { return connection.setSavepoint(name); } /** * Releases savepoint of transaction * * @param savepoint * savepoint to release * @throws SQLException * if something went wrong */ public void releaseSavepoint(Savepoint savepoint) throws SQLException { connection.releaseSavepoint(savepoint); } /** * Commits transaction * * @throws SQLException * if something is wrong with transaction */ public void commit() throws SQLException { commit(null); } /** * Commits transaction. If rollBackToOnError is null - whole transaction will be rolledback * * @param rollBackToOnError * savepoint that should be used to rollback * @throws SQLException * if something went wrongF */ public void commit(Savepoint rollBackToOnError) throws SQLException { try { connection.commit(); } catch(SQLException e) { log.warn("Error while commiting transaction", e); try { if(rollBackToOnError != null) { connection.rollback(rollBackToOnError); } else { connection.rollback(); } } catch(SQLException e1) { log.error("Can't rollback transaction", e1); } } connection.setAutoCommit(true); connection.close(); } }