Transaction Manager
The IliTransactionManager class manages so-called local transactions in which the propagation of changes of one or more IliTable objects is deferred. This is especially useful when using IliSQLTable objects. In effect, each time a row is inserted, updated, or deleted in an IliSQLTable object, one or more corresponding SQL statements are submitted to the database server to which the SQL table object is connected.
Although it is necessary to send SQL statements immediately when the IliSQLTable object is in auto-commit mode, it can be useful to retain these statements when not in auto-commit mode. Instead, the user could be allowed to make a number of changes to one or more IliSQLTable objects. The changes would be effective in local row cache so that they are reflected in all connected gadgets, but the corresponding SQL statements are retained. Later, when the user validates the changes, all SQL statements are submitted to the database server.
If all statements are accepted by the server, the transaction has succeeded and the user can issue a database commit. However, if at least one of the statements fails, the user should issue a database rollback to cancel any statement that would have succeeded before it. The user can then either make some additional changes and retry the validation process or cancel all changes locally so that the local row cache(s) of the IliSQLTable object(s) revert their state(s) to what they were before the first change.
The set of changes that have been effected in the local row cache(s) of the IliSQLTable object(s) and the corresponding SQL statements that have been retained are called a local transaction.
To participate in a local transaction, an IliTable object must be managed by an instance of the IliTransactionManager class.
A transaction manager is anonymous or named. The name space for a transaction manager is global. There can be at most one transaction manager with a given name.
The simplest way to assign a transaction manager to an IliTable object is to assign its transactionManagerName property. If a name is assigned to the property and there is no transaction manager with that name, a transaction manager is automatically created and is assigned to the IliTable object. Other table objects can then be made to share this transaction manager by assigning the same name to their transactionManagerName property. The transaction manager can then be obtained by accessing the transactionManager property of one of the table objects.
The IliSQLTable and IliMemoryTable classes are currently transaction-manager-aware classes.
Note that the following restrictions apply to the use of a transaction manager:
-
The IliTable::select and IliTable::clearRows member functions should not be called on table objects involved in a pending local transaction.
-
Nested tables should not be managed by a transaction manager. See the Parameters for more information.
The following code sample shows how a transaction manager is used:
class MyPanel: public IlvGadgetContainer { public: IliSQLTable* getTableEMP() const { ... } IliSQLTable* getTableDEPT() const { ... }
MyPanel(IlvDisplay* dpy) : IlvGadgetContainer(dpy, ...) { ... }
void initPanel() { // Could be done in Views Studio without coding, // shown here for exposition. // Ensure both tables are using the same transaction manager. getTableEMP()->setTransactionManagerName("TRANS_MGR"); getTableDEPT()->setTransactionManagerName("TRANS_MGR");
// And the same session. IliSQLSession* session = getTableEMP()->getSQLSession(); getTableDEPT()->setSQLSession(session);
// Do not auto-commit. getTableEMP()->setAutoCommit(IlvFalse); getTableDEPT()->setAutoCommit(IlvFalse); }
IliTransactionManager* getTransMgr() const { return getTableEMP()->getTransactionManager(); }
IliSQLSession* getSQLSession() const { return getTableEMP()->getEffectiveSQLSession(); }
IlBoolean isTransactionStarted() const { return getTransMgr()->isStarted(); }
void startTransaction() { getTransMgr()->start(); }
IlBoolean acceptTransaction() { if (getTransMgr()->accept()) { getTransMgr()->stop(); getSQLSession()->commit(); return IlTrue; } else { getSQLSession()->rollback(); return IlFalse; } }
void cancelTransaction() { getTransMgr()->cancel(); getTransMgr()->stop(); } }; |