001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.transaction.support; 018 019import org.springframework.transaction.NestedTransactionNotSupportedException; 020import org.springframework.transaction.SavepointManager; 021import org.springframework.transaction.TransactionException; 022import org.springframework.transaction.TransactionStatus; 023import org.springframework.transaction.TransactionUsageException; 024 025/** 026 * Abstract base implementation of the 027 * {@link org.springframework.transaction.TransactionStatus} interface. 028 * 029 * <p>Pre-implements the handling of local rollback-only and completed flags, and 030 * delegation to an underlying {@link org.springframework.transaction.SavepointManager}. 031 * Also offers the option of a holding a savepoint within the transaction. 032 * 033 * <p>Does not assume any specific internal transaction handling, such as an 034 * underlying transaction object, and no transaction synchronization mechanism. 035 * 036 * @author Juergen Hoeller 037 * @since 1.2.3 038 * @see #setRollbackOnly() 039 * @see #isRollbackOnly() 040 * @see #setCompleted() 041 * @see #isCompleted() 042 * @see #getSavepointManager() 043 * @see SimpleTransactionStatus 044 * @see DefaultTransactionStatus 045 */ 046public abstract class AbstractTransactionStatus implements TransactionStatus { 047 048 private boolean rollbackOnly = false; 049 050 private boolean completed = false; 051 052 private Object savepoint; 053 054 055 //--------------------------------------------------------------------- 056 // Handling of current transaction state 057 //--------------------------------------------------------------------- 058 059 @Override 060 public void setRollbackOnly() { 061 this.rollbackOnly = true; 062 } 063 064 /** 065 * Determine the rollback-only flag via checking both the local rollback-only flag 066 * of this TransactionStatus and the global rollback-only flag of the underlying 067 * transaction, if any. 068 * @see #isLocalRollbackOnly() 069 * @see #isGlobalRollbackOnly() 070 */ 071 @Override 072 public boolean isRollbackOnly() { 073 return (isLocalRollbackOnly() || isGlobalRollbackOnly()); 074 } 075 076 /** 077 * Determine the rollback-only flag via checking this TransactionStatus. 078 * <p>Will only return "true" if the application called {@code setRollbackOnly} 079 * on this TransactionStatus object. 080 */ 081 public boolean isLocalRollbackOnly() { 082 return this.rollbackOnly; 083 } 084 085 /** 086 * Template method for determining the global rollback-only flag of the 087 * underlying transaction, if any. 088 * <p>This implementation always returns {@code false}. 089 */ 090 public boolean isGlobalRollbackOnly() { 091 return false; 092 } 093 094 /** 095 * This implementations is empty, considering flush as a no-op. 096 */ 097 @Override 098 public void flush() { 099 } 100 101 /** 102 * Mark this transaction as completed, that is, committed or rolled back. 103 */ 104 public void setCompleted() { 105 this.completed = true; 106 } 107 108 @Override 109 public boolean isCompleted() { 110 return this.completed; 111 } 112 113 114 //--------------------------------------------------------------------- 115 // Handling of current savepoint state 116 //--------------------------------------------------------------------- 117 118 /** 119 * Set a savepoint for this transaction. Useful for PROPAGATION_NESTED. 120 * @see org.springframework.transaction.TransactionDefinition#PROPAGATION_NESTED 121 */ 122 protected void setSavepoint(Object savepoint) { 123 this.savepoint = savepoint; 124 } 125 126 /** 127 * Get the savepoint for this transaction, if any. 128 */ 129 protected Object getSavepoint() { 130 return this.savepoint; 131 } 132 133 @Override 134 public boolean hasSavepoint() { 135 return (this.savepoint != null); 136 } 137 138 /** 139 * Create a savepoint and hold it for the transaction. 140 * @throws org.springframework.transaction.NestedTransactionNotSupportedException 141 * if the underlying transaction does not support savepoints 142 */ 143 public void createAndHoldSavepoint() throws TransactionException { 144 setSavepoint(getSavepointManager().createSavepoint()); 145 } 146 147 /** 148 * Roll back to the savepoint that is held for the transaction 149 * and release the savepoint right afterwards. 150 */ 151 public void rollbackToHeldSavepoint() throws TransactionException { 152 if (!hasSavepoint()) { 153 throw new TransactionUsageException( 154 "Cannot roll back to savepoint - no savepoint associated with current transaction"); 155 } 156 getSavepointManager().rollbackToSavepoint(getSavepoint()); 157 getSavepointManager().releaseSavepoint(getSavepoint()); 158 setSavepoint(null); 159 } 160 161 /** 162 * Release the savepoint that is held for the transaction. 163 */ 164 public void releaseHeldSavepoint() throws TransactionException { 165 if (!hasSavepoint()) { 166 throw new TransactionUsageException( 167 "Cannot release savepoint - no savepoint associated with current transaction"); 168 } 169 getSavepointManager().releaseSavepoint(getSavepoint()); 170 setSavepoint(null); 171 } 172 173 174 //--------------------------------------------------------------------- 175 // Implementation of SavepointManager 176 //--------------------------------------------------------------------- 177 178 /** 179 * This implementation delegates to a SavepointManager for the 180 * underlying transaction, if possible. 181 * @see #getSavepointManager() 182 * @see SavepointManager#createSavepoint() 183 */ 184 @Override 185 public Object createSavepoint() throws TransactionException { 186 return getSavepointManager().createSavepoint(); 187 } 188 189 /** 190 * This implementation delegates to a SavepointManager for the 191 * underlying transaction, if possible. 192 * @see #getSavepointManager() 193 * @see SavepointManager#rollbackToSavepoint(Object) 194 */ 195 @Override 196 public void rollbackToSavepoint(Object savepoint) throws TransactionException { 197 getSavepointManager().rollbackToSavepoint(savepoint); 198 } 199 200 /** 201 * This implementation delegates to a SavepointManager for the 202 * underlying transaction, if possible. 203 * @see #getSavepointManager() 204 * @see SavepointManager#releaseSavepoint(Object) 205 */ 206 @Override 207 public void releaseSavepoint(Object savepoint) throws TransactionException { 208 getSavepointManager().releaseSavepoint(savepoint); 209 } 210 211 /** 212 * Return a SavepointManager for the underlying transaction, if possible. 213 * <p>Default implementation always throws a NestedTransactionNotSupportedException. 214 * @throws org.springframework.transaction.NestedTransactionNotSupportedException 215 * if the underlying transaction does not support savepoints 216 */ 217 protected SavepointManager getSavepointManager() { 218 throw new NestedTransactionNotSupportedException("This transaction does not support savepoints"); 219 } 220 221}