天天看点

【第二章 DataContext 】3 数据对象状态管理

数据容器(DataContext)的第二个(另一个是执行查询)重要特性就是跟踪数据对象的修改。注册一个对象到数据容器,可以使这个对象具备持久化能力。

How to Register a DataObject 注册数据对象

Behind the scenes "registering an object" results in storing this object in a map using its ObjectId as a key, setting "dataContext" property of a DataObject to the current DataContext, and taking a snapshot of all persistent properties to be able to track later modifications. Objects can become "registered" in two ways:

  • automatically when they are fetched via query API
  • explicitly for the newly created objects

Whenever a selecting query is executed by a DataContext, all fetched objects are automatically registered with this DataContext. On the other hand, newly created objects must be registered explicitly:

import org.apache.cayenne.access.DataContext;
...
DataContext context; // assume this exists

Artist artist = new Artist();
context.registerNewObject(artist);

// after the line above is executed, artist object acquired "persistent" behavior
// and is said to be "managed" by DataContext
           

This code can be simplified - object creation and registrations steps can be combined in one method call:

import org.apache.cayenne.access.DataContext;
...
DataContext context; // assume this exists

Artist artist = (Artist) context.newObject(Artist.class);
           

This method relies on the presence of a no-argument constructor in the DataObject class.

Checking the State of Registered DataObjects 检查注册的数据对象状态

State transitions of DataObjects from persistence point of view are discussed in the "Design" chapter. State of each individual object is described by an integer constant obtained via a call to DataObject.getPeristenceState(). Allowed states are defined as static variables in PersistenceState class.

When a new object is inserted to the DataContext as described above, it becomes "NEW":

import org.apache.cayenne.access.DataContext;
...
DataContext context; // assume this exists

// artist will become PersistenceState.NEW
Artist artist = (Artist) context.newObject(Artist.class);
           

When a DataContext is committed, such object becomes "COMMITTED":

// artist will become PersistenceState.COMMITTED
context.commitChanges();
           

When any of the attributes or relationships of the fetched or committed object are changed, such an object becomes MODIFIED:

// this will change the object state to PersistenceState.MODIFIED
artist.setName("NewName");
           

When a fetched or committed object is explicitly deleted from the DataContext, object becomes DELETED:

// this will change the object state to PersistenceState.DELETED
context.deleteObject(artist);
           

DataContext is said to have changes if it has one or more registered objects in a state PersistenceState.MODIFIED, PersistenceState.NEW or PersistenceState.DELETED. DataContext provides the following method to check if it has any changed objects:

  • public boolean hasChanges()

There is also a way to obtain a list of changed objects in each one of the above states:

  • public java.util.Collection newObjects()
  • public java.util.Collection deletedObjects()
  • public java.util.Collection modifiedObjects()

Saving All Uncommitted DataObjects 保存所有未提交的数据对象

All of the uncommitted objects ("uncommitted" means "new", "modified" or "deleted") are saved ("committed") to the database with a single method call on the DataContext:

  • public void commitChanges()

Method commitChanges takes care of building correct SQL statements, generating primary keys and transactional behaviour. It roughly follows this scenario:

  • Checks if there are any changed objects (also detecting "phantom" modifications, e.g. if an object property was "updated" with the equivalent value).
  • Validates "dirty" objects (for more information on validation see this page).
  • Generates primary keys for any NEW objects that require autogenerated key.
  • Builds any needed INSERT, UPDATE, DELETE queries.
  • Starts the database transaction.
  • Runs the queries.
  • Commits transaction.
  • Changes all committed objects state to PersistenceState.COMMITTED.
  • Updates internally stored snapshots of the recently saved objects.

Undoing All Uncommitted Changes 回滚所有已提交的对象

There is a way for the DataContext to undo all uncommitted changes:

  • public void rollbackChanges()

This will restore the persistence state and the values of all registered objects to the values that objects had when they were fetched or the last commitChanges was executed. This effectively restores previously committed state of the object graph. Note that any NEW objects are unregistered from the context.

继续阅读