Difference between revisions of "EclipseLink/Examples/JPA/ORMTransactions"

From Eclipsepedia

Jump to: navigation, search
(New page: 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 transa...)
 
(Deleting an Object)
 
(4 intermediate revisions by 2 users not shown)
Line 16: Line 16:
 
This example shows how to acquire a Unit of Work from a client session object.  
 
This example shows how to acquire a Unit of Work from a client session object.  
  
<code><pre>
+
<source lang="java">
 
Server server = (Server) SessionManager.getManager().getSession(sessionName, MyServerSession.class.getClassLoader());
 
Server server = (Server) SessionManager.getManager().getSession(sessionName, MyServerSession.class.getClassLoader());
 
Session session = (Session) server.acquireClientSession();
 
Session session = (Session) server.acquireClientSession();
 
UnitOfWork uow = session.acquireUnitOfWork();
 
UnitOfWork uow = session.acquireUnitOfWork();
</pre></code>
+
</source>
  
 
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.
 
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 ==
+
== Creating Objects ==
 
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.
 
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 ===
 
=== Creating an Object: Preferred Method ===
<code><pre>
+
<source lang="java">
 
UnitOfWork uow = session.acquireUnitOfWork();
 
UnitOfWork uow = session.acquireUnitOfWork();
 
Pet pet = new Pet();
 
Pet pet = new Pet();
Line 36: Line 36:
 
petClone.setType("Cat");
 
petClone.setType("Cat");
 
uow.commit();
 
uow.commit();
</pre></code>
+
</source>
  
 
=== Creating an Object: Alternative Method ===
 
=== Creating an Object: Alternative Method ===
<code><pre>
+
<source lang="java">
 
UnitOfWork uow = session.acquireUnitOfWork();
 
UnitOfWork uow = session.acquireUnitOfWork();
 
Pet pet = new Pet();
 
Pet pet = new Pet();
Line 47: Line 47:
 
uow.registerObject(pet);
 
uow.registerObject(pet);
 
uow.commit();
 
uow.commit();
</pre></code>
+
</source>
  
 
Both approaches produce the following SQL:
 
Both approaches produce the following SQL:
 +
<source lang="sql">
 
INSERT INTO PET (ID, NAME, TYPE, PET_OWN_ID) VALUES (100, 'Fluffy', 'Cat', NULL)
 
INSERT INTO PET (ID, NAME, TYPE, PET_OWN_ID) VALUES (100, 'Fluffy', 'Cat', NULL)
 +
</source>
  
 
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.
 
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.
 +
 +
== Modifying Objects ==
 +
=== Modifying an Object: Using the Registration Step ===
 +
In this example, a Pet is read prior to a Unit of Work: the variable pet is the cache copy for that Pet. Inside of the Unit of Work, we must register the cache copy to get a working copy. We then modify the working copy and commit the Unit of Work.
 +
 +
<source lang="java">
 +
// Read in any pet.
 +
Pet pet = (Pet)session.readObject(Pet.class);
 +
UnitOfWork uow = session.acquireUnitOfWork();
 +
Pet petClone = (Pet) uow.registerObject(pet);
 +
petClone.setName("Furry");
 +
uow.commit();
 +
</source>
 +
 +
=== Modifying an Object: Skipping the Registration Step ===
 +
In this example, we take advantage of the fact that you can query through a Unit of Work and get back clones, saving the registration step. However, the drawback is that we do not have a handle to the cache copy. If we wanted to do something with the updated Pet after commit, we would have to query the session to get it (remember that after a Unit of Work is committed, its
 +
clones are invalid and must not be used).
 +
 +
<source lang="java">
 +
UnitOfWork uow = session.acquireUnitOfWork();
 +
Pet petClone = (Pet) uow.readObject(Pet.class);
 +
petClone.setName("Furry");
 +
uow.commit();
 +
</source>
 +
 +
Both approaches produce the following SQL:
 +
 +
<source lang="sql">
 +
UPDATE PET SET NAME = 'Furry' WHERE (ID = 100)
 +
</source>
 +
 +
Take care when querying through a Unit of Work. All objects read in the query are registered in the Unit of Work and therefore will be checked for changes at commit time. Rather than do a ReadAllQuery through a Unit of Work, it is better for performance to design your application to do the ReadAllQuery through a session and then only register in a Unit of Work the objects that need to be changed.
  
 
== Deleting Objects ==
 
== Deleting Objects ==
Line 58: Line 92:
  
 
=== Deleting an Object ===
 
=== Deleting an Object ===
<code><pre>
+
<source lang="java">
 
UnitOfWork uow = session.acquireUnitOfWork();
 
UnitOfWork uow = session.acquireUnitOfWork();
 
pet petClone = (Pet)uow.readObject(Pet.class);
 
pet petClone = (Pet)uow.readObject(Pet.class);
 
uow.deleteObject(petClone);
 
uow.deleteObject(petClone);
 
uow.commit();
 
uow.commit();
</pre></code>
+
</source>
  
 
The above code generates the following SQL:
 
The above code generates the following SQL:
<code><pre>
+
<source lang="sql">
 
DELETE FROM PET WHERE (ID = 100)
 
DELETE FROM PET WHERE (ID = 100)
</pre></code>
+
</source>

Latest revision as of 10:49, 24 June 2008

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).

Contents

[edit] 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

[edit] 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.

[edit] Creating Objects

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.

[edit] 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();

[edit] 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.

[edit] Modifying Objects

[edit] Modifying an Object: Using the Registration Step

In this example, a Pet is read prior to a Unit of Work: the variable pet is the cache copy for that Pet. Inside of the Unit of Work, we must register the cache copy to get a working copy. We then modify the working copy and commit the Unit of Work.

// Read in any pet.
Pet pet = (Pet)session.readObject(Pet.class);
UnitOfWork uow = session.acquireUnitOfWork();
Pet petClone = (Pet) uow.registerObject(pet);
petClone.setName("Furry");
uow.commit();

[edit] Modifying an Object: Skipping the Registration Step

In this example, we take advantage of the fact that you can query through a Unit of Work and get back clones, saving the registration step. However, the drawback is that we do not have a handle to the cache copy. If we wanted to do something with the updated Pet after commit, we would have to query the session to get it (remember that after a Unit of Work is committed, its clones are invalid and must not be used).

UnitOfWork uow = session.acquireUnitOfWork();
Pet petClone = (Pet) uow.readObject(Pet.class);
petClone.setName("Furry");
uow.commit();

Both approaches produce the following SQL:

UPDATE PET SET NAME = 'Furry' WHERE (ID = 100)

Take care when querying through a Unit of Work. All objects read in the query are registered in the Unit of Work and therefore will be checked for changes at commit time. Rather than do a ReadAllQuery through a Unit of Work, it is better for performance to design your application to do the ReadAllQuery through a session and then only register in a Unit of Work the objects that need to be changed.

[edit] Deleting Objects

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.

[edit] 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)