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