package io.ebeaninternal.server.transaction;

import io.ebeaninternal.api.SpiTransaction;
import io.ebeaninternal.api.SpiTransactionProxy;
import io.ebeaninternal.server.lib.Str;

import javax.persistence.PersistenceException;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Savepoint;

A nested transaction that represents a Savepoint.
/** * A nested transaction that represents a Savepoint. */
class SavepointTransaction extends SpiTransactionProxy { private static final int STATE_COMMITTED = 1; private static final int STATE_ROLLED_BACK = 2; private final TransactionManager manager; private final Savepoint savepoint; private final Connection connection; private final String logPrefix; private final String spPrefix; private boolean rollbackOnly; private int state; SavepointTransaction(SpiTransaction transaction, TransactionManager manager) throws SQLException { this.manager = manager; this.transaction = transaction; this.connection = transaction.getInternalConnection(); this.savepoint = connection.setSavepoint(); if (manager.isTxnDebug()) { int savepointId = manager.isSupportsSavepointId() ? savepoint.getSavepointId() : 0; this.spPrefix = "sp[" + savepointId + "] "; } else { this.spPrefix = "sp[] "; } this.logPrefix = transaction.getLogPrefix() + spPrefix; } @Override public String getLogPrefix() { return logPrefix; } @Override public void logSql(String msg) { transaction.logSql(Str.add(spPrefix, msg)); } @Override public void logSummary(String msg) { transaction.logSummary(Str.add(spPrefix, msg)); } @Override public void setRollbackOnly() { this.rollbackOnly = true; } @Override public void commit() { if (rollbackOnly) { rollbackSavepoint(null); } else { commitSavepoint(); } } @Override public void rollback() throws PersistenceException { rollbackSavepoint(null); } @Override public void rollback(Throwable e) throws PersistenceException { rollbackSavepoint(e); } private void commitSavepoint() { try { connection.releaseSavepoint(savepoint); state = STATE_COMMITTED; manager.notifyOfCommit(this); } catch (SQLException e) { throw new PersistenceException("Error trying to commit/release Savepoint", e); } } private void rollbackSavepoint(Throwable cause) throws PersistenceException { try { connection.rollback(savepoint); state = STATE_ROLLED_BACK; manager.notifyOfRollback(this, cause); } catch (SQLException e) { throw new PersistenceException("Error trying to rollback Savepoint", e); } } @Override public void end() { if (state == 0) { rollback(); } } @Override public void close() { end(); } }