001package com.avaje.ebean;
002
003import com.avaje.ebean.annotation.DocStoreMode;
004import com.avaje.ebean.config.DocStoreConfig;
005import com.avaje.ebean.config.PersistBatch;
006import com.avaje.ebean.config.ServerConfig;
007
008import javax.persistence.PersistenceException;
009import javax.persistence.RollbackException;
010import java.io.Closeable;
011import java.sql.Connection;
012
013/**
014 * The Transaction object. Typically representing a JDBC or JTA transaction.
015 */
016public interface Transaction extends Closeable {
017
018  /**
019   * Read Committed transaction isolation. Same as
020   * java.sql.Connection.TRANSACTION_READ_COMMITTED.
021   */
022  int READ_COMMITTED = java.sql.Connection.TRANSACTION_READ_COMMITTED;
023
024  /**
025   * Read Uncommitted transaction isolation. Same as
026   * java.sql.Connection.TRANSACTION_READ_UNCOMMITTED.
027   */
028  int READ_UNCOMMITTED = java.sql.Connection.TRANSACTION_READ_UNCOMMITTED;
029
030  /**
031   * Repeatable read transaction isolation. Same as
032   * java.sql.Connection.TRANSACTION_REPEATABLE_READ.
033   */
034  int REPEATABLE_READ = java.sql.Connection.TRANSACTION_REPEATABLE_READ;
035
036  /**
037   * Serializable transaction isolation. Same as
038   * java.sql.Connection.TRANSACTION_SERIALIZABLE.
039   */
040  int SERIALIZABLE = java.sql.Connection.TRANSACTION_SERIALIZABLE;
041
042  /**
043   * Register a TransactionCallback with this transaction.
044   */
045  void register(TransactionCallback callback);
046
047  /**
048   * Return true if this transaction is read only.
049   */
050  boolean isReadOnly();
051
052  /**
053   * Set whether this transaction should be readOnly.
054   */
055  void setReadOnly(boolean readOnly);
056
057  /**
058   * Commit the transaction.
059   */
060  void commit() throws RollbackException;
061
062  /**
063   * Rollback the transaction.
064   */
065  void rollback() throws PersistenceException;
066
067  /**
068   * Rollback the transaction specifying a throwable that caused the rollback to
069   * occur.
070   * <p>
071   * If you are using transaction logging this will log the throwable in the
072   * transaction logs.
073   * </p>
074   */
075  void rollback(Throwable e) throws PersistenceException;
076
077  /**
078   * Mark the transaction for rollback only.
079   */
080  void setRollbackOnly();
081
082  /**
083   * If the transaction is active then perform rollback. Otherwise do nothing.
084   */
085  void end() throws PersistenceException;
086
087  /**
088   * Return true if the transaction is active.
089   */
090  boolean isActive();
091
092  /**
093   * Set the behavior for document store updates on this transaction.
094   * <p>
095   *   For example, set the mode to DocStoreEvent.IGNORE for this transaction and
096   *   then any changes via this transaction are not sent to the doc store. This
097   *   would be used when doing large bulk inserts into the database and we want
098   *   to control how that is sent to the document store.
099   * </p>
100   */
101  void setDocStoreMode(DocStoreMode mode);
102
103  /**
104   * Set the batch size to use for sending messages to the document store.
105   * <p>
106   *   You might set this if you know the changes in this transaction result in especially large or
107   *   especially small payloads and want to adjust the batch size to match.
108   * </p>
109   * <p>
110   *   Setting this overrides the default of {@link DocStoreConfig#getBulkBatchSize()}
111   * </p>
112   */
113  void setDocStoreBatchSize(int batchSize);
114
115  /**
116   * Explicitly turn off or on the cascading nature of save() and delete(). This
117   * gives the developer exact control over what beans are saved and deleted
118   * rather than Ebean cascading detecting 'dirty/modified' beans etc.
119   * <p>
120   * This is useful if you can getting back entity beans from a layer of code
121   * (potentially remote) and you prefer to have exact control.
122   * </p>
123   * <p>
124   * This may also be useful if you are using jdbc batching with jdbc drivers
125   * that do not support getGeneratedKeys.
126   * </p>
127   */
128  void setPersistCascade(boolean persistCascade);
129
130  /**
131   * Set to true when you want all loaded properties to be included in the update
132   * (rather than just the changed properties).
133   * <p>
134   * You might set this when using JDBC batch in order to get multiple updates
135   * with slightly different sets of changed properties into the same statement
136   * and hence better JDBC batch performance.
137   * </p>
138   */
139  void setUpdateAllLoadedProperties(boolean updateAllLoadedProperties);
140
141  /**
142   * Set if the L2 cache should be skipped for "find by id" and "find by natural key" queries.
143   * <p>
144   * By default {@link ServerConfig#isSkipCacheAfterWrite()} is true and that means that for
145   * "find by id" and "find by natural key" queries which normally hit L2 bean cache automatically
146   * - will not do so after a persist/write on the transaction.
147   * </p>
148   * <p>
149   * This method provides explicit control over whether "find by id" and "find by natural key"
150   * will skip the L2 bean cache or not (regardless of whether the transaction is considered "read only").
151   * </p>
152   * <p>
153   * Refer to {@link ServerConfig#setSkipCacheAfterWrite(boolean)} for configuring the default behavior
154   * for using the L2 bean cache in transactions spanning multiple query/persist requests.
155   * </p>
156   *
157   * <pre>{@code
158   *
159   *   // assume Customer has L2 bean caching enabled ...
160   *
161   *   Transaction transaction = Ebean.beginTransaction();
162   *   try {
163   *
164   *     // this uses L2 bean cache as the transaction
165   *     // ... is considered "query only" at this point
166   *     Customer.find.byId(42);
167   *
168   *     // transaction no longer "query only" once
169   *     // ... a bean has been saved etc
170   *     Ebean.save(someBean);
171   *
172   *     // will NOT use L2 bean cache as the transaction
173   *     // ... is no longer considered "query only"
174   *     Customer.find.byId(55);
175   *
176   *
177   *
178   *     // explicit control - please use L2 bean cache
179   *
180   *     transaction.setSkipCache(false);
181   *     Customer.find.byId(77); // hit the l2 bean cache
182   *
183   *
184   *     // explicit control - please don't use L2 bean cache
185   *
186   *     transaction.setSkipCache(true);
187   *     Customer.find.byId(99); // skips l2 bean cache
188   *
189   *
190   *   } finally {
191   *     transaction.end();
192   *   }
193   *
194   * }</pre>
195   *
196   * @see ServerConfig#isSkipCacheAfterWrite()
197   */
198  void setSkipCache(boolean skipCache);
199
200  /**
201   * Return true if the L2 cache should be skipped. More accurately if true then find by id
202   * and find by natural key queries should NOT automatically use the L2 bean cache.
203   */
204  boolean isSkipCache();
205
206  /**
207   * Turn on or off statement batching. Statement batching can be transparent
208   * for drivers and databases that support getGeneratedKeys. Otherwise you may
209   * wish to specifically control when batching is used via this method.
210   * <p>
211   * Refer to <code>java.sql.PreparedStatement.addBatch();</code>
212   * <p>
213   * Note that you may also wish to use the setPersistCascade method to stop
214   * save and delete cascade behaviour. You may do this to have full control
215   * over the order of execution rather than the normal cascading fashion.
216   * </p>
217   * <p>
218   * Note that the <em>execution order</em> in batch mode may be different from
219   * non batch mode execution order. Also note that <em>insert behaviour</em>
220   * may be different depending on the JDBC driver and its support for
221   * getGeneratedKeys. That is, for JDBC drivers that do not support
222   * getGeneratedKeys you may not get back the generated IDs (used for inserting
223   * associated detail beans etc).
224   * </p>
225   * <p>
226   * Calls to save(), delete(), insert() and execute() all support batch
227   * processing. This includes normal beans, MapBean, CallableSql and UpdateSql.
228   * </p>
229   * <p>
230   * The flushing of the batched statements is automatic but you can call
231   * batchFlush when you like. Note that flushing occurs when a query is
232   * executed or when you mix UpdateSql and CallableSql with save and delete of
233   * beans.
234   * </p>
235   * <p>
236   * Example: batch processing executing every 3 rows
237   * </p>
238   * 
239   * <pre>{@code
240   *
241   * String data = "This is a simple test of the batch processing"
242   *             + " mode and the transaction execute batch method";
243   * 
244   * String[] da = data.split(" ");
245   * 
246   * String sql = "{call sp_t3(?,?)}";
247   * 
248   * CallableSql cs = new CallableSql(sql);
249   * cs.registerOut(2, Types.INTEGER);
250   * 
251   * // (optional) inform eBean this stored procedure
252   * // inserts into a table called sp_test
253   * cs.addModification("sp_test", true, false, false);
254   * 
255   * Transaction txn = ebeanServer.beginTransaction();
256   * txn.setBatchMode(true);
257   * txn.setBatchSize(3);
258   * try {
259   *   for (int i = 0; i < da.length;) {
260   *     cs.setParameter(1, da[i]);
261   *     ebeanServer.execute(cs);
262   *   }
263   * 
264   *   // NB: commit implicitly flushes
265   *   txn.commit();
266   * 
267   * } finally {
268   *   txn.end();
269   * }
270   *
271   * }</pre>
272   * 
273   */
274  void setBatchMode(boolean useBatch);
275
276  /**
277   * The JDBC batch mode to use for this transaction.
278   * <p>
279   * If this is NONE then JDBC batch can still be used for each request - save(), insert(), update() or delete()
280   * and this would be useful if the request cascades to detail beans.
281   * </p>
282   *
283   * @param persistBatchMode the batch mode to use for this transaction
284   *
285   * @see com.avaje.ebean.config.ServerConfig#setPersistBatch(com.avaje.ebean.config.PersistBatch)
286   */
287  void setBatch(PersistBatch persistBatchMode);
288
289  /**
290   * Return the batch mode at the transaction level.
291   */
292  PersistBatch getBatch();
293
294  /**
295   * Set the JDBC batch mode to use for a save() or delete() request.
296   * <p>
297   * This only takes effect when batch mode on the transaction has not already meant that
298   * JDBC batch mode is being used.
299   * </p>
300   * <p>
301   * This is useful when the single save() or delete() cascades. For example, inserting a 'master' cascades
302   * and inserts a collection of 'detail' beans. The detail beans can be inserted using JDBC batch.
303   * </p>
304   *
305   * @param batchOnCascadeMode the batch mode to use per save(), insert(), update() or delete()
306   *
307   * @see com.avaje.ebean.config.ServerConfig#setPersistBatchOnCascade(com.avaje.ebean.config.PersistBatch)
308   */
309  void setBatchOnCascade(PersistBatch batchOnCascadeMode);
310
311  /**
312   * Return the batch mode at the request level (for each save(), insert(), update() or delete()).
313   */
314  PersistBatch getBatchOnCascade();
315
316  /**
317   * Specify the number of statements before a batch is flushed automatically.
318   */
319  void setBatchSize(int batchSize);
320
321  /**
322   * Return the current batch size.
323   */
324  int getBatchSize();
325
326  /**
327   * Specify if you want batched inserts to use getGeneratedKeys.
328   * <p>
329   * By default batched inserts will try to use getGeneratedKeys if it is
330   * supported by the underlying jdbc driver and database.
331   * </p>
332   * <p>
333   * You may want to turn getGeneratedKeys off when you are inserting a large
334   * number of objects and you don't care about getting back the ids.
335   * </p>
336   */
337  void setBatchGetGeneratedKeys(boolean getGeneratedKeys);
338
339  /**
340   * By default when mixing UpdateSql (or CallableSql) with Beans the batch is
341   * automatically flushed when you change (between persisting beans and
342   * executing UpdateSql or CallableSql).
343   * <p>
344   * If you want to execute both WITHOUT having the batch automatically flush
345   * you need to call this with batchFlushOnMixed = false.
346   * </p>
347   * <p>
348   * Note that UpdateSql and CallableSql are ALWAYS executed first (before the
349   * beans are executed). This is because the UpdateSql and CallableSql have
350   * already been bound to their PreparedStatements. The beans on the other hand
351   * have a 2 step process (delayed binding).
352   * </p>
353   */
354  void setBatchFlushOnMixed(boolean batchFlushOnMixed);
355
356  /**
357   * By default executing a query will automatically flush any batched
358   * statements (persisted beans, executed UpdateSql etc).
359   * <p>
360   * Calling this method with batchFlushOnQuery = false means that you can
361   * execute a query and the batch will not be automatically flushed.
362   * </p>
363   */
364  void setBatchFlushOnQuery(boolean batchFlushOnQuery);
365
366  /**
367   * Return true if the batch (of persisted beans or executed UpdateSql etc)
368   * should be flushed prior to executing a query.
369   * <p>
370   * The default is for this to be true.
371   * </p>
372   */
373  boolean isBatchFlushOnQuery();
374
375  /**
376   * The batch will be flushing automatically but you can use this to explicitly
377   * flush the batch if you like.
378   * <p>
379   * Flushing occurs automatically when:
380   * </p>
381   * <ul>
382   * <li>the batch size is reached</li>
383   * <li>A query is executed on the same transaction</li>
384   * <li>UpdateSql or CallableSql are mixed with bean save and delete</li>
385   * <li>Transaction commit occurs</li>
386   * </ul>
387   */
388  void flushBatch() throws PersistenceException;
389
390  /**
391   * Return the underlying Connection object.
392   * <p>
393   * Useful where a Developer wishes to use the JDBC API directly. Note that the
394   * commit() rollback() and end() methods on the Transaction should still be
395   * used. Calling these methods on the Connection would be a big no no unless
396   * you know what you are doing.
397   * </p>
398   * <p>
399   * Examples of when a developer may wish to use the connection directly are:
400   * Savepoints, advanced CLOB BLOB use and advanced stored procedure calls.
401   * </p>
402   */
403  Connection getConnection();
404
405  /**
406   * Add table modification information to the TransactionEvent.
407   * <p>
408   * Use this in conjunction with getConnection() and raw JDBC.
409   * </p>
410   * <p>
411   * This effectively informs Ebean of the data that has been changed by the
412   * transaction and this information is normally automatically handled by Ebean
413   * when you save entity beans or use UpdateSql etc.
414   * </p>
415   * <p>
416   * If you use raw JDBC then you can use this method to inform Ebean for the
417   * tables that have been modified. Ebean uses this information to keep its
418   * caches in synch and maintain text indexes.
419   * </p>
420   */
421  void addModification(String tableName, boolean inserts, boolean updates, boolean deletes);
422
423  /**
424   * Add an arbitrary user object to the transaction. The objects added have no
425   * impact on any internals of ebena and are solely meant as a convenient
426   * method push user information to e.g. the
427   * {@link com.avaje.ebean.event.TransactionEventListener}.
428   */
429  void putUserObject(String name, Object value);
430
431  /**
432   * Get an object added with {@link #putUserObject(String, Object)}.
433   */
434  Object getUserObject(String name);
435}