1.3 Orthogonal Persistence


Java is an object-oriented language, and developers inherently work with objects, which at any time have a state represented by member variables . From the Java developer's perspective, persistence focuses on the fact that the state in these objects should be available after the Java virtual machine has exited. For example, an application passing and using an instance of an Order class should be capable of recreating the Order instance after a machine reboot, or a year later when the account is audited .

The traditional programming approach has been to acquire the relevant state information and store it externally in some form for example, using a relational database. When required, a new object instance is created and populated with this previously stored state. It is the developer's responsibility to map the information in the underlying datastore to its programmatic representation, as illustrated in Figure 1-2:

Figure 1-2. Traditional persistence deals with information.

graphics/01fig02.gif

For example, to save an Order object from Figure 1-1(b), developers write code to insert order attributes (date, amount, etc.) and dependent attributes like those in the LineItem in some datastore. When needed, the datastore is queried for some field (like an orderid) that uniquely identifies the collective information set about that order and a new Order instance is created and populated with that information.

In general Java applications have followed variations of the following development steps:

  • Identify the object model.

  • Identify persistent entities in the model.

  • Write database schemas to map the persistent entities information.

  • Write code to store that information in a form that is understood by the database (e.g., access attributes in objects and insert corresponding rows in a database table), and write code to access that information in a form that can be used by the application (e.g., read rows in a table and return Java objects).

  • Write application code that uses these classes and performs the business task.

As shown in Figure 1-3, developers now have to define, build, and use two models that programmatically reflect the same business domain for example, business objects in the application code and their relational representation in the database. They also have to ensure that the view and behavior of these two models remains consistent because the slightest variation in either will result in an impedance mismatch between the models and the real-world business.

Figure 1-3. Traditional persistence leads to two models.

graphics/01fig03.gif

The idea of orthogonal persistence is one in which the application design is decoupled and independent of the entire underlying persistence infrastructure and has been around for a while. [1] An application is said to exhibit orthogonal persistence when the following three principles [2] that have been established after many years of research into persistence are met:

[1] Atkinson, M. P.; Bailey, P. J.; Chisholm, K. J.; Cockshott, W. P.; and Morrison, R. (1983). "An Approach to Persistent Programming." Computer Journal 26: 4.

[2] Atkinson, M. P.; Daynes, L.; Jordan, M. J.; Printezis, T.; and Spence, S. (1996). "An orthogonally persistent Java." ACM SIGMOD Record , December, pp. 2-3.

  • The principle of data type orthogonality requires that all data, irrespective of its type information, should have the ability to be persisted . There are no special cases in which objects are not allowed to be persistent or are not allowed to be transient .

  • The principle of persistence independence requires the application code to be indistinguishable whether it is manipulating persistent data (i.e., data originating from the stable store and outliving the program) or transient data (i.e., data that is created in and will only exist during the lifetime of the Java program execution).

  • The principle of persistence by reachability requires that the lifetime of objects be determined by their reachability. This is the same principle that is applied to objects on the Java heap. When an object is marked for deletion, the entire tree of objects that it references can be garbage collected.

The first attempts at building orthogonal persistence using these principles in Java were initiated by Sun Laboratories in July 1995 as a research project called "Forest" and resulted in a prototype design called PJama. [3] However, the design was based around a modified virtual machine, and a second research project called JSPIN [4] tried another approach with the use of a preprocessor based on earlier research on ADA83. Although JDO is unrelated to these efforts, the principles outlined in all these works JDO share a conceptual similarity. In practical terms, JDO fulfills the needs of the community with a much simpler architecture.

[3] The Forest project, Sun Laboratories, available at http://research.sun.com/forest/index.html.

[4] Our SPIN on Persistent Java: The JavaSPIN Approach Jack C. Wileden, Alan Kaplan, Geir A Myrestrand, John V.E. Ridgway, available at http://research.sun.com/forest/UK.Ac.Gla.Dcs.PJW1.Jack_Wileden2_pdf.pdf. First International Workshop on Persistence and Java (1996).

An architecture utilizing any form of orthogonal persistence is quite different from the traditional persistence approach that we looked at earlier, in that this model deals with objects directly rather than the information contained therein. Such a persistence service abstracts away all the semantics relating to persistence from the application. Rather than working with information and mapping that information back and forth between objects, developers work with persistent objects directly in their code just like any other application objects. The difference is that some of these objects now represent persistent information in a datastore, as illustrated in Figure 1-4. The details about how they are persisted and recreated are transparent to the developer; this is often referred to as transparent persistence.

Figure 1-4. Transparent persistence deals directly with objects.

graphics/01fig04.gif

For example, to save an Order object from Figure 1-1(b), developers would use a transparent persistence service and give it that particular Order instance. When needed by the application at a later time, developers would query the service for that unique Order, by using, for example, an attribute "give me the order object with the orderid of 2828." The previously stored object matching that criterion is returned by the service. JDO is the standard that provides transparent persistence services to Java applications.

With JDO, architects and developers can concentrate on the application at hand, rather than the information contained therein. In comparison to the previously listed steps, development with JDO would involve the following steps:

  • Identify the object model.

  • Identify persistent entities in the model.

  • Write application code that uses these objects and performs the business task.

  • Use the rather straightforward JDO API in application code to persist and retrieve the objects when needed.

As shown in Figure 1-5, design with transparent persistence is much more simplified. Developers need to write and maintain only a single model or programmatic representation, e.g., business objects in the application code, when needed entities from that model can be persisted using the transparent persistence service.

Figure 1-5. The transparent persistence model.

graphics/01fig05.gif

Of course, JDO is not the single solution to all persistence- related issues, and some situations in which this might not be appropriate are discussed in Chapter 13. However, one thing is clear: JDO greatly simplifies (and possibly speeds up) the development approach.

JDO and Java Serialization

Developers will notice the similarities between JDO and Java Serialization. We look at Serialization, which also is a form of transparent persistence, and other persistence-related technologies in Chapter 2.


1.3.1 Transient and persistent objects

Java applications instantiate objects using the new operator and the constructor. For example:

 
 Order myorder=  new Order(2828);  myorder.addItem(  new LineItem  ("Core JDO",".99")); 

When instantiated , the virtual machine allocates space on the heap in memory, creates the object, and returns a reference. These objects do not represent any persistent data, meaning that their state and the state of objects referenced by them is present only in the memory of the virtual machine in which they are created. Such objects are called transient because they live only as long as the virtual machine process is running, or unless they are garbage collected.

A persistent object is no different from any other object, in that it is created using the same new operator and constructor. However, a persistent object is an instance of a class that has been marked as persistence capable and represents data in some persistent store. The lifespan of persistent objects is not tied to the life of the virtual machine in which they are created.

A persistent object becomes the representation of persistent data as a result of an explicit invocation of JDO API. For example:

 
 PersistenceManager mgr=pmf.getPersistenceManager();// JDO API mgr.currentTransaction().begin()/ JDO API Order myorder= new Order(2828); // Transient object mgr.  makePersistent  (myorder); // myorder marked as persistent mgr.currentTransaction().commit() // JDO API instance myorder                                   //is written to datastore 

A transient object can also become persistent if it is referenced as a field in a persistent object. This is known as persistence by reachability or transitive persistence (in ODMG terms), and it ensures that when an object is stored in a datastore, every item or the graph of items that the object references and collectively represent that object's state are also preserved. This is necessary to recreate the object instance correctly when required. Persistence by reachability is the aspect that results in the appearance of transparent persistence to the developer. The code extract below explains this further:

 
 PersistenceManager mgr=pmf.getPersistenceManager();// JDO API mgr.currentTransaction().begin();// JDO API Order myorder= new Order(2828); // Transient object mgr.  makePersistent  (myorder); // myorder marked as persistent // other application code here  myorder.addItem(new LineItem  ("Core JDO",".99")); mgr.currentTransaction().commit();// JDO API myorder                     //including the LineItem is                                  //also written to datastore 

In the above code segment, unlike the Order object, the LineItem object was never explicitly persisted. However, because it is referenced by an object that is persisted, it too will be saved, as depicted here in Figure 1-6:

Figure 1-6. Persistence by reachability.

graphics/01fig06.gif

A persistent object can be changed back to a transient object by an explicit call to the JDO API. When a persistent object is marked as transient, any change made to it is not reflected in the datastore. For example:

 
 PersistenceManager mgr=pmf.getPersistenceManager();// JDO API mgr.currentTransaction().begin(); // JDO API // other application code here mgr.  makeTransient  (myorder) // JDO API // other application code here 

A persistent object is also automatically changed to a transient object after it has been persisted. For example, look again at the code shown earlier:

 
 PersistenceManager mgr=pmf.getPersistenceManager();// JDO API mgr.currentTransaction().begin()/ JDO API Order myorder= new Order(2828); // Transient object mgr.  makePersistent  (myorder); // myorder marked as persistent mgr.currentTransaction().commit() // JDO API instance myorder                                   //is written to datastore myorder.doSomething(); // Transient object 

Both transient and persistent instances go through different state changes that we discuss in Chapter 4.

Another strategy employed in object persistence is termed persistence by inheritance , in which object instances of a subclass of a persistence-capable class can be persisted. JDO is very complete in its support for inheritance. A class can be persistence capable even if its parent is not, a parent can be persistence capable and sub classes may not be, and even selective individual classes may be persistence capable in a large inheritance tree. It is up to the requirements specified by the developer.

The key architectural points surrounding JDO persistence are as follows :

  • Persistence is orthogonal to the class hierarchy. All user -defined objects of any level and of any type may be persisted except those whose state depends on the operating environment (for example, system classes like File, Sockets, Thread, InputStream, etc.). This is understandable because objects with such native state depend on or are a reflection off the state of the operating system in which they are executing, upon which no guarantees can be placed.

  • Persistence is transparent to clients . The logic relating to object persistence is abstracted away. Application code does not move objects to and from stable storage, nor does it deal directly with the underlying datastore.

  • Persistence is per-object based. Objects of a particular class may be persistent or transient, and in fact may be in general objects of both kinds for a given class.

  • Persistence is based on method invocation. An object is promoted to a persistent state by making use of a makePersistent() method .

  • Persistence is based on reachability and ensures that all observable properties of a persistent object are preserved even though they may refer to other objects.

  • Persistence does not alter object type information and guarantees type safety.



Core Java Data Objects
Core Java Data Objects
ISBN: 0131407317
EAN: 2147483647
Year: 2003
Pages: 146

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net