001package com.avaje.ebean;
002
003import com.avaje.ebean.config.PersistBatch;
004
005import java.util.ArrayList;
006
007/**
008 * Holds the definition of how a transactional method should run.
009 * <p>
010 * This information matches the features of the Transactional annotation. You
011 * can use it directly with TxRunnable or TxCallable via
012 * {@link Ebean#execute(TxScope, TxCallable)} or
013 * {@link Ebean#execute(TxScope, TxRunnable)}.
014 * </p>
015 * <p>
016 * This object is used internally with the enhancement of a method with
017 * Transactional annotation.
018 * </p>
019 *
020 * @see TxCallable
021 * @see TxRunnable
022 * @see Ebean#execute(TxScope, TxCallable)
023 * @see Ebean#execute(TxScope, TxRunnable)
024 */
025public final class TxScope {
026
027  TxType type;
028
029  String serverName;
030
031  TxIsolation isolation;
032
033  PersistBatch batch;
034
035  PersistBatch batchOnCascade;
036
037  int batchSize;
038
039  boolean skipGeneratedKeys;
040
041  boolean readOnly;
042
043  ArrayList<Class<? extends Throwable>> rollbackFor;
044
045  ArrayList<Class<? extends Throwable>> noRollbackFor;
046
047  /**
048   * Helper method to create a TxScope with REQUIRES.
049   */
050  public static TxScope required() {
051    return new TxScope(TxType.REQUIRED);
052  }
053
054  /**
055   * Helper method to create a TxScope with REQUIRES_NEW.
056   */
057  public static TxScope requiresNew() {
058    return new TxScope(TxType.REQUIRES_NEW);
059  }
060
061  /**
062   * Helper method to create a TxScope with MANDATORY.
063   */
064  public static TxScope mandatory() {
065    return new TxScope(TxType.MANDATORY);
066  }
067
068  /**
069   * Helper method to create a TxScope with SUPPORTS.
070   */
071  public static TxScope supports() {
072    return new TxScope(TxType.SUPPORTS);
073  }
074
075  /**
076   * Helper method to create a TxScope with NOT_SUPPORTED.
077   */
078  public static TxScope notSupported() {
079    return new TxScope(TxType.NOT_SUPPORTED);
080  }
081
082  /**
083   * Helper method to create a TxScope with NEVER.
084   */
085  public static TxScope never() {
086    return new TxScope(TxType.NEVER);
087  }
088
089  /**
090   * Create a REQUIRED transaction scope.
091   */
092  public TxScope() {
093    this.type = TxType.REQUIRED;
094  }
095
096  /**
097   * Create with a given transaction scope type.
098   */
099  public TxScope(TxType type) {
100    this.type = type;
101  }
102
103  /**
104   * Describes this TxScope instance.
105   */
106  public String toString() {
107    return "TxScope[" + type + "] readOnly[" + readOnly + "] isolation[" + isolation
108        + "] serverName[" + serverName
109        + "] rollbackFor[" + rollbackFor + "] noRollbackFor[" + noRollbackFor + "]";
110  }
111
112  /**
113   * Return true if PersistBatch has been set.
114   */
115  public boolean isBatchSet() {
116    return batch != null && batch != PersistBatch.INHERIT;
117  }
118
119  /**
120   * Return true if batch on cascade has been set.
121   */
122  public boolean isBatchOnCascadeSet() {
123    return batchOnCascade != null && batchOnCascade != PersistBatch.INHERIT;
124  }
125
126  /**
127   * Return true if batch size has been set.
128   */
129  public boolean isBatchSizeSet() {
130    return batchSize > 0;
131  }
132
133  /**
134   * Check for batchSize being set without batch mode and use this to imply PersistBatch.ALL.
135   */
136  public void checkBatchMode() {
137    if (batchSize > 0 && notSet(batch) && notSet(batchOnCascade)) {
138      // Use setting the batchSize as implying PersistBatch.ALL for @Transactional
139      batch = PersistBatch.ALL;
140    }
141  }
142
143  /**
144   * Return true if the mode is considered not set.
145   */
146  private boolean notSet(PersistBatch batchMode) {
147    return batchMode == null || batchMode == PersistBatch.INHERIT;
148  }
149
150  /**
151   * Return the transaction type.
152   */
153  public TxType getType() {
154    return type;
155  }
156
157  /**
158   * Set the transaction type.
159   */
160  public TxScope setType(TxType type) {
161    this.type = type;
162    return this;
163  }
164
165  /**
166   * Return the batch mode.
167   */
168  public PersistBatch getBatch() {
169    return batch;
170  }
171
172  /**
173   * Set the batch mode to use.
174   */
175  public TxScope setBatch(PersistBatch batch) {
176    this.batch = batch;
177    return this;
178  }
179
180  /**
181   * Return the batch on cascade mode.
182   */
183  public PersistBatch getBatchOnCascade() {
184    return batchOnCascade;
185  }
186
187  /**
188   * Set the batch on cascade mode.
189   */
190  public TxScope setBatchOnCascade(PersistBatch batchOnCascade) {
191    this.batchOnCascade = batchOnCascade;
192    return this;
193  }
194
195  /**
196   * Return the batch size. 0 means use the default value.
197   */
198  public int getBatchSize() {
199    return batchSize;
200  }
201
202  /**
203   * Set the batch size to use.
204   */
205  public TxScope setBatchSize(int batchSize) {
206    this.batchSize = batchSize;
207    return this;
208  }
209
210  /**
211   * Set if the transaction should skip reading generated keys for inserts.
212   */
213  public TxScope setSkipGeneratedKeys() {
214    this.skipGeneratedKeys = true;
215    return this;
216  }
217
218  /**
219   * Return true if getGeneratedKeys should be skipped for this transaction.
220   */
221  public boolean isSkipGeneratedKeys() {
222    return skipGeneratedKeys;
223  }
224
225  /**
226   * Return if the transaction should be treated as read only.
227   */
228  public boolean isReadonly() {
229    return readOnly;
230  }
231
232  /**
233   * Set if the transaction should be treated as read only.
234   */
235  public TxScope setReadOnly(boolean readOnly) {
236    this.readOnly = readOnly;
237    return this;
238  }
239
240  /**
241   * Return the Isolation level this transaction should run with.
242   */
243  public TxIsolation getIsolation() {
244    return isolation;
245  }
246
247  /**
248   * Set the transaction isolation level this transaction should run with.
249   */
250  public TxScope setIsolation(TxIsolation isolation) {
251    this.isolation = isolation;
252    return this;
253  }
254
255  /**
256   * Return the serverName for this transaction. If this is null then the
257   * default server (default DataSource) will be used.
258   */
259  public String getServerName() {
260    return serverName;
261  }
262
263  /**
264   * Set the serverName (DataSource name) for which this transaction will be. If
265   * the serverName is not specified (left null) then the default server will be
266   * used.
267   */
268  public TxScope setServerName(String serverName) {
269    this.serverName = serverName;
270    return this;
271  }
272
273  /**
274   * Return the throwable's that should cause a rollback.
275   */
276  public ArrayList<Class<? extends Throwable>> getRollbackFor() {
277    return rollbackFor;
278  }
279
280  /**
281   * Set a Throwable that should explicitly cause a rollback.
282   */
283  public TxScope setRollbackFor(Class<? extends Throwable> rollbackThrowable) {
284    if (rollbackFor == null) {
285      rollbackFor = new ArrayList<Class<? extends Throwable>>(2);
286    }
287    rollbackFor.add(rollbackThrowable);
288    return this;
289  }
290
291  /**
292   * Set multiple throwable's that will cause a rollback.
293   */
294  @SuppressWarnings("unchecked")
295  public TxScope setRollbackFor(Class<?>[] rollbackThrowables) {
296    if (rollbackFor == null) {
297      rollbackFor = new ArrayList<Class<? extends Throwable>>(rollbackThrowables.length);
298    }
299    for (int i = 0; i < rollbackThrowables.length; i++) {
300      rollbackFor.add((Class<? extends Throwable>) rollbackThrowables[i]);
301    }
302    return this;
303  }
304
305  /**
306   * Return the throwable's that should NOT cause a rollback.
307   */
308  public ArrayList<Class<? extends Throwable>> getNoRollbackFor() {
309    return noRollbackFor;
310  }
311
312  /**
313   * Add a Throwable to a list that will NOT cause a rollback. You are able to
314   * call this method multiple times with different throwable's and they will
315   * added to a list.
316   */
317  public TxScope setNoRollbackFor(Class<? extends Throwable> noRollback) {
318    if (noRollbackFor == null) {
319      noRollbackFor = new ArrayList<Class<? extends Throwable>>(2);
320    }
321    this.noRollbackFor.add(noRollback);
322    return this;
323  }
324
325  /**
326   * Set multiple throwable's that will NOT cause a rollback.
327   */
328  @SuppressWarnings("unchecked")
329  public TxScope setNoRollbackFor(Class<?>[] noRollbacks) {
330    if (noRollbackFor == null) {
331      noRollbackFor = new ArrayList<Class<? extends Throwable>>(noRollbacks.length);
332    }
333    for (int i = 0; i < noRollbacks.length; i++) {
334      noRollbackFor.add((Class<? extends Throwable>) noRollbacks[i]);
335    }
336    return this;
337  }
338
339}