001/* 002 * Copyright 2002-2019 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.lang.Nullable; 020import org.springframework.transaction.NestedTransactionNotSupportedException; 021import org.springframework.transaction.SavepointManager; 022import org.springframework.transaction.TransactionException; 023import org.springframework.transaction.TransactionStatus; 024import org.springframework.transaction.TransactionUsageException; 025 026/** 027 * Abstract base implementation of the 028 * {@link org.springframework.transaction.TransactionStatus} interface. 029 * 030 * <p>Pre-implements the handling of local rollback-only and completed flags, and 031 * delegation to an underlying {@link org.springframework.transaction.SavepointManager}. 032 * Also offers the option of a holding a savepoint within the transaction. 033 * 034 * <p>Does not assume any specific internal transaction handling, such as an 035 * underlying transaction object, and no transaction synchronization mechanism. 036 * 037 * @author Juergen Hoeller 038 * @since 1.2.3 039 * @see #setRollbackOnly() 040 * @see #isRollbackOnly() 041 * @see #setCompleted() 042 * @see #isCompleted() 043 * @see #getSavepointManager() 044 * @see SimpleTransactionStatus 045 * @see DefaultTransactionStatus 046 */ 047public abstract class AbstractTransactionStatus implements TransactionStatus { 048 049 private boolean rollbackOnly = false; 050 051 private boolean completed = false; 052 053 @Nullable 054 private Object savepoint; 055 056 057 //--------------------------------------------------------------------- 058 // Implementation of TransactionExecution 059 //--------------------------------------------------------------------- 060 061 @Override 062 public void setRollbackOnly() { 063 this.rollbackOnly = true; 064 } 065 066 /** 067 * Determine the rollback-only flag via checking both the local rollback-only flag 068 * of this TransactionStatus and the global rollback-only flag of the underlying 069 * transaction, if any. 070 * @see #isLocalRollbackOnly() 071 * @see #isGlobalRollbackOnly() 072 */ 073 @Override 074 public boolean isRollbackOnly() { 075 return (isLocalRollbackOnly() || isGlobalRollbackOnly()); 076 } 077 078 /** 079 * Determine the rollback-only flag via checking this TransactionStatus. 080 * <p>Will only return "true" if the application called {@code setRollbackOnly} 081 * on this TransactionStatus object. 082 */ 083 public boolean isLocalRollbackOnly() { 084 return this.rollbackOnly; 085 } 086 087 /** 088 * Template method for determining the global rollback-only flag of the 089 * underlying transaction, if any. 090 * <p>This implementation always returns {@code false}. 091 */ 092 public boolean isGlobalRollbackOnly() { 093 return false; 094 } 095 096 /** 097 * Mark this transaction as completed, that is, committed or rolled back. 098 */ 099 public void setCompleted() { 100 this.completed = true; 101 } 102 103 @Override 104 public boolean isCompleted() { 105 return this.completed; 106 } 107 108 109 //--------------------------------------------------------------------- 110 // Handling of current savepoint state 111 //--------------------------------------------------------------------- 112 113 @Override 114 public boolean hasSavepoint() { 115 return (this.savepoint != null); 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(@Nullable Object savepoint) { 123 this.savepoint = savepoint; 124 } 125 126 /** 127 * Get the savepoint for this transaction, if any. 128 */ 129 @Nullable 130 protected Object getSavepoint() { 131 return this.savepoint; 132 } 133 134 /** 135 * Create a savepoint and hold it for the transaction. 136 * @throws org.springframework.transaction.NestedTransactionNotSupportedException 137 * if the underlying transaction does not support savepoints 138 */ 139 public void createAndHoldSavepoint() throws TransactionException { 140 setSavepoint(getSavepointManager().createSavepoint()); 141 } 142 143 /** 144 * Roll back to the savepoint that is held for the transaction 145 * and release the savepoint right afterwards. 146 */ 147 public void rollbackToHeldSavepoint() throws TransactionException { 148 Object savepoint = getSavepoint(); 149 if (savepoint == null) { 150 throw new TransactionUsageException( 151 "Cannot roll back to savepoint - no savepoint associated with current transaction"); 152 } 153 getSavepointManager().rollbackToSavepoint(savepoint); 154 getSavepointManager().releaseSavepoint(savepoint); 155 setSavepoint(null); 156 } 157 158 /** 159 * Release the savepoint that is held for the transaction. 160 */ 161 public void releaseHeldSavepoint() throws TransactionException { 162 Object savepoint = getSavepoint(); 163 if (savepoint == null) { 164 throw new TransactionUsageException( 165 "Cannot release savepoint - no savepoint associated with current transaction"); 166 } 167 getSavepointManager().releaseSavepoint(savepoint); 168 setSavepoint(null); 169 } 170 171 172 //--------------------------------------------------------------------- 173 // Implementation of SavepointManager 174 //--------------------------------------------------------------------- 175 176 /** 177 * This implementation delegates to a SavepointManager for the 178 * underlying transaction, if possible. 179 * @see #getSavepointManager() 180 * @see SavepointManager#createSavepoint() 181 */ 182 @Override 183 public Object createSavepoint() throws TransactionException { 184 return getSavepointManager().createSavepoint(); 185 } 186 187 /** 188 * This implementation delegates to a SavepointManager for the 189 * underlying transaction, if possible. 190 * @see #getSavepointManager() 191 * @see SavepointManager#rollbackToSavepoint(Object) 192 */ 193 @Override 194 public void rollbackToSavepoint(Object savepoint) throws TransactionException { 195 getSavepointManager().rollbackToSavepoint(savepoint); 196 } 197 198 /** 199 * This implementation delegates to a SavepointManager for the 200 * underlying transaction, if possible. 201 * @see #getSavepointManager() 202 * @see SavepointManager#releaseSavepoint(Object) 203 */ 204 @Override 205 public void releaseSavepoint(Object savepoint) throws TransactionException { 206 getSavepointManager().releaseSavepoint(savepoint); 207 } 208 209 /** 210 * Return a SavepointManager for the underlying transaction, if possible. 211 * <p>Default implementation always throws a NestedTransactionNotSupportedException. 212 * @throws org.springframework.transaction.NestedTransactionNotSupportedException 213 * if the underlying transaction does not support savepoints 214 */ 215 protected SavepointManager getSavepointManager() { 216 throw new NestedTransactionNotSupportedException("This transaction does not support savepoints"); 217 } 218 219 220 //--------------------------------------------------------------------- 221 // Flushing support 222 //--------------------------------------------------------------------- 223 224 /** 225 * This implementations is empty, considering flush as a no-op. 226 */ 227 @Override 228 public void flush() { 229 } 230 231}