You can cause transient instances to observe transaction boundaries, such that their state is preserved at commit and restored on rollback. A transient instance that observes transaction boundaries is called a transient-transactional instance. Support for transient-transactional instances is optional; their use requires support of the optional TransientTransactional feature. If your implementation does not support TransientTransactional, it will not include the functionality that causes the state transitions associated with transient-transactional instances.
You can use the following PersistenceManager methods to make transient instances transactional:
void makeTransactional(Object obj); void makeTransactionalAll(Object[] objs); void makeTransactionalAll(Collection objs);
After these methods complete, the instances observe transaction boundaries. If the transaction commits, the transient-transactional instances retain their values. The makeTransactional( ) method throws a JDOUnsupportedOptionException if you pass a transient instance as a parameter and the implementation does not support the optional TransientTransactional feature.
If the call to makeTransactional( ) is made within the current transaction and the transaction is rolled back, the fields of the transient-transactional instances are restored to the values they had when makeTransactional( ) was called, using their captured before image (discussed in Chapter 14). If the call to makeTransactional( ) is made before the beginning of the current transaction and the transaction is rolled back, the fields are restored to their values as of the beginning of the transaction.
The PersistenceManager also provides makeNontransactional( ) to make a persistent instance nontransactional. Chapter 14 covers this in detail.
Transient-transactional instances are either clean or dirty, based on whether they have been modified in the current transaction. If a clean instance is not modified, it remains clean. If a clean instance is modified, its field values are saved. If the transaction rolls back, field values of dirty instances are restored from the saved field values. If the transaction commits, the saved field values are discarded. For either commit or rollback, dirty instances become clean.
Managing the behavior of transient-transactional instances requires additional lifecycle states and state transitions. Similar to persistent instances, transient-transactional instances have the transient-clean and transient-dirty lifecycle states to indicate their change status. An instance can be in the transient-clean or transient-dirty state only if the implementation supports the optional TransientTransactional feature.
A transient-transactional instance that has not been changed in the current transaction is in the transient-clean state. When a transient instance is passed as a parameter to makeTransactional( ), it transitions to the transient-clean state. You can make changes to a transient-clean instance outside of a transaction without changing its lifecycle state. Chapter 14 covers nontransactional access.
If you change any managed field of a transient-clean instance in a transaction, it transitions to the transient-dirty state. This is similar to a persistent-clean instance transitioning to persistent-dirty. When you first modify a managed field of a transient-clean instance, before the field's value is changed, the PersistenceManager saves the instance's fields in a before image that is used if a rollback occurs.
Table 13-1 specifies the values that the JDOHelper lifecycle-state interrogation methods return for the three transient lifecycle states.
State of Instance |
isPersistent( ) |
isTransactional( ) |
isDirty( ) |
isNew( ) |
isDeleted( ) |
---|---|---|---|---|---|
Transient |
false |
false |
false |
false |
false |
Transient-clean |
false |
true |
false |
false |
false |
Transient-dirty |
false |
true |
true |
false |
false |
Figure 13-1 illustrates the state transitions that occur with transient-transactional instances.
If you pass a transient-clean instance to makeNontransactional( ), it transitions to transient; but if you pass a transient-dirty instance, a JDOUserException is thrown.
At commit, a transient-dirty instance transitions to transient-clean and it retains its values. If a transaction rollback occurs and the instance was made transactional in the current transaction, the instance's field values are restored with the before image to the values they had when makeTransactional( ) was called.
If an instance was made transactional in a previous transaction and a transaction rollback occurs, the instance's fields are restored to their values as of the beginning of the current transaction. When transaction-rollback processing completes, the before images of transient-transactional instances are discarded and the instances transition to transient-clean.
If you pass a transient-dirty instance to makePersistent( ), it transitions to persistent-new. What happens if a transaction rollback occurs? The before image that was saved when the instance transitioned to transient-dirty is used to restore the instance. However, as with any persistent-new instance, the instance reverts to transient at rollback, even if it was previously a transient-transactional instance.