A database transaction is a set of operations (create, read, update, or delete) that either succeed or fail as a single operation. The database discards, or rolls back, unsuccessful transactions, leaving the database in its original state. In EclipseLink, transactions are encapsulated by the Unit of Work object. Using the Unit of Work, you can transactionally modify objects directly or by way of a Java 2 Enterprise Edition (J2EE) external transaction controller such as the Java Transaction API (JTA).
Unit Of Work
The EclipseLink Unit of Work simplifies transactions and improves transactional performance. It is the preferred method of writing to a database in EclipseLink because it:
- sends a minimal amount of SQL to the database during the commit by updating only the exact changes down to the field level
- reduces database traffic by isolating transaction operations in their own memory space
- optimizes cache synchronization, in applications that use multiple caches, by passing change sets (rather than objects) between caches
- isolates object modifications in their own transaction space to allow parallel transactions on the same objects
- ensures referential integrity and minimizes deadlocks by automatically maintaining SQL ordering
- orders database inserts, updates, and deletes to maintain referential integrity for mapped objects
- resolves bidirectional references automatically
- frees the application from tracking or recording its changes
- simplifies persistence with persistence by reachability
Acquiring a Unit of Work
This example shows how to acquire a Unit of Work from a client session object.
Server server = (Server) SessionManager.getManager().getSession(sessionName, MyServerSession.class.getClassLoader()); Session session = (Session) server.acquireClientSession(); UnitOfWork uow = session.acquireUnitOfWork();
You can acquire a Unit of Work from any session type. Note that you do not need to create a new session and login before every transaction. The Unit of Work is valid until the commit or release method is called. After a commit or release, a Unit of Work is not valid even if the transaction fails and is rolled back.
Creating an Object
When you create new objects in the Unit of Work, use the registerObject method to ensure that the Unit of Work writes the objects to the database at commit time. The Unit of Work calculates commit order using foreign key information from one-to-one and one-to-many mappings. If you encounter constraint problems during commit, verify your mapping definitions. The order in which you register objects with the registerObject method does not affect the commit order.
Creating an Object: Preferred Method
UnitOfWork uow = session.acquireUnitOfWork(); Pet pet = new Pet(); Pet petClone = (Pet)uow.registerObject(pet); petClone.setId(100); petClone.setName("Fluffy"); petClone.setType("Cat"); uow.commit();
Creating an Object: Alternative Method
UnitOfWork uow = session.acquireUnitOfWork(); Pet pet = new Pet(); pet.setId(100); pet.setName("Fluffy"); pet.setType("Cat"); uow.registerObject(pet); uow.commit();
Both approaches produce the following SQL: INSERT INTO PET (ID, NAME, TYPE, PET_OWN_ID) VALUES (100, 'Fluffy', 'Cat', NULL)
However the first example is preferred since it gets you into the pattern of working with clones and provides the most flexibility for future code changes. Working with combinations of new objects and clones can lead to confusion and unwanted results.
To delete objects in a Unit of Work, use the deleteObject or deleteAllObjects method. When you delete an object that is not already registered in the Unit of Work, the Unit of Work registers the object automatically.
Deleting an Object
UnitOfWork uow = session.acquireUnitOfWork(); pet petClone = (Pet)uow.readObject(Pet.class); uow.deleteObject(petClone); uow.commit();
The above code generates the following SQL:
DELETE FROM PET WHERE (ID = 100)