001package io.ebean;
002
003import io.ebean.annotation.DocStoreMode;
004import io.ebean.annotation.PersistBatch;
005import io.ebean.config.DocStoreConfig;
006import io.ebean.config.ServerConfig;
007
008import javax.persistence.PersistenceException;
009import java.sql.Connection;
010
011/**
012 * The Transaction object. Typically representing a JDBC or JTA transaction.
013 */
014public interface Transaction extends AutoCloseable {
015
016  /**
017   * Return the current transaction (of the default database) or null if there is
018   * no current transaction in scope.
019   * <p>
020   * This is the same as <code>DB.currentTransaction()</code>
021   * </p>
022   * <p>
023   * This returns the current transaction for the 'default server'.  If you are using
024   * multiple EbeanServer's then use {@link DB#currentTransaction()}.
025   * </p>
026   *
027   * @see DB#currentTransaction()
028   * @see Database#currentTransaction()
029   */
030  static Transaction current() {
031    return Ebean.currentTransaction();
032  }
033
034  /**
035   * Read Committed transaction isolation. Same as
036   * java.sql.Connection.TRANSACTION_READ_COMMITTED.
037   */
038  int READ_COMMITTED = java.sql.Connection.TRANSACTION_READ_COMMITTED;
039
040  /**
041   * Read Uncommitted transaction isolation. Same as
042   * java.sql.Connection.TRANSACTION_READ_UNCOMMITTED.
043   */
044  int READ_UNCOMMITTED = java.sql.Connection.TRANSACTION_READ_UNCOMMITTED;
045
046  /**
047   * Repeatable read transaction isolation. Same as
048   * java.sql.Connection.TRANSACTION_REPEATABLE_READ.
049   */
050  int REPEATABLE_READ = java.sql.Connection.TRANSACTION_REPEATABLE_READ;
051
052  /**
053   * Serializable transaction isolation. Same as
054   * java.sql.Connection.TRANSACTION_SERIALIZABLE.
055   */
056  int SERIALIZABLE = java.sql.Connection.TRANSACTION_SERIALIZABLE;
057
058  /**
059   * Register a TransactionCallback with this transaction.
060   */
061  void register(TransactionCallback callback);
062
063  /**
064   * Set a label on the transaction.
065   * <p>
066   * This label is used to group transaction execution times for performance metrics reporting.
067   * </p>
068   */
069  void setLabel(String label);
070
071  /**
072   * Return true if this transaction is read only.
073   */
074  boolean isReadOnly();
075
076  /**
077   * Set whether this transaction should be readOnly.
078   */
079  void setReadOnly(boolean readOnly);
080
081  /**
082   * Commits the transaction at this point with the expectation that another
083   * commit (or rollback or end) will occur later to complete the transaction.
084   * <p>
085   * This is similar to commit() but leaves the transaction "Active".
086   * </p>
087   * <h3>Functions</h3>
088   * <ul>
089   * <li>Flush the JDBC batch buffer</li>
090   * <li>Call commit on the underlying JDBC connection</li>
091   * <li>Trigger any registered TransactionCallbacks</li>
092   * <li>Perform post-commit processing updating L2 cache, ElasticSearch etc</li>
093   * </ul>
094   */
095  void commitAndContinue();
096
097  /**
098   * Commit the transaction.
099   * <p>
100   * This performs commit and completes the transaction closing underlying resources and
101   * marking the transaction as "In active".
102   * </p>
103   * <h3>Functions</h3>
104   * <ul>
105   * <li>Flush the JDBC batch buffer</li>
106   * <li>Call commit on the underlying JDBC connection</li>
107   * <li>Trigger any registered TransactionCallbacks</li>
108   * <li>Perform post-commit processing updating L2 cache, ElasticSearch etc</li>
109   * <li>Close any underlying resources, closing the underlying JDBC connection</li>
110   * <li>Mark the transaction as "Inactive"</li>
111   * </ul>
112   */
113  void commit();
114
115  /**
116   * Rollback the transaction.
117   * <p>
118   * This performs rollback, closes underlying resources and marks the transaction as "In active".
119   * </p>
120   * <h3>Functions</h3>
121   * <ul>
122   * <li>Call rollback on the underlying JDBC connection</li>
123   * <li>Trigger any registered TransactionCallbacks</li>
124   * <li>Close any underlying resources, closing the underlying JDBC connection</li>
125   * <li>Mark the transaction as "Inactive"</li>
126   * </ul>
127   */
128  void rollback() throws PersistenceException;
129
130  /**
131   * Rollback the transaction specifying a throwable that caused the rollback to
132   * occur.
133   * <p>
134   * If you are using transaction logging this will log the throwable in the
135   * transaction logs.
136   * </p>
137   */
138  void rollback(Throwable e) throws PersistenceException;
139
140  /**
141   * Set when we want nested transactions to use Savepoint's.
142   * <p>
143   * This means that for a nested transaction:
144   * <ul>
145   * <li>begin transaction maps to creating a savepoint</li>
146   * <li>commit transaction maps to releasing a savepoint</li>
147   * <li>rollback transaction maps to rollback a savepoint</li>
148   * </ul>
149   */
150  void setNestedUseSavepoint();
151
152  /**
153   * Mark the transaction for rollback only.
154   */
155  void setRollbackOnly();
156
157  /**
158   * Return true if the transaction is marked as rollback only.
159   */
160  boolean isRollbackOnly();
161
162  /**
163   * If the transaction is active then perform rollback. Otherwise do nothing.
164   */
165  void end();
166
167  /**
168   * Synonym for end() to support AutoClosable.
169   */
170  @Override
171  void close();
172
173  /**
174   * Return true if the transaction is active.
175   */
176  boolean isActive();
177
178  /**
179   * Set the behavior for document store updates on this transaction.
180   * <p>
181   * For example, set the mode to DocStoreEvent.IGNORE for this transaction and
182   * then any changes via this transaction are not sent to the doc store. This
183   * would be used when doing large bulk inserts into the database and we want
184   * to control how that is sent to the document store.
185   * </p>
186   */
187  void setDocStoreMode(DocStoreMode mode);
188
189  /**
190   * Set the batch size to use for sending messages to the document store.
191   * <p>
192   * You might set this if you know the changes in this transaction result in especially large or
193   * especially small payloads and want to adjust the batch size to match.
194   * </p>
195   * <p>
196   * Setting this overrides the default of {@link DocStoreConfig#getBulkBatchSize()}
197   * </p>
198   */
199  void setDocStoreBatchSize(int batchSize);
200
201  /**
202   * Explicitly turn off or on the cascading nature of save() and delete(). This
203   * gives the developer exact control over what beans are saved and deleted
204   * rather than Ebean cascading detecting 'dirty/modified' beans etc.
205   * <p>
206   * This is useful if you can getting back entity beans from a layer of code
207   * (potentially remote) and you prefer to have exact control.
208   * </p>
209   * <p>
210   * This may also be useful if you are using jdbc batching with jdbc drivers
211   * that do not support getGeneratedKeys.
212   * </p>
213   */
214  void setPersistCascade(boolean persistCascade);
215
216  /**
217   * Set to true when you want all loaded properties to be included in the update
218   * (rather than just the changed properties).
219   * <p>
220   * You might set this when using JDBC batch in order to get multiple updates
221   * with slightly different sets of changed properties into the same statement
222   * and hence better JDBC batch performance.
223   * </p>
224   */
225  void setUpdateAllLoadedProperties(boolean updateAllLoadedProperties);
226
227  /**
228   * Set if the L2 cache should be skipped for "find by id" and "find by natural key" queries.
229   * <p>
230   * By default {@link ServerConfig#isSkipCacheAfterWrite()} is true and that means that for
231   * "find by id" and "find by natural key" queries which normally hit L2 bean cache automatically
232   * - will not do so after a persist/write on the transaction.
233   * </p>
234   * <p>
235   * This method provides explicit control over whether "find by id" and "find by natural key"
236   * will skip the L2 bean cache or not (regardless of whether the transaction is considered "read only").
237   * </p>
238   * <p>
239   * Refer to {@link ServerConfig#setSkipCacheAfterWrite(boolean)} for configuring the default behavior
240   * for using the L2 bean cache in transactions spanning multiple query/persist requests.
241   * </p>
242   *
243   * <pre>{@code
244   *
245   *   // assume Customer has L2 bean caching enabled ...
246   *
247   *   try (Transaction transaction = DB.beginTransaction()) {
248   *
249   *     // this uses L2 bean cache as the transaction
250   *     // ... is considered "query only" at this point
251   *     Customer.find.byId(42);
252   *
253   *     // transaction no longer "query only" once
254   *     // ... a bean has been saved etc
255   *     someBean.save();
256   *
257   *     // will NOT use L2 bean cache as the transaction
258   *     // ... is no longer considered "query only"
259   *     Customer.find.byId(55);
260   *
261   *
262   *
263   *     // explicit control - please use L2 bean cache
264   *
265   *     transaction.setSkipCache(false);
266   *     Customer.find.byId(77); // hit the l2 bean cache
267   *
268   *
269   *     // explicit control - please don't use L2 bean cache
270   *
271   *     transaction.setSkipCache(true);
272   *     Customer.find.byId(99); // skips l2 bean cache
273   *
274   *
275   *     transaction.commit();
276   *   }
277   *
278   * }</pre>
279   *
280   * @see ServerConfig#isSkipCacheAfterWrite()
281   */
282  void setSkipCache(boolean skipCache);
283
284  /**
285   * Return true if the L2 cache should be skipped. More accurately if true then find by id
286   * and find by natural key queries should NOT automatically use the L2 bean cache.
287   */
288  boolean isSkipCache();
289
290  /**
291   * Turn on or off use of JDBC statement batching.
292   * <p>
293   * Calls to save(), delete(), insert() and execute() all support batch
294   * processing. This includes normal beans, CallableSql and UpdateSql.
295   * </p>
296   *
297   * <pre>{@code
298   *
299   * try (Transaction transaction = server.beginTransaction()) {
300   *
301   *   // turn on JDBC batch
302   *   transaction.setBatchMode(true);
303   *
304   *   // tune the batch size
305   *   transaction.setBatchSize(50);
306   *
307   *   ...
308   *
309   *   transaction.commit();
310   * }
311   *
312   * }</pre>
313   *
314   * <h3>getGeneratedKeys</h3>
315   * <p>
316   * Often with large batch inserts we want to turn off getGeneratedKeys. We do
317   * this via {@link #setBatchGetGeneratedKeys(boolean)}.
318   * Also note that some JDBC drivers do not support getGeneratedKeys in JDBC batch mode.
319   * </p>
320   * <pre>{@code
321   *
322   * try (Transaction transaction = server.beginTransaction()) {
323   *
324   *   transaction.setBatchMode(true);
325   *   transaction.setBatchSize(100);
326   *   // insert but don't bother getting back the generated keys
327   *   transaction.setBatchGetGeneratedKeys(false);
328   *
329   *
330   *   // perform lots of inserts ...
331   *   ...
332   *
333   *   transaction.commit();
334   * }
335   *
336   * }</pre>
337   *
338   * <h3>Flush</h3>
339   * <p>
340   * The batch is automatically flushed when it hits the batch size and also when we
341   * execute queries or when we mix UpdateSql and CallableSql with save and delete of
342   * beans.
343   * </p>
344   * <p>
345   * We use {@link #flush()} to explicitly flush the batch and we can use
346   * {@link #setBatchFlushOnQuery(boolean)} and {@link #setBatchFlushOnMixed(boolean)}
347   * to control the automatic flushing behaviour.
348   * </p>
349   * <p>
350   * Example: batch processing of CallableSql executing every 10 rows
351   * </p>
352   *
353   * <pre>{@code
354   *
355   * String data = "This is a simple test of the batch processing"
356   *             + " mode and the transaction execute batch method";
357   *
358   * String[] da = data.split(" ");
359   *
360   * String sql = "{call sp_t3(?,?)}";
361   *
362   * CallableSql cs = new CallableSql(sql);
363   * cs.registerOut(2, Types.INTEGER);
364   *
365   * // (optional) inform Ebean this stored procedure
366   * // inserts into a table called sp_test
367   * cs.addModification("sp_test", true, false, false);
368   *
369   * try (Transaction txn = DB.beginTransaction()) {
370   *   txn.setBatchMode(true);
371   *   txn.setBatchSize(10);
372   *
373   *   for (int i = 0; i < da.length;) {
374   *     cs.setParameter(1, da[i]);
375   *     DB.execute(cs);
376   *   }
377   *
378   *   // Note: commit implicitly flushes
379   *   txn.commit();
380   * }
381   *
382   * }</pre>
383   */
384  void setBatchMode(boolean useBatch);
385
386  /**
387   * Return the batch mode at the transaction level.
388   */
389  boolean isBatchMode();
390
391  /**
392   * Set the JDBC batch mode to use for a save() or delete() when cascading to children.
393   * <p>
394   * This only takes effect when batch mode on the transaction has not already meant that
395   * JDBC batch mode is being used.
396   * </p>
397   * <p>
398   * This is useful when the single save() or delete() cascades. For example, inserting a 'master' cascades
399   * and inserts a collection of 'detail' beans. The detail beans can be inserted using JDBC batch.
400   * </p>
401   * <p>
402   * This is effectively already turned on for all platforms apart from older Sql Server.
403   * </p>
404   *
405   * @param batchMode the batch mode to use per save(), insert(), update() or delete()
406   * @see io.ebean.config.ServerConfig#setPersistBatchOnCascade(PersistBatch)
407   */
408  void setBatchOnCascade(boolean batchMode);
409
410  /**
411   * Return the batch mode at the request level.
412   */
413  boolean isBatchOnCascade();
414
415  /**
416   * Specify the number of statements before a batch is flushed automatically.
417   */
418  void setBatchSize(int batchSize);
419
420  /**
421   * Return the current batch size.
422   */
423  int getBatchSize();
424
425  /**
426   * Specify if you want batched inserts to use getGeneratedKeys.
427   * <p>
428   * By default batched inserts will try to use getGeneratedKeys if it is
429   * supported by the underlying jdbc driver and database.
430   * </p>
431   * <p>
432   * You may want to turn getGeneratedKeys off when you are inserting a large
433   * number of objects and you don't care about getting back the ids.
434   * </p>
435   */
436  void setBatchGetGeneratedKeys(boolean getGeneratedKeys);
437
438  /**
439   * By default when mixing UpdateSql (or CallableSql) with Beans the batch is
440   * automatically flushed when you change (between persisting beans and
441   * executing UpdateSql or CallableSql).
442   * <p>
443   * If you want to execute both WITHOUT having the batch automatically flush
444   * you need to call this with batchFlushOnMixed = false.
445   * </p>
446   * <p>
447   * Note that UpdateSql and CallableSql are ALWAYS executed first (before the
448   * beans are executed). This is because the UpdateSql and CallableSql have
449   * already been bound to their PreparedStatements. The beans on the other hand
450   * have a 2 step process (delayed binding).
451   * </p>
452   */
453  void setBatchFlushOnMixed(boolean batchFlushOnMixed);
454
455  /**
456   * By default executing a query will automatically flush any batched
457   * statements (persisted beans, executed UpdateSql etc).
458   * <p>
459   * Calling this method with batchFlushOnQuery = false means that you can
460   * execute a query and the batch will not be automatically flushed.
461   * </p>
462   */
463  void setBatchFlushOnQuery(boolean batchFlushOnQuery);
464
465  /**
466   * Return true if the batch (of persisted beans or executed UpdateSql etc)
467   * should be flushed prior to executing a query.
468   * <p>
469   * The default is for this to be true.
470   * </p>
471   */
472  boolean isBatchFlushOnQuery();
473
474  /**
475   * The batch will be flushing automatically but you can use this to explicitly
476   * flush the batch if you like.
477   * <p>
478   * Flushing occurs automatically when:
479   * </p>
480   * <ul>
481   * <li>the batch size is reached</li>
482   * <li>A query is executed on the same transaction</li>
483   * <li>UpdateSql or CallableSql are mixed with bean save and delete</li>
484   * <li>Transaction commit occurs</li>
485   * <li>A getter method is called on a batched bean</li>
486   * </ul>
487   */
488  void flush() throws PersistenceException;
489
490  /**
491   * This is a synonym for flush() and will be deprecated.
492   * <p>
493   * flush() is preferred as it matches the JPA flush() method.
494   * </p>
495   */
496  void flushBatch() throws PersistenceException;
497
498  /**
499   * Return the underlying Connection object.
500   * <p>
501   * Useful where a Developer wishes to use the JDBC API directly. Note that the
502   * commit() rollback() and end() methods on the Transaction should still be
503   * used. Calling these methods on the Connection would be a big no no unless
504   * you know what you are doing.
505   * </p>
506   * <p>
507   * Examples of when a developer may wish to use the connection directly are:
508   * Savepoints, advanced CLOB BLOB use and advanced stored procedure calls.
509   * </p>
510   */
511  Connection getConnection();
512
513  /**
514   * Add table modification information to the TransactionEvent.
515   * <p>
516   * Use this in conjunction with getConnection() and raw JDBC.
517   * </p>
518   * <p>
519   * This effectively informs Ebean of the data that has been changed by the
520   * transaction and this information is normally automatically handled by Ebean
521   * when you save entity beans or use UpdateSql etc.
522   * </p>
523   * <p>
524   * If you use raw JDBC then you can use this method to inform Ebean for the
525   * tables that have been modified. Ebean uses this information to keep its
526   * caches in synch and maintain text indexes.
527   * </p>
528   */
529  void addModification(String tableName, boolean inserts, boolean updates, boolean deletes);
530
531  /**
532   * Add an arbitrary user object to the transaction. The objects added have no
533   * impact on any internals of ebean and are solely meant as a convenient
534   * method push user information (although somewhat replaced by TransactionCallback).
535   */
536  void putUserObject(String name, Object value);
537
538  /**
539   * Get an object added with {@link #putUserObject(String, Object)}.
540   */
541  Object getUserObject(String name);
542}