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