Committing and Aborting Transactions

When you have completed all database operations that you want to perform from within a transaction, you must commit the transaction. Committing the transaction causes the database modifications to be permanently written to the database. In most cases, committing the transaction also causes the database modifications to be flushed to stable storage.

Once a transaction has been committed, you can no longer use that same transaction handle for subsequent database operations.

Use one of the following methods to commit a transaction:

Aborting Transactions

If for some reason you do not want to commit a transaction, then call Transaction.abort(). Aborting the transaction causes JE to discard all modifications made to the database during the course of the transaction.

Most frequently you will want to call Transaction.abort() as a part of your exception handling activity. The circumstances that require you to call Transaction.abort() will vary depending on your application's activities. Certainly any time your application catches a DatabaseException, the transaction should probably be aborted.

Note that any time your application receives a DeadlockException, you must close any cursors opened for the transaction, abort the transaction and, optionally, start over again. For more information, see Transactions and Deadlocks.

For example:

import com.sleepycat.je.Transaction;
import com.sleepycat.je.DatabaseException;

...

Transaction txn = myEnv.beginTransaction(null, null);
try {
    Database myDb = myEnv.openDatabase(txn, "myDbName", null);
    txn.commit();
} catch (DatabaseException dbe) {
    txn.abort();
} 

Using Autocommit

If your application does not require atomicity for multiple database operations, then you can use JE's autocommit feature to transactionally protect your database operations. Essentially, autocommit is a convenience feature that causes JE to automatically use a transaction for those write operations that do not provide a transaction handle.

To use autocommit:

  1. Open your environment and database such that they support transactions. See Enabling and Starting Transactions for a description of how to do this.

  2. Do not provide a transaction handle for the database put or delete operation. Instead, simply specify null for the transaction parameter. If you are using a cursor, do not provide a transaction handle when you open the cursor.

Note that when you use autocommit, there is no opportunity for you to explicitly abort the operation. JE, however, will abort the operation if it encounters an error during the write.

For example:

import com.sleepycat.je.Environment;
import com.sleepycat.je.EnvironmentConfig;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.DatabaseConfig;
import com.sleepycat.je.Database;

...

// Open the environment and database such that transactions 
// are supported
EnvironmentConfig myEnvConfig = new EnvironmentConfig();
DatabaseConfig myDbConfig = new DatabaseConfig();
myEnvConfig.setTransactional(true);
myDbConfig.setTransactional(true);
Environment myEnv = 
        new Environment(new File("/my/env/home"), myEnvConfig);

try {
    // This database is opened from within a transaction using autocommit
    // because the database configuration specifies transactions.
    // As a result follow-on database operations can use transactions.
    Database myDb = myEnv.openDatabase(null, "myDbName", myDbConfig);

    String aKey = "myFirstKey";
    String aData = "myFirstData";

    DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));
    DatabaseEntry theData = new DatabaseEntry(aData.getBytes("UTF-8"));

    // This database put is also transactionally protected
    // using autocommit.
    myDatabase.put(null, theKey, theData); 
} catch (Exception e) {
    // Exception handling goes here.
}