001package io.ebean; 002 003import io.ebean.annotation.PersistBatch; 004import io.ebean.annotation.TxIsolation; 005import io.ebean.annotation.TxType; 006 007import java.util.ArrayList; 008import java.util.concurrent.Callable; 009 010/** 011 * Holds the definition of how a transactional method should run. 012 * <p> 013 * This information matches the features of the Transactional annotation. You 014 * can use it directly with Runnable or Callable via 015 * {@link DB#execute(TxScope, Runnable)} or 016 * {@link DB#executeCall(TxScope, Callable)}. 017 * </p> 018 * <p> 019 * This object is used internally with the enhancement of a method with 020 * Transactional annotation. 021 * </p> 022 * 023 * @see DB#execute(TxScope, Runnable) 024 * @see DB#executeCall(TxScope, Callable) 025 */ 026public final class TxScope { 027 028 private int profileId; 029 030 private TxType type; 031 032 private String serverName; 033 034 private TxIsolation isolation; 035 036 private PersistBatch batch; 037 038 private PersistBatch batchOnCascade; 039 040 private int batchSize; 041 042 private boolean skipGeneratedKeys; 043 044 private boolean readOnly; 045 046 /** 047 * Set this to false if the JDBC batch should not be automatically be flushed when a query is executed. 048 */ 049 private boolean flushOnQuery = true; 050 051 private boolean skipCache; 052 053 private String label; 054 055 private ArrayList<Class<? extends Throwable>> rollbackFor; 056 057 private ArrayList<Class<? extends Throwable>> noRollbackFor; 058 059 private ProfileLocation profileLocation; 060 061 /** 062 * Helper method to create a TxScope with REQUIRES. 063 */ 064 public static TxScope required() { 065 return new TxScope(TxType.REQUIRED); 066 } 067 068 /** 069 * Helper method to create a TxScope with REQUIRES_NEW. 070 */ 071 public static TxScope requiresNew() { 072 return new TxScope(TxType.REQUIRES_NEW); 073 } 074 075 /** 076 * Helper method to create a TxScope with MANDATORY. 077 */ 078 public static TxScope mandatory() { 079 return new TxScope(TxType.MANDATORY); 080 } 081 082 /** 083 * Helper method to create a TxScope with SUPPORTS. 084 */ 085 public static TxScope supports() { 086 return new TxScope(TxType.SUPPORTS); 087 } 088 089 /** 090 * Helper method to create a TxScope with NOT_SUPPORTED. 091 */ 092 public static TxScope notSupported() { 093 return new TxScope(TxType.NOT_SUPPORTED); 094 } 095 096 /** 097 * Helper method to create a TxScope with NEVER. 098 */ 099 public static TxScope never() { 100 return new TxScope(TxType.NEVER); 101 } 102 103 /** 104 * Create a REQUIRED transaction scope. 105 */ 106 public TxScope() { 107 this.type = TxType.REQUIRED; 108 } 109 110 /** 111 * Create with a given transaction scope type. 112 */ 113 public TxScope(TxType type) { 114 this.type = type; 115 } 116 117 /** 118 * Describes this TxScope instance. 119 */ 120 @Override 121 public String toString() { 122 return "TxScope[" + type + "] readOnly[" + readOnly + "] isolation[" + isolation 123 + "] serverName[" + serverName + "] rollbackFor[" + rollbackFor + "] noRollbackFor[" + noRollbackFor + "]"; 124 } 125 126 /** 127 * Return true if PersistBatch has been set. 128 */ 129 public boolean isBatchSet() { 130 return batch != null && batch != PersistBatch.INHERIT; 131 } 132 133 /** 134 * Return true if batch on cascade has been set. 135 */ 136 public boolean isBatchOnCascadeSet() { 137 return batchOnCascade != null && batchOnCascade != PersistBatch.INHERIT; 138 } 139 140 /** 141 * Return true if batch size has been set. 142 */ 143 public boolean isBatchSizeSet() { 144 return batchSize > 0; 145 } 146 147 /** 148 * Check for batchSize being set without batch mode and use this to imply PersistBatch.ALL. 149 */ 150 public void checkBatchMode() { 151 if (batchSize > 0 && notSet(batch) && notSet(batchOnCascade)) { 152 // Use setting the batchSize as implying PersistBatch.ALL for @Transactional 153 batch = PersistBatch.ALL; 154 } 155 } 156 157 /** 158 * Return true if the mode is considered not set. 159 */ 160 private boolean notSet(PersistBatch batchMode) { 161 return batchMode == null || batchMode == PersistBatch.INHERIT; 162 } 163 164 /** 165 * Return the transaction type. 166 */ 167 public TxType getType() { 168 return type; 169 } 170 171 /** 172 * Set the transaction type. 173 */ 174 public TxScope setType(TxType type) { 175 this.type = type; 176 return this; 177 } 178 179 /** 180 * Return the transaction profile id. 181 */ 182 public int getProfileId() { 183 return profileId; 184 } 185 186 /** 187 * Set the transaction profile id. 188 */ 189 public TxScope setProfileId(int profileId) { 190 this.profileId = profileId; 191 return this; 192 } 193 194 /** 195 * Return the profile location. 196 */ 197 public ProfileLocation getProfileLocation() { 198 return profileLocation; 199 } 200 201 /** 202 * Set the profile location. 203 */ 204 public TxScope setProfileLocation(ProfileLocation profileLocation) { 205 this.profileLocation = profileLocation; 206 return this; 207 } 208 209 /** 210 * Return true if the L2 cache should be skipped for this transaction. 211 */ 212 public boolean isSkipCache() { 213 return skipCache; 214 } 215 216 /** 217 * Set to true if the transaction should skip L2 cache access. 218 */ 219 public TxScope setSkipCache(boolean skipCache) { 220 this.skipCache = skipCache; 221 return this; 222 } 223 224 /** 225 * Return the label for the transaction. 226 */ 227 public String getLabel() { 228 return label; 229 } 230 231 /** 232 * Set a label for the transaction. 233 */ 234 public TxScope setLabel(String label) { 235 this.label = label; 236 return this; 237 } 238 239 /** 240 * Return the batch mode. 241 */ 242 public PersistBatch getBatch() { 243 return batch; 244 } 245 246 /** 247 * Set the batch mode to use. 248 */ 249 public TxScope setBatch(PersistBatch batch) { 250 this.batch = batch; 251 return this; 252 } 253 254 /** 255 * Return the batch on cascade mode. 256 */ 257 public PersistBatch getBatchOnCascade() { 258 return batchOnCascade; 259 } 260 261 /** 262 * Set the batch on cascade mode. 263 */ 264 public TxScope setBatchOnCascade(PersistBatch batchOnCascade) { 265 this.batchOnCascade = batchOnCascade; 266 return this; 267 } 268 269 /** 270 * Return the batch size. 0 means use the default value. 271 */ 272 public int getBatchSize() { 273 return batchSize; 274 } 275 276 /** 277 * Set the batch size to use. 278 */ 279 public TxScope setBatchSize(int batchSize) { 280 this.batchSize = batchSize; 281 return this; 282 } 283 284 /** 285 * Set if the transaction should skip reading generated keys for inserts. 286 */ 287 public TxScope setSkipGeneratedKeys() { 288 this.skipGeneratedKeys = true; 289 return this; 290 } 291 292 /** 293 * Return true if getGeneratedKeys should be skipped for this transaction. 294 */ 295 public boolean isSkipGeneratedKeys() { 296 return skipGeneratedKeys; 297 } 298 299 /** 300 * Return if the transaction should be treated as read only. 301 */ 302 public boolean isReadonly() { 303 return readOnly; 304 } 305 306 /** 307 * Set if the transaction should be treated as read only. 308 */ 309 public TxScope setReadOnly(boolean readOnly) { 310 this.readOnly = readOnly; 311 return this; 312 } 313 314 /** 315 * Return false if the JDBC batch buffer should not be flushed automatically when a query is executed. 316 */ 317 public boolean isFlushOnQuery() { 318 return flushOnQuery; 319 } 320 321 /** 322 * Set flushOnQuery to be false to stop automatically flushing the JDBC batch buffer when a query is executed. 323 */ 324 public TxScope setFlushOnQuery(boolean flushOnQuery) { 325 this.flushOnQuery = flushOnQuery; 326 return this; 327 } 328 329 /** 330 * Return the isolation level. 331 */ 332 public int getIsolationLevel() { 333 return isolation != null ? isolation.getLevel() : -1; 334 } 335 336 /** 337 * Return the Isolation level this transaction should run with. 338 */ 339 public TxIsolation getIsolation() { 340 return isolation; 341 } 342 343 /** 344 * Set the transaction isolation level this transaction should run with. 345 */ 346 public TxScope setIsolation(TxIsolation isolation) { 347 this.isolation = isolation; 348 return this; 349 } 350 351 /** 352 * Return the serverName for this transaction. If this is null then the 353 * default server (default DataSource) will be used. 354 */ 355 public String getServerName() { 356 return serverName; 357 } 358 359 /** 360 * Set the serverName (DataSource name) for which this transaction will be. If 361 * the serverName is not specified (left null) then the default server will be 362 * used. 363 */ 364 public TxScope setServerName(String serverName) { 365 this.serverName = serverName; 366 return this; 367 } 368 369 /** 370 * Return the throwable's that should cause a rollback. 371 */ 372 public ArrayList<Class<? extends Throwable>> getRollbackFor() { 373 return rollbackFor; 374 } 375 376 /** 377 * Set a Throwable that should explicitly cause a rollback. 378 */ 379 public TxScope setRollbackFor(Class<? extends Throwable> rollbackThrowable) { 380 if (rollbackFor == null) { 381 rollbackFor = new ArrayList<>(2); 382 } 383 rollbackFor.add(rollbackThrowable); 384 return this; 385 } 386 387 /** 388 * Set multiple throwable's that will cause a rollback. 389 */ 390 @SuppressWarnings("unchecked") 391 public TxScope setRollbackFor(Class<?>[] rollbackThrowables) { 392 if (rollbackFor == null) { 393 rollbackFor = new ArrayList<>(rollbackThrowables.length); 394 } 395 for (Class<?> rollbackThrowable : rollbackThrowables) { 396 rollbackFor.add((Class<? extends Throwable>) rollbackThrowable); 397 } 398 return this; 399 } 400 401 /** 402 * Return the throwable's that should NOT cause a rollback. 403 */ 404 public ArrayList<Class<? extends Throwable>> getNoRollbackFor() { 405 return noRollbackFor; 406 } 407 408 /** 409 * Add a Throwable to a list that will NOT cause a rollback. You are able to 410 * call this method multiple times with different throwable's and they will 411 * added to a list. 412 */ 413 public TxScope setNoRollbackFor(Class<? extends Throwable> noRollback) { 414 if (noRollbackFor == null) { 415 noRollbackFor = new ArrayList<>(2); 416 } 417 this.noRollbackFor.add(noRollback); 418 return this; 419 } 420 421 /** 422 * Set multiple throwable's that will NOT cause a rollback. 423 */ 424 @SuppressWarnings("unchecked") 425 public TxScope setNoRollbackFor(Class<?>[] noRollbacks) { 426 if (noRollbackFor == null) { 427 noRollbackFor = new ArrayList<>(noRollbacks.length); 428 } 429 for (Class<?> noRollback : noRollbacks) { 430 noRollbackFor.add((Class<? extends Throwable>) noRollback); 431 } 432 return this; 433 } 434 435 public boolean isBatchMode() { 436 return PersistBatch.ALL.equals(batch); 437 } 438 439 public boolean isBatchOnCascade() { 440 return PersistBatch.ALL.equals(batchOnCascade); 441 } 442}