[ Team LiB ] |
14.3 Persistent-Nontransactional StateThe use of instances outside a transaction introduces another instance lifecycle state: persistent-nontransactional. From the application program perspective, this state is indistinguishable from the hollow state. That is, the results of executing the interrogatives in JDOHelper (isNew( ), isDirty( ), etc.) are the same for instances in both states. Your application generally should not be aware of the difference between instances in the hollow and persistent-nontransactional states. From a performance perspective, your application might run faster, because accessing field values of instances in the persistent-nontransactional state might be done without a datastore access. Your application can retrieve field values cached in the instance and navigate the object graph to other instances, relying only on the cached values. The only time the datastore must be accessed is when a field that has not yet been loaded from the datastore is read. With datastore transactions, existing persistent instances begin their lifecycle in the cache as persistent-clean or persistent-dirty. With the first access to persistent instances outside a transaction, they begin their lifecycle in the cache in the persistent-nontransactional state. This can be the result of an Extent iteration, a query execution, or navigation from another persistent-nontransactional instance. With NontransactionalRead set to true, outside a transaction:
Figure 14-1. State transitions outside a transactionWith NontransactionalRead set to false, outside a transaction:
We will now discuss a more complete example, based on the Media Mania application. MediaManiaApp declares an abstract method, execute( ), which is implemented by a derived class. In the derived classes, we have seen examples of main( ), which calls executeTransaction( ). This method then begins a transaction, calls execute( ), and commits the transaction. For this example, we will implement main( ) to call execute( ) instead of executeTransaction( ), which will make the program run without a transaction. The program is PrintMovies in the com.mediamania.nontx package: package com.mediamania.nontx; import com.mediamania.MediaManiaApp; import com.mediamania.content.Movie; public class PrintMovies { We don't define a constructor, so the compiler generates a no-arg constructor that calls the superclass to construct the PersistenceManagerFactory. The superclass constructor calls getPropertyOverrides( ), which is implemented in this class to specify the required NontransactionalRead property: protected static Map getPropertyOverrides( ) { Map overrides = new HashMap( ); overrides.put("javax.jdo.option.NontransactionalRead", "true"); return overrides; } In this class, main( ) constructs a new instance of PrintMovies and calls execute( ): public static void main(String[] args) { PrintMovies printMovies = new PrintMovies( ); printMovies.execute( ); } The superclass defines the pmf and pm fields and initializes them in the constructor. The execute( ) method gets an Extent of Movie and iterates it, calling Utilities.printMovie( ) to display the contents on System.out: public void execute( ) { Extent extent = pm.getExtent(Movie.class, true); Iterator iter = extent.iterator( ); while (iter.hasNext( )){ Movie movie = (Movie) iter.next( ); Utilities.printMovie(movie, System.out); } } } As an alternative to using getPropertyOverrides( ), execute( ) could be slightly different, setting the NontransactionalRead property of the Transaction instance to true. public void execute( ) { pm.currentTransaction( ).setNontransactionalRead(true); Extent extent = pm.getExtent(Movie.class, true); Iterator iter = extent.iterator( ); while (iter.hasNext( )){ Movie movie = (Movie) iter.next( ); Utilities.printMovie(movie, System.out); } } |
[ Team LiB ] |