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}