5. Transaction Control 


Contents

5.1. Introduction

5.2. Explicit Transaction Control

5.2.1. Using a Transaction Object

5.2.2. Using Database Methods


5.1. Introduction

Objects must always be written to the database in the context of a transaction. This ensures that either all updates are done, or none are. Transactions can be manually controlled, or started automatically by the persistence layer. When a Database update, insert, or delete method is called, the persistence layer checks to see if a transaction is in progress. If no transaction is in progress, then it starts one automatically. If the persistence layer started the transaction, it will automatically commit it once the database update is complete, or roll it back if an error occurs.

This automatic transaction feature of the persistence layer can be disabled by checking the Disable automatic transactions option in the Transactions Panel of the mapping tool DB Configuration form. If automatic transactions are disabled, the persistence layer will never issue any transaction demarcation commands. In this case, if transactions are not explicitly started and committed, objects will not be written to the database. Since you still have the flexibility to manually control transactions when automatic transactions are enabled, we recommend leaving the automatic transaction feature of VBSF enabled to act as a safety net. Disabling automatic transactions might still be necessary when using VBSF in conjunction with a middleware based product that manages transactions.

When a transaction is explicitly started by a client application, the persistence layer does not issue any start, commit, or rollback transaction commands. In this case, it is the responsibility of the client application to commit a transaction once completed, or to roll it back when an error occurs. When manually controlling transactions, it is specially important to explicitly issue a rollback in the event of a lost connection error on a pooled connection. This ensures that the persistence layer connection pool clean-up utility, if enabled, will be able to automatically replace the stale connection when the database comes back on-line.

In the case of  manually controlled transactions the persistence layer does not allow for an object to be updated more than once within the context of the same transaction. Duplicate calls to Database.update() with the same persistent object as argument within the same transaction are silently ignored. For this reason, it is best to start a transaction after changes to all objects involved in the transaction have been completed.

 

5.2. Explicit Transaction Control

VBSF supports two ways of providing explicit transaction control:

  1. Using a Transaction or RelativeTransaction object.
  2. Using the transaction control methods provided in the Database class.

 

5.2.1 Using a Transaction or RelativeTransaction Object

VBSF provides a Transaction class that implements the ODMG 2.0 Java Binding Specification Transaction class. A Transaction object must be associated with a Database object when it is created. This is done by passing a Database object as argument to the constructor. The Transaction class supplies methods to begin, commit, abort, and checkpoint a transaction. Below is an example taken from the sample vcontactdemo application that demonstrates how a Transaction object is used:

Contact currContact = (Contact)db.lookup(Contact.class,6);
currContact.setLastName("DUCK");
Contact currContact2 = (Contact)db.lookup(Contact.class,10);
currContact2.setFirstName("RON");
Transaction txn = new Transaction(db);
txn.begin();
int rowCount = db.update(currContact);
rowCount += db.update(currContact2);
txn.commit();


The example above retrieves two Contact objects from the database, modifies them, and writes the changes to the database in the context of a transaction. Note that, as recommended in the first paragraph of the introduction,  the transaction is started after changes to both objects have been completed, so only calls to db.update() are placed inside the transaction demarcation statements. This is consistent to with a short transaction paradigm. Compare the above example with the one below, which depicts a long transaction paradigm that has the object modification statements placed inside the transaction demarcation statements:

Contact currContact = (Contact)db.lookup(Contact.class,6);
Contact currContact2 = (Contact)db.lookup(Contact.class,10);
Transaction txn = new Transaction(db);
txn.begin();
currContact.setLastName("DUCK");
currContact2.setFirstName("RON");
int rowCount = db.update(currContact);
rowCount += db.update(currContact2);
txn.commit();


The above code could result in a very long transaction if the setLastName and setFirstName calls occur inside in a GUI edit screen. The user could go to lunch while inside the edit screen, and leave the transaction pending. In addition, a long transaction paradigm could also lead to multiple updates to the same object within the same transaction, which is illegal in VBSF. Below is an example that demonstrates this invalid scenario:

Contact currContact = (Contact)db.lookup(Contact.class,6);
Transaction txn = new Transaction(db);
txn.begin();
currContact.setLastName("DUCK");
int rowCount = db.update(currContact);
currContact.setFirstName("HOWARD");
rowCount += db.update(currContact);  //call ignored
txn.commit();


You can also use a RelativeTransaction object instead of a Transaction object. The RelativeTransaction class is identical to the Transaction class, except that the begin() operation is conditional on whether another transaction for the same Database object is not already in progress, and the commit(), abort() and checkpoint() operations are performed only if the transaction was started locally by the RelativeTransaction object. See the RelativeTransaction class in the API Reference for details.

 

5.2.2 Using Database Methods

Transactions can also be demarcated by using the following transaction control method provided in the Database class:

The example below is also taken from the sample vcontactdemo application. It demonstrates explicit transaction control using the methods provided in the Database class:

Contact currContact = (Contact)db.lookup(Contact.class,2);
currContact.setLastName("BAND");
currContact.setSecondName(null);
Contact currContact2 = (Contact)db.lookup(Contact.class,15);
currContact2.setFirstName("MIKE");
db.startTrans();
int rowCount = db.update(currContact);
rowCount += db.update(currContact2);
db.commit();

 

Next Section

Return to Table of Contents