[hibernate-commits] Hibernate SVN: r19978 - core/trunk/documentation/manual/src/main/docbook/en-US/content.
hibernate-commits at lists.jboss.org
hibernate-commits at lists.jboss.org
Tue Jul 20 20:58:11 EDT 2010
Author: steve.ebersole at jboss.com
Date: 2010-07-20 20:58:10 -0400 (Tue, 20 Jul 2010)
New Revision: 19978
Modified:
core/trunk/documentation/manual/src/main/docbook/en-US/content/persistent_classes.xml
Log:
HHH-5397 - Odds and ends from documentation merge : persistent_classes.xml
Modified: core/trunk/documentation/manual/src/main/docbook/en-US/content/persistent_classes.xml
===================================================================
--- core/trunk/documentation/manual/src/main/docbook/en-US/content/persistent_classes.xml 2010-07-20 12:45:55 UTC (rev 19977)
+++ core/trunk/documentation/manual/src/main/docbook/en-US/content/persistent_classes.xml 2010-07-21 00:58:10 UTC (rev 19978)
@@ -2,10 +2,10 @@
<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
- ~ Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ ~ Copyright (c) 2010, Red Hat Inc. or third-party contributors as
~ indicated by the @author tags or express copyright attribution
~ statements applied by the authors. All third-party contributions are
- ~ distributed under license by Red Hat Middleware LLC.
+ ~ distributed under license by Red Hat Inc.
~
~ This copyrighted material is made available to anyone wishing to use, modify,
~ copy, or redistribute it subject to the terms and conditions of the GNU
@@ -27,39 +27,40 @@
<!ENTITY % BOOK_ENTITIES SYSTEM "../HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.ent">
%BOOK_ENTITIES;
]>
-<chapter id="persistent-classes" revision="2">
- <title>Persistent Classes</title>
- <para>Persistent classes are classes in an application that implement the
- entities of the business problem (e.g. Customer and Order in an E-commerce
- application). Not all instances of a persistent class are considered to be
- in the persistent state. For example, an instance can instead be transient
- or detached.</para>
+<chapter id="persistent-classes">
+ <title>Persistent Classes</title>
- <para>Hibernate works best if these classes follow some simple rules, also
- known as the Plain Old Java Object (POJO) programming model. However, none
- of these rules are hard requirements. Indeed, Hibernate3 assumes very little
- about the nature of your persistent objects. You can express a domain model
- in other ways (using trees of <literal>Map</literal> instances, for
- example).</para>
+ <para>
+ Persistent classes are classes in an application that implement the entities of the business problem
+ (e.g. Customer and Order in an E-commerce application). The term "persistent" here means that the classes
+ are able to be persisted, not that they are in the persistent state (see <xref linkend="objectstate-overview"/>
+ for discussion).
+ </para>
- <section id="persistent-classes-pojo">
- <title>A simple POJO example</title>
+ <para>
+ Hibernate works best if these classes follow some simple rules, also known as the Plain Old Java Object (POJO)
+ programming model. However, none of these rules are hard requirements. Indeed, Hibernate assumes very little
+ about the nature of your persistent objects. You can express a domain model in other ways (using trees of
+ <interfacename>java.util.Map</interfacename> instances, for example).
+ </para>
- <para>Most Java applications require a persistent class representing
- felines. For example:</para>
+ <section id="persistent-classes-pojo">
+ <title>A simple POJO example</title>
- <programlisting role="JAVA">package eg;
+ <example id="persistent-classes-pojo-example-cat">
+ <title>Simple POJO representing a cat</title>
+ <programlisting role="JAVA">package eg;
import java.util.Set;
import java.util.Date;
public class Cat {
- private Long id; // identifier
+private Long id; // identifier
- private Date birthdate;
- private Color color;
- private char sex;
- private float weight;
+private Date birthdate;
+private Color color;
+private char sex;
+private float weight;
private int litterId;
private Cat mother;
@@ -119,107 +120,136 @@
public Set getKittens() {
return kittens;
}
-
+
// addKitten not needed by Hibernate
public void addKitten(Cat kitten) {
- kitten.setMother(this);
- kitten.setLitterId( kittens.size() );
+ kitten.setMother(this);
+ kitten.setLitterId( kittens.size() );
kittens.add(kitten);
}
}</programlisting>
+ </example>
- <para>The four main rules of persistent classes are explored in more
- detail in the following sections.</para>
- <section id="persistent-classes-pojo-constructor" revision="1">
- <title>Implement a no-argument constructor</title>
+ <para>
+ The four main rules of persistent classes are explored in more detail in the following sections.
+ </para>
- <para><literal>Cat</literal> has a no-argument constructor. All
- persistent classes must have a default constructor (which can be
- non-public) so that Hibernate can instantiate them using
- <literal>Constructor.newInstance()</literal>. It is recommended that you
- have a default constructor with at least <emphasis>package</emphasis>
- visibility for runtime proxy generation in Hibernate.</para>
- </section>
+ <section id="persistent-classes-pojo-constructor">
+ <title>Implement a no-argument constructor</title>
- <section id="persistent-classes-pojo-identifier" revision="2">
- <title>Provide an identifier property (optional)</title>
+ <para>
+ <classname>Cat</classname> has a no-argument constructor. All persistent classes must have a default
+ constructor (which can be non-public) so that Hibernate can instantiate them using
+ <literal><classname>java.lang.reflect.Constructor</classname>.newInstance()</literal>. It is recommended
+ that this constructor be defined with at least <emphasis>package</emphasis> visibility in order for
+ runtime proxy generation to work properly.
+ </para>
+ </section>
- <para><literal>Cat</literal> has a property called
- <literal>id</literal>. This property maps to the primary key column of a
- database table. The property might have been called anything, and its
- type might have been any primitive type, any primitive "wrapper" type,
- <literal>java.lang.String</literal> or
- <literal>java.util.Date</literal>. If your legacy database table has
- composite keys, you can use a user-defined class with properties of
- these types (see the section on composite identifiers later in the
- chapter.)</para>
+ <section id="persistent-classes-pojo-identifier" revision="2">
+ <title>Provide an identifier property</title>
- <para>The identifier property is strictly optional. You can leave them
- off and let Hibernate keep track of object identifiers internally. We do
- not recommend this, however.</para>
+ <note>
+ <para>
+ Historically this was considered option. While still not (yet) enforced, this should be considered
+ a deprecated feature as it will be completely required to provide a identifier property in an
+ upcoming release.
+ </para>
+ </note>
- <para>In fact, some functionality is available only to classes that
- declare an identifier property:</para>
+ <para>
+ <classname>Cat</classname> has a property named <literal>id</literal>. This property maps to the
+ primary key column(s) of the underlying database table. The type of the identifier property can
+ be any "basic" type (see <xref linkend="types.value.basic"/>). See <xref linkend="components-compositeid"/>
+ for information on mapping composite (multi-column) identifiers.
+ </para>
- <itemizedlist spacing="compact">
- <listitem>
- <para>Transitive reattachment for detached objects (cascade update
- or cascade merge) - see <xref
- linkend="objectstate-transitive" /></para>
- </listitem>
+ <note>
+ <para>
+ Identifiers do not necessarily need to identify column(s) in the database physically defined
+ as a primary key. They should just identify columns that can be used to uniquely identify rows
+ in the underlying table.
+ </para>
+ </note>
- <listitem>
- <para><literal>Session.saveOrUpdate()</literal></para>
- </listitem>
+ <para>
+ We recommend that you declare consistently-named identifier properties on persistent classes and that you use
+ a nullable (i.e., non-primitive) type.
+ </para>
+ </section>
- <listitem>
- <para><literal>Session.merge()</literal></para>
- </listitem>
- </itemizedlist>
- <para>We recommend that you declare consistently-named identifier
- properties on persistent classes and that you use a nullable (i.e.,
- non-primitive) type.</para>
- </section>
+ <section id="persistent-classes-pojo-final">
+ <title>Prefer non-final classes (semi-optional)</title>
- <section id="persistent-classes-pojo-final">
- <title>Prefer non-final classes (optional)</title>
+ <para>
+ A central feature of Hibernate, <emphasis>proxies</emphasis> (lazy loading), depends upon the
+ persistent class being either non-final, or the implementation of an interface that declares all public
+ methods. You can persist <literal>final</literal> classes that do not implement an interface with
+ Hibernate; you will not, however, be able to use proxies for lazy association fetching which will
+ ultimately limit your options for performance tuning. To persist a <literal>final</literal>
+ class which does not implement a "full" interface you must disable proxy generation. See
+ <xref linkend="persistent-classes-pojo-final-example-disable-proxies-xml"/> and
+ <xref linkend="persistent-classes-pojo-final-example-disable-proxies-ann"/>.
+ </para>
- <para>A central feature of Hibernate, <emphasis>proxies</emphasis>,
- depends upon the persistent class being either non-final, or the
- implementation of an interface that declares all public methods.</para>
+ <example id="persistent-classes-pojo-final-example-disable-proxies-xml">
+ <title>Disabling proxies in <literal>hbm.xml</literal></title>
+ <programlisting role="XML"><![CDATA[<class name="Cat" lazy="false"...>...</class>]]></programlisting>
+ </example>
- <para>You can persist <literal>final</literal> classes that do not
- implement an interface with Hibernate. You will not, however, be able to
- use proxies for lazy association fetching which will ultimately limit
- your options for performance tuning.</para>
+ <example id="persistent-classes-pojo-final-example-disable-proxies-ann">
+ <title>Disabling proxies in annotations</title>
+ <programlisting role="JAVA"><![CDATA[@Entity @Proxy(lazy=false) public class Cat { ... }]]></programlisting>
+ </example>
- <para>You should also avoid declaring <literal>public final</literal>
- methods on the non-final classes. If you want to use a class with a
- <literal>public final</literal> method, you must explicitly disable
- proxying by setting <literal>lazy="false"</literal>.</para>
- </section>
+ <para>
+ If the <literal>final</literal> class does implement a proper interface, you could alternatively tell
+ Hibernate to use the interface instead when generating the proxies. See
+ <xref linkend="persistent-classes-pojo-final-example-proxy-interface-xml"/> and
+ <xref linkend="persistent-classes-pojo-final-example-proxy-interface-ann"/>.
- <section id="persistent-classes-pojo-accessors" revision="2">
- <title>Declare accessors and mutators for persistent fields
- (optional)</title>
+ </para>
- <para><literal>Cat</literal> declares accessor methods for all its
- persistent fields. Many other ORM tools directly persist instance
- variables. It is better to provide an indirection between the relational
- schema and internal data structures of the class. By default, Hibernate
- persists JavaBeans style properties and recognizes method names of the
- form <literal>getFoo</literal>, <literal>isFoo</literal> and
- <literal>setFoo</literal>. If required, you can switch to direct field
- access for particular properties.</para>
+ <example id="persistent-classes-pojo-final-example-proxy-interface-xml">
+ <title>Proxying an interface in <literal>hbm.xml</literal></title>
+ <programlisting role="XML"><![CDATA[<class name="Cat" proxy="ICat"...>...</class>]]></programlisting>
+ </example>
- <para>Properties need <emphasis>not</emphasis> be declared public -
- Hibernate can persist a property with a default,
- <literal>protected</literal> or <literal>private</literal> get / set
- pair.</para>
+ <example id="persistent-classes-pojo-final-example-proxy-interface-ann">
+ <title>Proxying an interface in annotations</title>
+ <programlisting role="JAVA"><![CDATA[@Entity @Proxy(proxyClass=ICat.class) public class Cat implements ICat { ... }]]></programlisting>
+ </example>
+
+ <para>
+ You should also avoid declaring <literal>public final</literal> methods as this will again limit
+ the ability to generate <emphasis>proxies</emphasis> from this class. If you want to use a
+ class with <literal>public final</literal> methods, you must explicitly disable proxying. Again, see
+ <xref linkend="persistent-classes-pojo-final-example-disable-proxies-xml"/> and
+ <xref linkend="persistent-classes-pojo-final-example-disable-proxies-ann"/>.
+ </para>
+ </section>
+
+ <section id="persistent-classes-pojo-accessors">
+ <title>Declare accessors and mutators for persistent fields (optional)</title>
+
+ <para>
+ <classname>Cat</classname> declares accessor methods for all its persistent fields. Many other ORM
+ tools directly persist instance variables. It is better to provide an indirection between the relational
+ schema and internal data structures of the class. By default, Hibernate persists JavaBeans style
+ properties and recognizes method names of the form <literal>getFoo</literal>, <literal>isFoo</literal>
+ and <literal>setFoo</literal>. If required, you can switch to direct field access for particular
+ properties.
+ </para>
+
+ <para>
+ Properties need <emphasis>not</emphasis> be declared public. Hibernate can persist a property declared
+ with <literal>package</literal>, <literal>protected</literal> or <literal>private</literal> visibility
+ as well.
+ </para>
+ </section>
</section>
- </section>
<section id="persistent-classes-inheritance">
<title>Implementing inheritance</title>
@@ -447,44 +477,53 @@
found in <xref linkend="xml" />.</para>
</section>
- <section id="persistent-classes-tuplizers" revision="1">
- <title>Tuplizers</title>
- <para><literal>org.hibernate.tuple.Tuplizer</literal>, and its
- sub-interfaces, are responsible for managing a particular representation
- of a piece of data given that representation's
- <literal>org.hibernate.EntityMode</literal>. If a given piece of data is
- thought of as a data structure, then a tuplizer is the thing that knows
- how to create such a data structure and how to extract values from and
- inject values into such a data structure. For example, for the POJO entity
- mode, the corresponding tuplizer knows how create the POJO through its
- constructor. It also knows how to access the POJO properties using the
- defined property accessors.</para>
+ <section id="persistent-classes-tuplizers" revision="1">
+ <title>Tuplizers</title>
- <para>There are two high-level types of Tuplizers, represented by the
- <literal>org.hibernate.tuple.entity.EntityTuplizer</literal> and
- <literal>org.hibernate.tuple.component.ComponentTuplizer</literal>
- interfaces. <literal>EntityTuplizer</literal>s are responsible for
- managing the above mentioned contracts in regards to entities, while
- <literal>ComponentTuplizer</literal>s do the same for components.</para>
+ <para>
+ <interfacename>org.hibernate.tuple.Tuplizer</interfacename> and its sub-interfaces are responsible for
+ managing a particular representation of a piece of data given that representation's
+ <classname>org.hibernate.EntityMode</classname>. If a given piece of data is thought of as a data
+ structure, then a tuplizer is the thing that knows how to create such a data structure, how to extract
+ values from such a data structure and how to inject values into such a data structure. For example, for
+ the POJO entity mode, the corresponding tuplizer knows how create the POJO through its constructor.
+ It also knows how to access the POJO properties using the defined property accessors.
+ </para>
- <para>Users can also plug in their own tuplizers. Perhaps you require that
- a <literal>java.util.Map</literal> implementation other than
- <literal>java.util.HashMap</literal> be used while in the dynamic-map
- entity-mode. Or perhaps you need to define a different proxy generation
- strategy than the one used by default. Both would be achieved by defining
- a custom tuplizer implementation. Tuplizer definitions are attached to the
- entity or component mapping they are meant to manage. Going back to the
- example of our customer entity <xref
- linkend="example-defining-tuplizer-using-annotations" /> shows how to
- configure tuplizers using annotations whereas <xref
- linkend="example-defining-tuplizer-using-mapping-file" /> shows how to do
- the same thing using Hibernate mapping files.</para>
+ <para>
+ There are two (high-level) types of Tuplizers:
+ <itemizedlist>
+ <listitem>
+ <para>
+ <interfacename>org.hibernate.tuple.entity.EntityTuplizer</interfacename> which is
+ responsible for managing the above mentioned contracts in regards to entities
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <interfacename>org.hibernate.tuple.component.ComponentTuplizer</interfacename> which does the
+ same for components
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
- <example id="example-defining-tuplizer-using-annotations">
- <title>Mapping custom tuplizers using annotations</title>
+ <para>
+ Users can also plug in their own tuplizers. Perhaps you require that
+ <interfacename>java.util.Map</interfacename> implementation other than
+ <classname>java.util.HashMap</classname> be used while in the dynamic-map entity-mode. Or perhaps you
+ need to define a different proxy generation strategy than the one used by default. Both would be achieved
+ by defining a custom tuplizer implementation. Tuplizer definitions are attached to the entity or component
+ mapping they are meant to manage. Going back to the example of our <classname>Customer</classname> entity,
+ <xref linkend="example-specify-custom-tuplizer-ann"/> shows how to specify a custom
+ <interfacename>org.hibernate.tuple.entity.EntityTuplizer</interfacename> using annotations while
+ <xref linkend="example-specify-custom-tuplizer-xml"/> shows how to do the same in <literal>hbm.xml</literal>
+ </para>
- <programlisting role="XML">@Entity
+ <example id="example-specify-custom-tuplizer-ann">
+ <title>Specify custom tuplizers in annotations</title>
+<programlisting role="JAVA">@Entity
@Tuplizer(impl = DynamicEntityTuplizer.class)
public interface Cuisine {
@Id
@@ -499,13 +538,10 @@
public Country getCountry();
public void setCountry(Country country);
}</programlisting>
- </example>
-
- <example>
- <title id="example-defining-tuplizer-using-mapping-file">Mapping custom
- tuplizers using mapping files</title>
-
- <programlisting role="XML"><hibernate-mapping>
+ </example>
+ <example id="example-specify-custom-tuplizer-xml">
+ <title>Specify custom tuplizers in <literal>hbm.xml</literal></title>
+<programlisting role="XML"><hibernate-mapping>
<class entity-name="Customer">
<!--
Override the dynamic-map entity-mode
@@ -521,33 +557,29 @@
<!-- other properties -->
...
</class>
-</hibernate-mapping>
-</programlisting>
- </example>
- </section>
+</hibernate-mapping></programlisting>
+ </example>
+ </section>
- <section id="persistent-classes-entity-name-resolver" revision="0">
- <title>EntityNameResolvers</title>
+ <section id="persistent-classes-entity-name-resolver">
+ <title>EntityNameResolvers</title>
- <para>The <interfacename>org.hibernate.EntityNameResolver</interfacename>
- interface is a contract for resolving the entity name of a given entity
- instance. The interface defines a single method
- <methodname>resolveEntityName</methodname> which is passed the entity
- instance and is expected to return the appropriate entity name (null is
- allowed and would indicate that the resolver does not know how to resolve
- the entity name of the given entity instance). Generally speaking, an
- <interfacename>org.hibernate.EntityNameResolver</interfacename> is going
- to be most useful in the case of dynamic models. One example might be
- using proxied interfaces as your domain model. The hibernate test suite
- has an example of this exact style of usage under the
- <package>org.hibernate.test.dynamicentity.tuplizer2</package>. Here is
- some of the code from that package for illustration.</para>
+ <para>
+ <interfacename>org.hibernate.EntityNameResolver</interfacename> is a contract for resolving the entity name
+ of a given entity instance. The interface defines a single method <methodname>resolveEntityName</methodname>
+ which is passed the entity instance and is expected to return the appropriate entity name (null is
+ allowed and would indicate that the resolver does not know how to resolve the entity name of the given entity
+ instance). Generally speaking, an <interfacename>org.hibernate.EntityNameResolver</interfacename> is going
+ to be most useful in the case of dynamic models. One example might be using proxied interfaces as your
+ domain model. The hibernate test suite has an example of this exact style of usage under the
+ <package>org.hibernate.test.dynamicentity.tuplizer2</package>. Here is some of the code from that package
+ for illustration.
+ </para>
- <programlisting role="JAVA">
-/**
- * A very trivial JDK Proxy InvocationHandler implementation where we proxy an interface as
- * the domain model and simply store persistent state in an internal Map. This is an extremely
- * trivial example meant only for illustration.
+<programlisting role="JAVA">/**
+ * A very trivial JDK Proxy InvocationHandler implementation where we proxy an
+ * interface as the domain model and simply store persistent state in an internal
+ * Map. This is an extremely trivial example meant only for illustration.
*/
public final class DataProxyHandler implements InvocationHandler {
private String entityName;
@@ -586,9 +618,6 @@
}
}
-/**
- *
- */
public class ProxyHelper {
public static String extractEntityName(Object object) {
// Our custom java.lang.reflect.Proxy instances actually bundle
@@ -610,12 +639,14 @@
/**
* The EntityNameResolver implementation.
- * IMPL NOTE : An EntityNameResolver really defines a strategy for how entity names should be
- * resolved. Since this particular impl can handle resolution for all of our entities we want to
- * take advantage of the fact that SessionFactoryImpl keeps these in a Set so that we only ever
- * have one instance registered. Why? Well, when it comes time to resolve an entity name,
- * Hibernate must iterate over all the registered resolvers. So keeping that number down
- * helps that process be as speedy as possible. Hence the equals and hashCode impls
+ *
+ * IMPL NOTE : An EntityNameResolver really defines a strategy for how entity names
+ * should be resolved. Since this particular impl can handle resolution for all of our
+ * entities we want to take advantage of the fact that SessionFactoryImpl keeps these
+ * in a Set so that we only ever have one instance registered. Why? Well, when it
+ * comes time to resolve an entity name, Hibernate must iterate over all the registered
+ * resolvers. So keeping that number down helps that process be as speedy as possible.
+ * Hence the equals and hashCode implementations as is
*/
public class MyEntityNameResolver implements EntityNameResolver {
public static final MyEntityNameResolver INSTANCE = new MyEntityNameResolver();
@@ -651,26 +682,26 @@
}
...
-}
- </programlisting>
+</programlisting>
- <para>In order to register an
- <interfacename>org.hibernate.EntityNameResolver</interfacename> users must
- either: <orderedlist>
- <listitem>
- <para>Implement a custom <link
- linkend="persistent-classes-tuplizers">Tuplizer</link>, implementing
- the <methodname>getEntityNameResolvers</methodname> method.</para>
- </listitem>
+ <para>
+ In order to register an <interfacename>org.hibernate.EntityNameResolver</interfacename> users must either:
+ <orderedlist>
+ <listitem>
+ <para>
+ Implement a custom tuplizer (see <xref linkend="persistent-classes-tuplizers"/>), implementing
+ the <methodname>getEntityNameResolvers</methodname> method
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Register it with the <classname>org.hibernate.impl.SessionFactoryImpl</classname> (which is the
+ implementation class for <interfacename>org.hibernate.SessionFactory</interfacename>) using the
+ <methodname>registerEntityNameResolver</methodname> method.
+ </para>
+ </listitem>
+ </orderedlist>
+ </para>
+ </section>
- <listitem>
- <para>Register it with the
- <classname>org.hibernate.impl.SessionFactoryImpl</classname> (which
- is the implementation class for
- <interfacename>org.hibernate.SessionFactory</interfacename>) using
- the <methodname>registerEntityNameResolver</methodname>
- method.</para>
- </listitem>
- </orderedlist></para>
- </section>
</chapter>
More information about the hibernate-commits
mailing list