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