|
10 | 10 |
|
11 | 11 | import org.hibernate.resource.transaction.spi.TransactionStatus; |
12 | 12 |
|
| 13 | +import java.util.function.Consumer; |
| 14 | + |
| 15 | +import static org.hibernate.resource.transaction.backend.jta.internal.StatusTranslator.translate; |
| 16 | + |
13 | 17 | /** |
14 | 18 | * Represents a resource-local transaction, where <em>resource-local</em> is interpreted |
15 | 19 | * by Hibernate to mean any transaction under the control of Hibernate. That is to say, |
|
44 | 48 | public interface Transaction extends EntityTransaction { |
45 | 49 | /** |
46 | 50 | * Get the current {@linkplain TransactionStatus status} of this transaction. |
| 51 | + * |
| 52 | + * @apiNote {@link TransactionStatus} belongs to an SPI package, and so this |
| 53 | + * operation is a (fairly harmless) layer-breaker. Prefer the use |
| 54 | + * of {@link #isActive}, {@link #isComplete}, {@link #wasStarted}, |
| 55 | + * {@link #wasSuccessful}, {@link #wasFailure}, or |
| 56 | + * {@link #isInCompletionProcess} according to need. |
| 57 | + * |
47 | 58 | */ |
48 | 59 | TransactionStatus getStatus(); |
49 | 60 |
|
50 | 61 | /** |
51 | | - * Register a user {@link Synchronization synchronization callback} for this transaction. |
| 62 | + * Is this transaction still active? |
| 63 | + * <p> |
| 64 | + * A transaction which has been {@linkplain #markRollbackOnly marked for rollback} |
| 65 | + * is still considered active, and is still able to perform work. To determine if |
| 66 | + * a transaction has been marked for rollback, call {@link #getRollbackOnly()}. |
| 67 | + * |
| 68 | + * @return {@code true} if the {@linkplain #getStatus status} |
| 69 | + * is {@link TransactionStatus#ACTIVE} or |
| 70 | + * {@link TransactionStatus#MARKED_ROLLBACK} |
| 71 | + * |
| 72 | + * @since 7.0 |
| 73 | + */ |
| 74 | + default boolean isActive() { |
| 75 | + return switch (getStatus()) { |
| 76 | + case ACTIVE, MARKED_ROLLBACK -> true; |
| 77 | + default -> false; |
| 78 | + }; |
| 79 | + } |
| 80 | + |
| 81 | + /** |
| 82 | + * Is this transaction currently in the completion process? |
| 83 | + * |
| 84 | + * @return {@code true} if the {@linkplain #getStatus status} |
| 85 | + * is {@link TransactionStatus#COMMITTING} or |
| 86 | + * {@link TransactionStatus#ROLLING_BACK} |
| 87 | + * |
| 88 | + * @since 7.0 |
| 89 | + */ |
| 90 | + default boolean isInCompletionProcess() { |
| 91 | + return switch (getStatus()) { |
| 92 | + case COMMITTING, ROLLING_BACK -> true; |
| 93 | + default -> false; |
| 94 | + }; |
| 95 | + } |
| 96 | + |
| 97 | + /** |
| 98 | + * Is this transaction complete? |
| 99 | + * |
| 100 | + * @return {@code true} if the {@linkplain #getStatus status} |
| 101 | + * is {@link TransactionStatus#COMMITTED}, |
| 102 | + * {@link TransactionStatus#ROLLED_BACK}, |
| 103 | + * {@link TransactionStatus#FAILED_COMMIT}, or |
| 104 | + * {@link TransactionStatus#FAILED_ROLLBACK} |
| 105 | + * |
| 106 | + * @since 7.0 |
| 107 | + */ |
| 108 | + default boolean isComplete() { |
| 109 | + return switch (getStatus()) { |
| 110 | + case COMMITTED, ROLLED_BACK, FAILED_COMMIT, FAILED_ROLLBACK -> true; |
| 111 | + default -> false; |
| 112 | + }; |
| 113 | + } |
| 114 | + |
| 115 | + /** |
| 116 | + * Was this transaction already started? |
| 117 | + * |
| 118 | + * @return {@code true} if the {@linkplain #getStatus status} is |
| 119 | + * anything other than {@link TransactionStatus#NOT_ACTIVE} |
| 120 | + * |
| 121 | + * @since 7.0 |
| 122 | + */ |
| 123 | + default boolean wasStarted() { |
| 124 | + return getStatus() != TransactionStatus.NOT_ACTIVE; |
| 125 | + } |
| 126 | + |
| 127 | + /** |
| 128 | + * Was this transaction already successfully committed? |
| 129 | + * |
| 130 | + * @return {@code true} if the {@linkplain #getStatus status} |
| 131 | + * is {@link TransactionStatus#COMMITTED} |
| 132 | + * |
| 133 | + * @since 7.0 |
| 134 | + */ |
| 135 | + default boolean wasSuccessful() { |
| 136 | + return getStatus() == TransactionStatus.COMMITTED; |
| 137 | + } |
| 138 | + |
| 139 | + /** |
| 140 | + * Was this transaction a failure? Here we consider a successful rollback, |
| 141 | + * a failed commit, or a failed rollback to amount to transaction failure. |
| 142 | + * |
| 143 | + * @return {@code true} if the {@linkplain #getStatus status} |
| 144 | + * is {@link TransactionStatus#ROLLED_BACK}, |
| 145 | + * {@link TransactionStatus#FAILED_COMMIT}, |
| 146 | + * {@link TransactionStatus#FAILED_ROLLBACK} |
| 147 | + * |
| 148 | + * @since 7.0 |
| 149 | + */ |
| 150 | + default boolean wasFailure() { |
| 151 | + return switch (getStatus()) { |
| 152 | + case ROLLED_BACK, FAILED_COMMIT, FAILED_ROLLBACK -> true; |
| 153 | + default -> false; |
| 154 | + }; |
| 155 | + } |
| 156 | + |
| 157 | + /** |
| 158 | + * Register an action which will be called during the "before completion" phase. |
52 | 159 | * |
53 | | - * @param synchronization The {@link Synchronization} callback to register. |
| 160 | + * @since 7.0 |
| 161 | + */ |
| 162 | + default void runBeforeCompletion(Runnable action) { |
| 163 | + registerSynchronization( new Synchronization() { |
| 164 | + @Override |
| 165 | + public void beforeCompletion() { |
| 166 | + action.run(); |
| 167 | + } |
| 168 | + @Override |
| 169 | + public void afterCompletion(int status) { |
| 170 | + } |
| 171 | + } ); |
| 172 | + } |
| 173 | + |
| 174 | + /** |
| 175 | + * Register an action which will be called during the "after completion" phase. |
54 | 176 | * |
55 | | - * @throws HibernateException Indicates a problem registering the synchronization. |
| 177 | + * @since 7.0 |
| 178 | + */ |
| 179 | + default void runAfterCompletion(Consumer<TransactionStatus> action) { |
| 180 | + registerSynchronization( new Synchronization() { |
| 181 | + @Override |
| 182 | + public void beforeCompletion() { |
| 183 | + } |
| 184 | + @Override |
| 185 | + public void afterCompletion(int status) { |
| 186 | + action.accept( translate( status ) ); |
| 187 | + } |
| 188 | + } ); |
| 189 | + } |
| 190 | + |
| 191 | + /** |
| 192 | + * Register a {@linkplain Synchronization synchronization callback} for this transaction. |
| 193 | + * |
| 194 | + * @param synchronization The {@link Synchronization} callback to register |
| 195 | + * |
| 196 | + * @apiNote {@link Synchronization} is a type defined by JTA, but this operation does |
| 197 | + * not depend on the use of JTA for transaction management. Prefer the use of |
| 198 | + * the methods {@link #runBeforeCompletion} and {@link #runAfterCompletion} |
| 199 | + * for convenience. |
56 | 200 | */ |
57 | 201 | void registerSynchronization(Synchronization synchronization); |
58 | 202 |
|
59 | 203 | /** |
60 | | - * Set the transaction timeout for any transaction started by any subsequent call to |
61 | | - * {@link #begin} on this instance. |
| 204 | + * Set the transaction timeout for any transaction started by a subsequent call to |
| 205 | + * {@link #begin} on this instance of {@code Transaction}. |
62 | 206 | * |
63 | | - * @param seconds The number of seconds before a timeout. |
| 207 | + * @param seconds The number of seconds before a timeout |
64 | 208 | */ |
65 | 209 | void setTimeout(int seconds); |
66 | 210 |
|
67 | 211 | /** |
68 | | - * Retrieve the transaction timeout set for this instance. A negative integer indicates |
69 | | - * that no timeout has been set. |
| 212 | + * Retrieve the transaction timeout set for this instance. |
| 213 | + * <p> |
| 214 | + * A {@code null} return value indicates that no timeout has been set. |
70 | 215 | * |
71 | | - * @return The timeout, in seconds. |
| 216 | + * @return the timeout, in seconds, or {@code null} |
72 | 217 | */ |
73 | 218 | @Nullable Integer getTimeout(); |
74 | 219 |
|
|
0 commit comments