![]() | ![]() |
![]() |
| Project | Ver 1.1 | Ver 1.2 | JDO | JPA | Guides | Tools |
| 1.2 | Persistence | JDO ORM | JPA ORM | Runtime | JDO Runtime | JPA Runtime | Extensions | Developer |
A Transaction forms a unit of work. The Transaction manages what happens within that unit of work, and when an error occurs the Transaction can roll back any changes performed. There are the following types of transaction.
See also :-
![]() Pessimistic transactions are the default in JDO but arent supported in JPA. They are suitable for short lived operations where no user interaction is taking place and so it is possible to block access to datastore entities for the duration of the transaction. By default JPOX does not currently lock the objects fetched in a pessimistic transaction, but you can configure this behaviour for RDBMS datastores by setting the PersistenceManagerFactory property org.jpox.rdbms.useUpdateLock to true. This will result in all "SELECT ... FROM ..." statements being changed to be "SELECT ... FROM ... FOR UPDATE". This will be applied only where the underlying RDBMS supports the "FOR UPDATE" syntax. This property has no effect on Optimistic transactions since no locking is needed there (by definition). With a pessimistic transaction JPOX will grab a datastore connection at the first operation, and maintain it for the duration of the transaction. A single connection is used for the transaction (with the exception of any Identity Generation operations which need datastore access, since these can use their own connection). In terms of the process of a pessimistic (datastore) transaction, we demonstrate this below.
So here whenever an operation is performed, JPOX pushes it straight to the datastore. Consequently any queries will always reflect the current state of all objects in use. However this mode of operation has no version checking of objects and so if they were updated by external processes in the meantime then they will overwrite those changes. It should be noted that JPOX provides two persistence properties that allow an amount of control over when flushing happens with datastore transactions.
![]() ![]() Optimistic transactions are the other option in JDO, and are the only option in JPA. They are suitable for longer lived operations maybe where user interaction is taking place and where it would be undesirable to block access to datastore entities for the duration of the transaction. The assumption is that data altered in this transaction will not be updated by other transactions during the duration of this transaction, so the changes are not propagated to the datastore until commit()/flush(). The data is checked just before commit to ensure the integrity in this respect. The most convenient way of checking data for updates is to maintain a column on each table that handles optimistic transaction data. The user will decide this when generating their MetaData. Rather than placing version/timestamp columns on all user datastore tables, JDO2/JPA1 allow the user to notate particular classes as requiring optimistic treatment. This is performed by specifying in MetaData or annotations the details of the field/column to use for storing the version - see JDO2 Versioning and JPA1 Versioning. With JDO2 the version is added in a surrogate column, whereas with JPA1 you must have a field in your class ready to store the version. In JDO2 the version is stored in a surrogate column in the datastore so it also provides a method for accessing the version of an object. You can call JDOHelper.getVersion(object) and this returns the version as an Object (typically Long or Timestamp). This will return null for a transient object, and will return the version for a persistent object. If the object is not PersistenceCapable then it will also return null. In JPA1 you can read the version by inspecting the field marked as storing the version value. In terms of the process of an optimistic transaction, we demonstrate this below.
Here no changes make it to the datastore until the user either commits the transaction, or they invoke flush(). The impact of this is that when performing a query, by default, the results may not contain the modified objects unless they are flushed to the datastore before invoking the query. Depending on whether you need the modified objects to be reflected in the results of the query governs what you do about that. If you invoke flush() just before running the query the query results will include the changes. The obvious benefit of optimistic transaction is that all changes are made in a block and version checking of objects is performed before application of changes, hence this mode copes better with external processes updating the objects. See also :-
![]() ![]() JPOX allows the ability to operate without transactions. With JDO this can be enabled by setting the 2 properties javax.jdo.option.NontransactionalRead, javax.jdo.option.NontransactionalWrite to true. With JPA this is the default behaviour. JPOX 1.2+ supports these allowing the ability to read objects and make updates outside of transactions. The important thing is that to use this mode of operation, you must enable it by setting the property (JPOX defaults to false if not set). Please be aware that any non transactional updates will typically be committed to the datastore by the subsequent transaction, with the updates being queued until that point.
![]() JPOX also allows specification of the transaction isolation level. This is specified via the PersistenceManagerFactory/EntityManagerFactory property org.jpox.transactionIsolation. It accepts the standard JDBC values of
The default is READ_COMMITTED. If the datastore doesn't support a particular isolation level then it will silently be changed to one that is supported (for example DB4O only supports READ_COMMITTED so will always use that). As an alternative you can also specify it on a per-transaction basis as follows (using the values in parentheses above).
JDO2:
org.jpox.jdo.JDOTransaction jpoxTx = (org.jpox.jdo.JDOTransaction)pm.currentTransaction();
jpoxTx.setOption("transaction.isolation", 2);
JPA1:
org.jpox.jpa.EntityTransactionImpl jpoxTx = (org.jpox.jpa.EntityTransactionImpl)pm.currentTransaction();
jpoxTx.setOption("transaction.isolation", 2); |