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}