Added: incubator/openjpa/trunk/openjpa-project/src/doc/manual/jpa_overview_pc.xml URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-project/src/doc/manual/jpa_overview_pc.xml?rev=433761&view=auto ============================================================================== --- incubator/openjpa/trunk/openjpa-project/src/doc/manual/jpa_overview_pc.xml (added) +++ incubator/openjpa/trunk/openjpa-project/src/doc/manual/jpa_overview_pc.xml Tue Aug 22 14:28:53 2006 @@ -0,0 +1,1058 @@ + + <chapter id="jpa_overview_pc"> + <title>Entity</title> + <indexterm zone="jpa_overview_pc"> + <primary>persistent classes</primary> + </indexterm> + <indexterm zone="jpa_overview_pc"> + <primary>Entity</primary> + <seealso>persistent classes</seealso> + </indexterm> + <indexterm> + <primary>class</primary> + <secondary>persistent</secondary> + <see>persistent classes</see> + </indexterm> + <indexterm> + <primary>persistence capable</primary> + <see>Entity</see> + </indexterm> + <para> + JPA recognizes two types of persistent classes: <emphasis> + entity</emphasis> classes and <emphasis>embeddable</emphasis> classes. + Each persistent instance of an entity class - each + <emphasis>entity</emphasis> - represents a unique datastore + record. You can use the <classname>EntityManager</classname> to find an + entity by its persistent identity (covered later in this chapter), or use + a <classname>Query</classname> to find entities matching certain criteria. + </para> + <para> + An instance of an embeddable class, on the other hand, is only stored + as part of a separate entity. Embeddable instances have no + persistent identity, and are never returned directly from the + <classname>EntityManager</classname> or from a <classname>Query</classname>. + </para> + <para> + Despite these differences, there are few differences between entity classes + and embeddable classes. In fact, writing either type + of persistent class is little different than writing any other + class. There are no special parent classes to extend from, field types to + use, or methods to write. This is one important way in which JPA makes + persistence transparent to you, the developer. + </para> + <note> + <para> + JPA supports both fields and JavaBean properties + as persistent state. For simplicity, however, we will + refer to all persistent state as persistent fields, unless we + want to note a unique aspect of persistent properties. + </para> + </note> + <example id="jpa_overview_pc_pcclass"> + <title>Persistent Class</title> + <programlisting format="linespecific"> +package org.mag; + +/** + * Example persistent class. Notice that it looks exactly like any other + * class. JPA makes writing persistent classes completely transparent. + */ +public class Magazine +{ + private String isbn; + private String title; + private Set articles = new HashSet (); + private Article coverArticle; + private int copiesSold; + private double price; + private Company publisher; + private int version; + + protected Magazine () + { + } + + public Magazine (String title, String isbn) + { + this.title = title; + this.isbn = isbn; + } + + public void publish (Company publisher, double price) + { + this.publisher = publisher; + publisher.addMagazine (this); + this.price = price; + } + + public void sell () + { + copiesSold++; + publisher.addRevenue (price); + } + + public void addArticle (Article article) + { + articles.add (article); + } + + // rest of methods omitted +} +</programlisting> + </example> + <section id="jpa_overview_pc_restrict"> + <title>Restrictions on Persistent Classes</title> + <indexterm zone="jpa_overview_pc_restrict"> + <primary>persistent classes</primary> + <secondary>restrictions on</secondary> + </indexterm> + <para> + There are very few restrictions placed on persistent classes. + Still, it never hurts to familiarize yourself with exactly what + JPA does and does not support. + </para> + <section id="jpa_overview_pc_no_arg"> + <title>Default or No-Arg Constructor</title> + <indexterm zone="jpa_overview_pc_no_arg"> + <primary>persistent classes</primary> + <secondary>no-arg constructor requirement</secondary> + </indexterm> + <indexterm> + <primary>constructor</primary> + <secondary>no-arg constructor requirement</secondary> + </indexterm> + <para> + The JPA specification requires that all persistent + classes have a no-arg constructor. This constructor + may be public or protected. Because the compiler automatically + creates a default no-arg constructor when no other constructor + is defined, only classes that define constructors must also + include a no-arg constructor. + </para> + <note> + <para> + OpenJPA's <emphasis>enhancer</emphasis> will automatically add a + protected no-arg constructor to your class when required. + Therefore, this restriction does not apply when using + OpenJPA. See <xref linkend="ref_guide_pc_enhance"/> + of the Reference Guide for details. + </para> + </note> + </section> + <section id="jpa_overview_pc_final"> + <title>Final</title> + <para> + Entity classes may not be final. No method of an entity class can + be final. + </para> + <note> + <para> + OpenJPA supports final classes and final methods. + </para> + </note> + </section> + <section id="jpa_overview_pc_id"> + <title>Identity Fields</title> + <indexterm zone="jpa_overview_pc_id"> + <primary>identity fields</primary> + <seealso>persistent fields</seealso> + </indexterm> + <indexterm zone="jpa_overview_pc_id"> + <primary>persistent classes</primary> + <secondary>JPA id requirement</secondary> + </indexterm> + <para> + All entity classes must declare one or more fields which together + form the persistent identity of an instance. These are called + <emphasis>identity</emphasis> or <emphasis>primary key</emphasis> + fields. In our <classname>Magazine</classname> class, + <literal>isbn</literal> and + <literal>title</literal> are identity fields, because no two + magazine records in the datastore can have the same + <literal>isbn</literal> and <literal>title</literal> values. + <xref linkend="jpa_overview_meta_id"/> will show you how to denote + your identity fields in JPA metadata. + <xref linkend="jpa_overview_pc_identity"/> below examines + persistent identity. + </para> + <note> + <para> + OpenJPA fully supports identity fields, but does not require them. + See <xref linkend="ref_guide_pc_oid"/> of the Reference + Guide for details. + </para> + </note> + </section> + <section id="jpa_overview_pc_version"> + <title>Version Field</title> + <indexterm zone="jpa_overview_pc_version"> + <primary>version fields</primary> + <seealso>persistent fields</seealso> + </indexterm> + <indexterm zone="jpa_overview_pc_version"> + <primary>persistent classes</primary> + <secondary>JPA version requirement</secondary> + </indexterm> + <para> + The <literal>version</literal> field in our <classname>Magazine + </classname> class may seem out of place. + JPA uses a version field in your entity to detect + concurrent modifications to the same datastore record. When the + JPA runtime detects an attempt to concurrently modify + the same record, it throws an exception to the transaction + attempting to commit last. This prevents overwriting the previous + commit with stale data. + </para> + <para> + The version field is not required, but without one concurrent + threads or processes might succeed in making conflicting changes + to the same record at the same time. This is unacceptable to most + applications. <xref linkend="jpa_overview_meta_version"/> + shows you how to designate a version field in JPA metadata. + </para> + <para> + The version field must be an integral type (<classname> + int</classname>, <classname>Long</classname>, etc) or a + <classname>java.sql.Timestamp</classname>. You should consider + version fields immutable. Changing the field value has undefined + results. + </para> + <note> + <para> + OpenJPA fully supports version fields, but does not require them + for concurrency detection. OpenJPA can maintain + surrogate version values or use state comparisons to detect + concurrent modifications. See + <xref linkend="ref_guide_mapping_ejb"/> in the Reference Guide. + </para> + </note> + </section> + <section id="jpa_overview_pc_restrict_inheritance"> + <title>Inheritance</title> + <indexterm zone="jpa_overview_pc_restrict_inheritance"> + <primary>persistent classes</primary> + <secondary>inheritance of</secondary> + <seealso>inheritance</seealso> + </indexterm> + <indexterm> + <primary>inheritance</primary> + <secondary>of persistent classes</secondary> + </indexterm> + <para> + JPA fully supports inheritance in persistent classes. + It allows persistent classes to inherit from non-persistent classes, + persistent classes to inherit from other persistent classes, + and non-persistent classes to inherit from persistent classes. + It is even possible to form inheritance hierarchies in which + persistence skips generations. There are, however, a few + important limitations: + </para> + <itemizedlist> + <listitem> + <para> + Persistent classes cannot inherit from certain + natively-implemented system classes such as + <classname>java.net.Socket</classname> and + <classname>java.lang.Thread</classname>. + </para> + </listitem> + <listitem> + <para> + If a persistent class inherits from a non-persistent + class, the fields of the non-persistent superclass + cannot be persisted. + </para> + </listitem> + <listitem> + <para> + All classes in an inheritance tree must use the same + identity type. We cover entity identity in + <xref linkend="jpa_overview_pc_identity"/>. + </para> + </listitem> + </itemizedlist> + </section> + <section id="jpa_overview_pc_restrict_fields"> + <title>Persistent Fields</title> + <indexterm zone="jpa_overview_pc_restrict_fields"> + <primary>persistent classes</primary> + <secondary>field restrictions</secondary> + <seealso>persistent fields</seealso> + </indexterm> + <indexterm> + <primary>field</primary> + <secondary>persistent</secondary> + <see>persistent fields</see> + </indexterm> + <indexterm zone="jpa_overview_pc_restrict_fields"> + <primary>persistent fields</primary> + <secondary>restrictions on</secondary> + </indexterm> + <para> + JPA manages the state of all persistent fields. + Before you access persistent state, the JPA runtime + makes sure that it has been loaded from the datastore. When you + set a field, the runtime records that it has changed so that + the new value will be persisted. This allows you to treat the + field in exactly the same way you treat any other field - another + aspect of JPA's transparency. + </para> + <para> + JPA does not support static or final fields. + It does, however, include built-in support for most + common field types. These types can be roughly divided into three + categories: immutable types, mutable types, and relations. + </para> + <para><indexterm><primary>persistent fields</primary><secondary>immutable types</secondary></indexterm><indexterm><primary>immutable</primary><secondary>persistent field types</secondary></indexterm><emphasis>Immutable</emphasis> types, once created, cannot be + changed. The only way to alter a persistent field of an immutable + type is to assign a new value to the field. JPA + supports the following immutable types: + </para> + <itemizedlist> + <listitem> + <para> + All primitives (<classname>int, float, byte</classname>, + etc) + </para> + </listitem> + <listitem> + <para> + All primitive wrappers (<classname>java.lang.Integer, + java.lang.Float, java.lang.Byte</classname>, etc) + </para> + </listitem> + <listitem> + <para> + <classname>java.lang.String</classname> + </para> + </listitem> + <listitem> + <para> + <classname>java.math.BigInteger</classname> + </para> + </listitem> + <listitem> + <para> + <classname>java.math.BigDecimal</classname> + </para> + </listitem> + </itemizedlist> + <para> + JPA also supports <classname>byte[]</classname> and + <classname>char[]</classname> as immutable types. That is, you + can persist fields of these types, but you should not manipulate + individual array indexes without resetting the array into the + persistent field. + </para> +<!-- ### EJB3 : Byte[], Character[] --> + <para><indexterm><primary>persistent fields</primary><secondary>mutable types</secondary><seealso>proxies</seealso></indexterm><indexterm><primary>mutable</primary><secondary>persistent field types</secondary><seealso>persistent fields</seealso><seealso>proxies</seealso></indexterm><indexterm><primary>persistent fields</primary><secondary>user-defined types</secondary></indexterm><indexterm><primary>user-defined</primary><secondary>persistent field types</secondary><seealso>persistent fields</seealso></indexterm> + Persistent fields of <emphasis>mutable</emphasis> types + can be altered without assigning the field a new value. + Mutable types can be modified directly through their own + methods. The JPA specification requires that + implementations support the following mutable field types: + </para> + <itemizedlist> + <listitem> + <para> + <classname>java.util.Date</classname> + </para> + </listitem> + <listitem> + <para> + <classname>java.util.Calendar</classname> + </para> + </listitem> + <listitem> + <para> + <classname>java.sql.Date</classname> + </para> + </listitem> + <listitem> + <para> + <classname>java.sql.Timestamp</classname> + </para> + </listitem> + <listitem> + <para>Enums</para> + </listitem> + <listitem> + <para>Entity types (relations between entities)</para> + </listitem> + <listitem> + <para>Embeddable types</para> + </listitem> + <listitem> + <para><classname>java.util.Collection</classname>s of entities + </para> + </listitem> + <listitem> + <para><classname>java.util.Set</classname>s of entities + </para> + </listitem> + <listitem> + <para><classname>java.util.List</classname>s of entities + </para> + </listitem> + <listitem> + <para><classname>java.util.Map</classname>s in which each entry + maps the value of one of an entity's fields to that entity. + </para> + </listitem> + </itemizedlist> + <para> + Collection and map types may be parameterized. + </para> + <para><indexterm><primary>persistent fields</primary><secondary>of unknown types</secondary></indexterm><indexterm><primary>Object</primary><secondary>as persistent field type</secondary><seealso>persistent fields</seealso></indexterm> + Most JPA implementations also have support for + persisting serializable values as binary data in the datastore. + <xref linkend="jpa_overview_meta"/> has more information on + persisting serializable types. + </para> + <note> + <para> + OpenJPA also supports arrays, <classname> + java.lang.Number</classname>, <classname> + java.util.Locale</classname>, all JDK 1.2 <classname> + Set</classname>, <classname>List</classname>, and <classname> + Map</classname> types, collections and maps of immutable and + embedded as well as entity types, and many other mutable and + immutable field types. OpenJPA also allows you to plug in + support for custom types. + </para> + </note> + </section> + <section id="jpa_overview_pc_restrict_conclusion"> + <title>Conclusions</title> + <para> + This section detailed all of the restrictions JPA + places on persistent classes. While it may seem like we presented + a lot of information, you will seldom find yourself hindered by + these restrictions in practice. Additionally, there are often ways + of using JPA's other features to circumvent any + limitations you run into. + <!-- ### EJBDOC : good transition when lifecycle listeners are + ### added back as next section + The next section explores a powerful JPA feature + that is particularly useful for this purpose. + --> + </para> + </section> + </section> + <section id="jpa_overview_pc_identity"> + <title>Entity Identity</title> + <indexterm zone="jpa_overview_pc_identity"> + <primary>JPA</primary> + <secondary>identity</secondary> + <seealso>identity</seealso> + </indexterm> + <indexterm> + <primary>entity identity</primary> + <see>identity</see> + </indexterm> + <indexterm zone="jpa_overview_pc_identity"> + <primary>identity</primary> + <secondary>JPA</secondary> + </indexterm> + <para><indexterm><primary>identity</primary><secondary>numeric</secondary></indexterm><indexterm><primary>identity</primary><secondary>qualitative</secondary></indexterm><indexterm><primary>numeric identity</primary><seealso>identity</seealso></indexterm><indexterm><primary>qualitative identity</primary><seealso>identity</seealso></indexterm> + Java recognizes two forms of object identity: numeric identity and + qualitative identity. If two references are + <emphasis>numerically</emphasis> identical, then they refer to the + same JVM instance in memory. You can test for this using the + <literal>==</literal> operator. <emphasis>Qualitative</emphasis> + identity, on the other hand, relies on some user-defined criteria to + determine whether two objects are "equal". You test for qualitative + identity using the <methodname>equals</methodname> method. By default, + this method simply relies on numeric identity. + </para> + <para> + JPA introduces another form of object identity, called + <emphasis>entity identity</emphasis> or <emphasis>persistent + identity</emphasis>. Entity identity tests whether two persistent + objects represent the same state in the datastore. + </para> + <para><indexterm><primary>persistent fields</primary><secondary>id</secondary></indexterm><indexterm><primary>id</primary><secondary>fields</secondary><seealso>persistent fields</seealso></indexterm> + The entity identity of each persistent instance is encapsulated in its + <emphasis>identity field(s)</emphasis>. If two entities of the same + type have the same identity field values, then the two + entities represent the same state in the datastore. Each entity's + identity field values must be unique among all other entites of the + same type. + </para> + <para> + Identity fields must be primitives, primitive wrappers, + <classname>String</classname>s, <classname>Date</classname>s, + <classname>Timestamp</classname>s, or embeddable types. Notably, other + entities instances can <emphasis>not</emphasis> be used as identity + fields. + </para> + <note> + <para> + For legacy schemas with binary primary key columns, OpenJPA + also supports using identity fields of type + <classname>byte[]</classname>. When you use a <classname>byte[] + </classname> identity field, you must + create an identity class. Identity classes are covered below. + </para> + </note> + <warning> + <para> + Changing the fields of an embeddable instance while it is assigned + to an identity field has undefined results. Always treat + embeddable identity instances as immutable objects in your + applications. + </para> + </warning> + <para><indexterm><primary>identity</primary><secondary>uniqueness requirement</secondary></indexterm><indexterm><primary>uniquness requirement</primary><seealso>identity</seealso></indexterm> + If you are dealing with a single persistence context (see + <xref linkend="jpa_overview_emfactory_perscontext"/>), + then you do not have to compare identity fields to test + whether two entity references represent the same state in the + datastore. There is a much easier way: the + <literal>==</literal> operator. JPA requires that + each persistence context maintain only one JVM object to represent + each unique datastore record. Thus, entity identity is equivalent to + numeric identity within a persistence context. This is referred to as + the <emphasis>uniqueness requirement</emphasis>. + </para> + <para> + The uniqueness requirement is extremely important - without it, it + would be impossible to maintain data integrity. Think of what + could happen if two different objects in the same transaction + were allowed to represent the same persistent data. If you made + different modifications to each of these objects, which set of changes + should be written to the datastore? How would your application logic + handle seeing two different "versions" of the same data? Thanks to the + uniqueness requirement, these questions do not have to be answered. + </para> + <section id="jpa_overview_pc_identitycls"> + <title>Identity Class</title> + <para><indexterm zone="jpa_overview_pc_identitycls"><primary>identity class</primary><seealso>identity</seealso></indexterm><indexterm zone="jpa_overview_pc_identitycls"><primary>identity</primary><secondary>class requirements</secondary></indexterm> + If your entity has only one identity field, you can use the value of + that field as the entity's identity object in all + <link linkend="jpa_overview_em"><classname>EntityManager + </classname></link> APIs. Otherwise, you must supply an identity + class to use for identity objects. Your identity + class must meet the following criteria: + </para> + <itemizedlist> + <listitem> + <para>The class must be public.</para> + </listitem> + <listitem> + <para>The class must be serializable.</para> + </listitem> + <listitem> + <para> + The class must have a public no-args constructor. + </para> + </listitem> + <listitem> + <para> + The names of the non-static fields or properties of the + class must be the same as the names of the identity fields + or properties of the corresponding entity class, and the + types must be identical. + </para> + </listitem> + <listitem> + <para> + The <methodname>equals</methodname> and + <methodname>hashCode</methodname> methods of the class + must use the values of all fields or properties + corresponding to identity fields or properties in the + entity class. + </para> + </listitem> + <listitem> + <para> + If the class is an inner class, it must be + <literal>static</literal>. + </para> + </listitem> + <listitem> + <para> + All entity classes related by inheritance must use the same + identity class, or else each entity class must have its + own identity class whose inheritance hierarchy mirrors the + inheritance hierarchy of the owning entity classes (see + <xref linkend="jpa_overview_pc_identity_hierarchy"/>). + </para> + </listitem> + </itemizedlist> + <note> + <para> + Though you may still create identity classes by + hand, OpenJPA provides the <classname>appidtool</classname> + to automatically generate proper identity classes + based on your identity fields. See + <xref linkend="ref_guide_pc_oid_application"/> of the + Reference Guide. + </para> + </note> + <example id="jpa_overview_pc_identity_appidcode"> + <title>Identity Class</title> + <para> + This example illustrates a proper identity class for an entity + with multiple identity fields. + </para> + <programlisting format="linespecific"> +/** + * Persistent class using application identity. + */ +public class Magazine +{ + private String isbn; // identity field + private String title; // identity field + + // rest of fields and methods omitted + + + /** + * Application identity class for Magazine. + */ + public static class MagazineId + { + // each identity field in the Magazine class must have a + // corresponding field in the identity class + public String isbn; + public String title; + + /** + * Equality must be implemented in terms of identity field + * equality, and must use instanceof rather than comparing + * classes directly (some JPA implementations may subclass the + * identity class). + */ + public boolean equals (Object other) + { + if (other == this) + return true; + if (!(other instanceof MagazineId)) + return false; + + MagazineId mi = (MagazineId) other; + return (isbn == mi.isbn + || (isbn != null && isbn.equals (mi.isbn))) + && (title == mi.title + || (title != null && title.equals (mi.title))); + } + + /** + * Hashcode must also depend on identity values. + */ + public int hashCode () + { + return ((isbn == null) ? 0 : isbn.hashCode ()) + ^ ((title == null) ? 0 : title.hashCode ()); + } + + public String toString () + { + return isbn + ":" + title; + } + } +} +</programlisting> + </example> + <section id="jpa_overview_pc_identity_hierarchy"> + <title>Identity Hierarchies</title> + <indexterm zone="jpa_overview_pc_identity_hierarchy"> + <primary>identity</primary> + <secondary>hierarchy</secondary> + </indexterm> + <mediaobject> + <imageobject> +<!-- PNG image data, 320 x 267 (see README) --> + <imagedata fileref="img/appid-hierarchy.png" width="213px"/> + </imageobject> + </mediaobject> + <para> + An alternative to having a single identity + class for an entire inheritance hierarchy is to have + one identity class per level in the + inheritance hierarchy. The requirements for using + a hierarchy of identity classes are as follows: + </para> + <itemizedlist> + <listitem> + <para> + The inheritance hierarchy of identity + classes must exactly mirror the hierarchy of the + persistent classes that they identify. In the example + pictured above, abstract class + <classname>Person</classname> is extended by abstract + class <classname>Employee</classname>, which is extended + by non-abstract class <classname> + FullTimeEmployee</classname>, which is extended by + non-abstract class <classname>Manager</classname>. + The corresponding identity classes, then, are + an abstract <classname>PersonId</classname> class, + extended by an abstract + <classname>EmployeeId</classname> class, extended by a + non-abstract <classname>FullTimeEmployeeId</classname> + class, extended by a non-abstract + <classname>ManagerId</classname> class. + </para> + </listitem> + <listitem> + <para> + Subclasses in the identity hierarchy + may define additional identity fields until + the hierarchy becomes non-abstract. In the + aforementioned example, <classname>Person</classname> + defines an identity field <literal>ssn</literal>, + <classname>Employee</classname> defines additional + identity field <literal>userName</literal>, and + <classname>FullTimeEmployee</classname> adds a final + identity field, <literal>empId</literal>. + However, <classname>Manager</classname> may not define + any additional identity fields, since it is a + subclass of a non-abstract class. The hierarchy of + identity classes, of course, must match the identity + field definitions of the persistent class hierarchy. + </para> + </listitem> + <listitem> + <para> + It is not necessary for each abstract class to declare + identity fields. In the previous example, the + abstract <classname>Person</classname> and + <classname>Employee</classname> classes could declare + no identity fields, and the first concrete subclass + <classname>FullTimeEmployee</classname> could define + one or more identity fields. + </para> + </listitem> + <listitem> + <para> + All subclasses of a concrete identity class must + be <methodname>equals</methodname> and <methodname> + hashCode</methodname>-compatible with the concrete + superclass. This means that in our example, a + <classname>ManagerId</classname> instance and a + <classname>FullTimeEmployeeId</classname> instance + with the same identity field values should have the + same hash code, and should compare equal to each other + using the <methodname>equals</methodname> method of + either one. In practice, this requirement reduces to + the following coding practices: + </para> + <orderedlist> + <listitem> + <para> + Use <literal>instanceof</literal> instead of + comparing <classname>Class</classname> objects + in the <methodname>equals</methodname> methods + of your identity classes. + </para> + </listitem> + <listitem> + <para> + An identity class that extends another + non-abstract identity class should not override + <methodname>equals</methodname> or + <methodname>hashCode</methodname>. + </para> + </listitem> + </orderedlist> + </listitem> + </itemizedlist> + </section> + </section> + </section> + <section id="jpa_overview_pc_callbacks"> + <title>Lifecycle Callbacks</title> + <indexterm zone="jpa_overview_pc_callbacks"> + <primary>lifecycle callbacks</primary> + </indexterm> + <indexterm zone="jpa_overview_pc_callbacks"> + <primary>persistent classes</primary> + <secondary>lifecycle callbacks</secondary> + <seealso>lifecycle callbacks</seealso> + </indexterm> + <para> + It is often necessary to perform various actions at different stages + of a persistent object's lifecycle. JPA includes + a variety of callbacks methods for monitoring changes in the + lifecycle of your persistent objects. These callbacks can + be defined on the persistent classes themselves and + on non-persistent listener classes. + </para> + <section id="jpa_overview_pc_callbacks_methods"> + <title>Callback Methods</title> + <indexterm zone="jpa_overview_pc_callbacks_methods"> + <primary>lifecycle callbacks</primary> + <secondary>callback methods</secondary> + </indexterm> + <indexterm zone="jpa_overview_pc_callbacks_methods"> + <primary>entity</primary> + <secondary>callback methods</secondary> + </indexterm> + <para> + Every persistence event has a corresponding callback method + marker. These markers are shared between persistent classes + and their listeners. You can use these markers to designate + a method for callback either by annotating that method or by + listing the method in the XML mapping file for a given class. + The lifecycle events and their corresponding method markers are: + </para> + <itemizedlist> + <listitem> + <para><indexterm><primary>PrePersist</primary><seealso>lifecycle callbacks</seealso></indexterm><ulink url="http://java.sun.com/javaee/5/docs/api/javax/persistence/PrePersist.html"><classname>PrePersist</classname></ulink>: + Methods marked with this annotation will be invoked + before an object is persisted. This could be used for + assigning primary key values to persistent objects. + This is equivalent to the XML element tag + <literal>pre-persist</literal>. + </para> + </listitem> + <listitem> + <para><indexterm><primary>PostPersist</primary><seealso>lifecycle callbacks</seealso></indexterm><ulink url="http://java.sun.com/javaee/5/docs/api/javax/persistence/PostPersist.html"><classname>PostPersist</classname></ulink>: + Methods marked with this annotation will be invoked + after an object has transitioned to the persistent state. + You might want to use such methods to update a screen + after a new row is added. This is equivalent + to the XML element tag <literal>post-persist</literal>. + </para> + </listitem> + <listitem> + <para><indexterm><primary>PostLoad</primary><seealso>lifecycle callbacks</seealso></indexterm><ulink url="http://java.sun.com/javaee/5/docs/api/javax/persistence/PostLoad.html"><classname>PostLoad</classname></ulink>: + Methods marked with this annotation will be invoked after + all eagerly fetched fields of your class have been + loaded from the datastore. No other persistent fields + can be accessed in this method. This is equivalent + to the XML element tag <literal>post-load</literal>. + </para> + <para><classname>PostLoad</classname> is often used to + initialize non-persistent fields whose values depend + on the values of persistent fields, such as a complex + datastructure. + </para> + </listitem> + <listitem> + <para><indexterm><primary>PreUpdate</primary><seealso>lifecycle callbacks</seealso></indexterm><ulink url="http://java.sun.com/javaee/5/docs/api/javax/persistence/PreUpdate.html"><classname>PreUpdate</classname></ulink>: + Methods marked with this annotation will be invoked + just the persistent values in your objects are flushed + to the datastore. This is equivalent to the XML element tag + <literal>pre-update</literal>. + </para> + <para><classname>PreUpdate</classname> is the complement to + <classname>PostLoad</classname>. While methods marked + with <classname>PostLoad</classname> are most often used + to initialize non-persistent values from persistent data, + methods annotated with <classname>PreUpdate</classname> + is normally used to set persistent fields with information + cached in non-persistent data. + </para> + </listitem> + <listitem> + <para><indexterm><primary>PostUpdate</primary><seealso>lifecycle callbacks</seealso></indexterm><ulink url="http://java.sun.com/javaee/5/docs/api/javax/persistence/PostUpdate.html"><classname>PostUpdate</classname></ulink>: + Methods marked with this annotation will be invoked + after changes to a given instance have been stored to the + datastore. This is useful for clearing stale data cached + at the application layer. This is equivalent to the + XML element tag <literal>post-update</literal>. + </para> + </listitem> + <listitem> + <para><indexterm><primary>PreRemove</primary><seealso>lifecycle callbacks</seealso></indexterm><ulink url="http://java.sun.com/javaee/5/docs/api/javax/persistence/PreRemove.html"><classname>PreRemove</classname></ulink>: + Methods marked with this annotation will be invoked + before an object transactions to the deleted state. + Access to persistent fields is valid within this method. + You might use this method to cascade the deletion to + related objects based on complex criteria, or to + perform other cleanup. This is equivalent to the + XML element tag <literal>pre-remove</literal>. + </para> + </listitem> + <listitem> + <para><indexterm><primary>PostRemove</primary><seealso>lifecycle callbacks</seealso></indexterm><ulink url="http://java.sun.com/javaee/5/docs/api/javax/persistence/PostRemove.html"><classname>PostRemove</classname></ulink>: + Methods marked with this annotation will be invoked after + an object has been marked as to be deleted. This is + equivalent to the XML element tag + <literal>post-remove</literal>. + </para> + </listitem> + </itemizedlist> + </section> + <section id="jpa_overview_callbacks_using"> + <title>Using Callback Methods</title> + <para> + When declaring callback methods on a persistent class, + any method may be used which takes no arguments and is not + shared with any property access fields. Multiple events + can be assigned to a single method as well. + </para> + <para> + Below is an example of how to declare callback methods + on persistent classes: + </para> + <programlisting format="linespecific"> +/** + * Example persistent class declaring our entity listener. + */ [EMAIL PROTECTED] +public class Magazine +{ + @Transient + private byte[][] data; + + @ManyToMany + private List<Photo> photos; + + @PostLoad + public void convertPhotos () + { + data = new byte[photos.size ()][]; + for (int i = 0; i < photos.size (); i++) + data[i] = photos.get (i).toByteArray (); + } + + @PreDelete + public void logMagazineDeletion () + { + getLog ().debug ("deleting magazine containing" + photos.size () + + " photos."); + } +} + +</programlisting> + <para> + In an XML mapping file, we can define the same methods + without annotations: + </para> + <programlisting format="linespecific"> +<entity class="Magazine"> + <pre-remove>logMagazineDeletion</pre-remove> + <post-load>convertPhotos</post-load> +</entity> +</programlisting> + <note> + <para> + We fully explore persistence metadata annotations and XML in + <xref linkend="jpa_overview_meta"/>. + </para> + </note> + </section> + <section id="jpa_overview_entity_listeners_using"> + <title>Using Entity Listeners</title> + <para> + Mixing lifecycle event code into your persistent classes is not + always ideal. It is often more elegant to handle cross-cutting + lifecycle events in a non-persistent listener class. + JPA allows for this, requiring only that listener + classes have a public no-arg constructor. Like persistent + classes, your listener classes can consume any number of callbacks. + The callback methods must take in a single + <classname>java.lang.Object</classname> argument which + represents the persistent object that triggered the event. + </para> + <para> + Entities can enumerate listeners using the + <classname>EntityListeners</classname> annotation. This annotation + takes an array of listener classes as its value. + </para> + <para> + Below is an example of how to declare an entity and its + corresponding listener classes. + </para> + <programlisting format="linespecific"> +/** + * Example persistent class declaring our entity listener. + */ [EMAIL PROTECTED] [EMAIL PROTECTED]({ MagazineLogger.class, ... }) +public class Magazine +{ + // ... // +} + + +/** + * Example entity listener. + */ +public class MagazineLogger +{ + @PostPersist + public void logAddition (Object pc) + { + getLog ().debug ("Added new magazine:" + ((Magazine) pc).getTitle ()); + } + + + @PreRemove + public void logDeletion (Object pc) + { + getLog ().debug ("Removing from circulation:" + + ((Magazine) pc).getTitle ()); + } +} +</programlisting> + <para> + In XML, we define both the listeners and their callback + methods as so: + </para> + <programlisting format="linespecific"> +<entity class="Magazine"> + <entity-listeners> + <entity-listener class="MagazineLogger"> + <post-persist>logAddition</post-persist> + <pre-remove>logDeletion</pre-remove> + </entity-listener> + </entity-listeners> +</entity> +</programlisting> + </section> + <section id="jpa_overview_entity_listeners_exclude"> + <title>Entity Listeners Hierarchy</title> + <indexterm zone="jpa_overview_entity_listeners_exclude"> + <primary>lifecycle listeners</primary> + <secondary>hierarchy</secondary> + </indexterm> + <para> + Entity listener methods are invoked in a specific order when a + given event is fired. So-called <emphasis>default</emphasis> + listeners are invoked first: these are listeners + which have been defined in a package annotation or in the root + element of XML mapping files. Next, entity listeners are invoked + in the order of the inheritance hierarchy, with superclass listeners + being invoked before subclass listeners. Finally, if an entity has + multiple listeners for the same event, the listeners are invoked + in declaration order. + </para> + <para> + You can exclude default listeners and listeners defined in + superclasses from the invocation chain through the use of two + class-level annotations: + </para> + <itemizedlist> + <listitem> + <para><classname>ExcludeDefaultListeners</classname>: This + annotation indicates that no default listeners will be + invoked for this class, or any of its subclasses. The XML + equivalent is the empty + <literal>exclude-default-listeners</literal> element. + </para> + </listitem> + <listitem> + <para><classname>ExcludeSuperclassListeners</classname>: This + annotation will cause OpenJPA to skip invoking any listeners + declared in superclasses. The XML equivalent is empty the + <literal>exclude-superclass-listeners</literal> element. + </para> + </listitem> + </itemizedlist> + </section> + </section> + <section id="jpa_overview_pc_conclusion"> + <title>Conclusions</title> + <para> + This chapter covered everything you need to know to write persistent + class definitions in JPA. JPA + cannot use your persistent classes, however, until you complete one + additional step: you must define the persistence metadata. The next + chapter explores metadata in detail. + </para> + </section> + </chapter>
Added: incubator/openjpa/trunk/openjpa-project/src/doc/manual/jpa_overview_persistence.xml URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-project/src/doc/manual/jpa_overview_persistence.xml?rev=433761&view=auto ============================================================================== --- incubator/openjpa/trunk/openjpa-project/src/doc/manual/jpa_overview_persistence.xml (added) +++ incubator/openjpa/trunk/openjpa-project/src/doc/manual/jpa_overview_persistence.xml Tue Aug 22 14:28:53 2006 @@ -0,0 +1,219 @@ + + <chapter id="jpa_overview_persistence"> + <title>Persistence</title> + <indexterm zone="jpa_overview_persistence"> + <primary>Persistence</primary> + </indexterm> + <indexterm zone="jpa_overview_persistence"> + <primary>EntityManagerFactory</primary> + <secondary>construction</secondary> + </indexterm> + <indexterm zone="jpa_overview_persistence"> + <primary>Persistence</primary> + <secondary>getEntityManagerFactory</secondary> + </indexterm> + <indexterm zone="jpa_overview_persistence"> + <primary>getEntityManagerFactory</primary> + <seealso>Persistence</seealso> + </indexterm> + <mediaobject> + <imageobject> +<!-- PNG image data, 427 x 121 (see README) --> + <imagedata fileref="img/persistence.png" width="285px"/> + </imageobject> + </mediaobject> + <note> + <para> + OpenJPA also includes the + <ulink url="../../api/openjpa/persistence/OpenJPAPersistence.html"><classname>OpenJPAPersistence</classname></ulink> helper class to provide + additional utility methods. + </para> + </note> + <para> + Within a container, you will typically use <emphasis>injection + </emphasis> to access an <classname>EntityManagerFactory</classname>. + Applications operating of a container, however, can use the + <ulink url="http://java.sun.com/javaee/5/docs/api/javax/persistence/Persistence.html"><classname>Persistence</classname></ulink> class to obtain + <classname>EntityManagerFactory</classname> objects in a vendor-neutral + fashion. + </para> + <programlisting format="linespecific"> +public static EntityManagerFactory createEntityManagerFactory (String name); +public static EntityManagerFactory createEntityManagerFactory (String name, Map props); +</programlisting> + <para> + Each <methodname>createEntityManagerFactory</methodname> method searches + the system for an <classname>EntityManagerFactory</classname> definition + with the given name. Use <literal>null</literal> for an unnamed factory. + The optional map contains vendor-specific property settings used to further + configure the factory. + </para> + <para><filename>persistence.xml</filename> files define <classname> + EntityManagerFactories</classname>. The <methodname> + createEntityManagerFactory</methodname> methods search for <filename> + persistence.xml</filename> files within the <filename>META-INF</filename> + directory of any <literal>CLASSPATH</literal> element. For example, if + your <literal>CLASSPATH</literal> contains the <filename>conf</filename> + directory, you could place an <classname>EntityManagerFactory</classname> + definition in <filename>conf/META-INF/persistence.xml</filename>. + </para> + <section id="jpa_overview_persistence_xml"> + <title>persistence.xml</title> + <para> + The <filename>persistence.xml</filename> file format obeys the following + Document Type Descriptor (DTD): + </para> + <programlisting format="linespecific"> +<!ELEMENT persistence (persistence-unit*)> +<!ELEMENT persistence-unit (description?,provider?,jta-datasource?, + non-jta-datasource?,(class|jar-file|mapping-file)*, + exclude-unlisted-classes?,properties?)> +<!ATTLIST persistence-unit name CDATA #REQUIRED> +<!ATTLIST persistence-unit transaction-type (JTA|RESOURCE_LOCAL) "JTA"> +<!ELEMENT description (#PCDATA)> +<!ELEMENT provider (#PCDATA)> +<!ELEMENT jta-datasource (#PCDATA)> +<!ELEMENT non-jta-datasource (#PCDATA)> +<!ELEMENT mapping-file (#PCDATA)> +<!ELEMENT jar-file (#PCDATA)> +<!ELEMENT class (#PCDATA)> +<!ELEMENT exclude-unlisted-classes EMPTY> +<!ELEMENT properties (property*)> +<!ELEMENT property EMPTY> +<!ATTLIST property name CDATA #REQUIRED> +<!ATTLIST property value CDATA #REQUIRED> +</programlisting> + <para> + The root element of a <filename>persistence.xml</filename> file is + <literal>persistence</literal>, which then contains one or more + <literal>persistence-unit</literal> definitions. + Each persistence unit describes the configuration for the entity + managers created by the persistence unit's entity manager factory. + The persistence unit can specify these elements and attribtues. + </para> + <itemizedlist> + <listitem> + <para><literal>name</literal>: This is the name you pass to the + <methodname>Persistence.createEntityManagerFactory</methodname> + methods described above. The name attribute is required. + </para> + </listitem> + <listitem> + <para><literal>transaction-type</literal>: Whether to use managed + (<literal>JTA</literal>) or local + (<literal>RESOURCE_LOCAL</literal>) transaction management. + Defaults to <literal>JTA</literal>. + </para> + </listitem> + <listitem> + <para><literal>provider</literal>: If you are using a third-party + JPA vendor, this element names its implementation of the + <ulink url="http://java.sun.com/javaee/5/docs/api/javax/persistence/spi/PersistenceProvider.html"><classname>PersistenceProvider</classname></ulink> bootstrapping + interface. + </para> + <note> + <para> + Set the <literal>provider</literal> to <classname> + org.apache.openjpa.persistence.PersistenceProviderImpl</classname> + to use OpenJPA. + </para> + </note> + </listitem> + <listitem> + <para><literal>jta-data-source</literal>: The JNDI name of a JDBC + <classname>DataSource</classname> that is automatically enlisted + in JTA transactions. This may be an XA <classname> + DataSource</classname>. + </para> + </listitem> + <listitem> + <para><literal>non-jta-data-source</literal>: The JNDI name of a JDBC + <classname>DataSource</classname> that is not enlisted + in JTA transactions. + </para> + </listitem> + <listitem> + <para><literal>mapping-file</literal>*: The resource names of + XML mapping files for entities and embeddable classes. + You can also specify mapping information in an <filename> + orm.xml</filename> file in your <filename>META-INF</filename> + directory. If present, the <filename>orm.xml</filename> + mapping file will be read automatically. + </para> + </listitem> + <listitem> + <para><literal>jar-file</literal>*: The names of jar files containing + entities and embeddable classes. The implementation will scan + the jar for annotated classes. + </para> + </listitem> + <listitem> + <para><literal>class</literal>*: The class names of entities and + embeddable classes. + </para> + </listitem> + <listitem> + <para><literal>properties</literal>: This element contains nested + <literal>property</literal> elements used to specify + vendor-specific settings. Each <literal>property</literal> + has a name attribute and a value attribute. + </para> + <note> + <para> + The Reference Guide's <xref linkend="ref_guide_conf"/> + describes OpenJPA's configuration properties. + </para> + </note> + </listitem> + </itemizedlist> + <para> + Here is a typical <filename>persistence.xml</filename> file for a + non-EE environment: + </para> + <example id="jpa_overview_persistence_xmlex"> + <title>persistence.xml</title> + <programlisting format="linespecific"> +<?xml version="1.0"?> +<persistence> + <persistence-unit name="openjpa"> + <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider> + <class>tutorial.Animal</class> + <class>tutorial.Dog</class> + <class>tutorial.Rabbit</class> + <class>tutorial.Snake</class> + <properties> + <property name="openjpa.ConnectionURL" value="jdbc:hsqldb:tutorial_database"/> + <property name="openjpa.ConnectionDriverName" value="org.hsqldb.jdbcDriver"/> + <property name="openjpa.ConnectionUserName" value="sa"/> + <property name="openjpa.ConnectionPassword" value=""/> + <property name="openjpa.Log" value="DefaultLevel=WARN, Tool=INFO"/> + </properties> + </persistence-unit> +</persistence> +</programlisting> + </example> + </section> + <section id="jpa_overview_persistence_use"> + <title>Non-EE Use</title> + <para> + The example below demonstrates the <classname>Persistence</classname> + class in action. You will typically execute code like this on + application startup, then cache the resulting factory for future use. + This bootstrapping code is only necessary in non-EE environments; in + an EE environment <classname>EntityManagerFactories</classname> are + typically injected. + </para> + <example id="jpa_overview_persistence_getemfactory"> + <title>Obtaining an EntityManagerFactory</title> + <programlisting format="linespecific"> +// if your persistence.xml file does not contain all settings already, you +// can add vendor settings to a map +Properties props = new Properties (); +... + +// create the factory defined by the "openjpa" entity-manager entry +EntityManagerFactory emf = Persistence.createEntityManagerFactory ("openjpa", props); +</programlisting> + </example> + </section> + </chapter>
