HHH-4949 - Document JPA 2 metamodel

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18874 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Steve Ebersole 2010-02-24 21:26:24 +00:00
parent 3df8bc5712
commit 1fa3112156
2 changed files with 241 additions and 0 deletions

View File

@ -70,6 +70,7 @@
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/architecture.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/configuration.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/entitymanagerapi.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/metamodel.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/transactions.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/listeners.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/batch.xml"/>

View File

@ -0,0 +1,240 @@
<?xml version='1.0' encoding='UTF-8'?>
<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
~ 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 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
~ Lesser General Public License, as published by the Free Software Foundation.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
~ for more details.
~
~ You should have received a copy of the GNU Lesser General Public License
~ along with this distribution; if not, write to:
~ Free Software Foundation, Inc.
~ 51 Franklin Street, Fifth Floor
~ Boston, MA 02110-1301 USA
-->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY jpa2Biblio '<xref linkend="JPA2"/>'>
<!ENTITY jpa2Cite '<citation>&jpa2Biblio;</citation>'>
<!ENTITY criteriaRef '<xref linkend="querycriteria"/>'>
<!ENTITY apt '<ulink url="http://java.sun.com/javase/6/docs/technotes/tools/solaris/javac.html#processing">annotation processor</ulink>'>
]>
<chapter id="metamodel">
<title>Metamodel</title>
<note>
<para>
The Metamodel itself is described in <citetitle pubwork="chapter">Chapter 5 Metamodel API</citetitle>
of the &jpa2Cite;. <citetitle pubwork="chapter">Chapter 6 Criteria API</citetitle> of the &jpa2Cite;
describes and shows uses of the metamodel in criteria queries, as does &criteriaRef;.
</para>
</note>
<para>
The metamodel is a set of objects that describe your domain model.
<interfacename>javax.persistence.metamodel.Metamodel</interfacename> acts as a repository of these metamodel
objects and provides access to them. We ask either the
<interfacename>javax.persistence.EntityManagerFactory</interfacename> or the
<interfacename>javax.persistence.EntityManager</interfacename> for a reference to the
<interfacename>javax.persistence.metamodel.Metamodel</interfacename> via their
<methodname>getMetamodel</methodname> method.
</para>
<para>
This metamodel is important in 2 ways. First, it allows providers and frameworks a generic way to
deal with an application's domain model. Persistence providers will already have some form of
metamodel that they use to describe the domain model being mapped. This API simply allows general access
to that existing information. A validation framework, for example, could use this information to
understand associations; a marshaling framework might use this information to decide how much of an
entity graph to marshal. This usage is beyond the scope of this documentation.
</para>
<important>
<para>
As of today the JPA 2 metamodel does not provide any facility for accessing relational information
pertaining to the physical model. It is expected this will be addressed in a future release of the
specification.
</para>
</important>
<para>
Second, from an application writer's perspective, it allows very fluent expression of completely type-safe
criteria queries, especially the <emphasis>Static Metamodel</emphasis> approach. The &jpa2Cite; defines a
number of ways the metamodel can be accessed and used, including the <emphasis>Static Metamodel</emphasis>
approach, which we will look at later. The <emphasis>Static Metamodel</emphasis> approach is wonderful
when the code has <ulink url="http://en.wikipedia.org/wiki/A_priori_and_a_posteriori">a priori knowledge</ulink>
of the domain model. &criteriaRef; uses this approach exclusively in its examples.
</para>
<section id="metamodel-static">
<title>Static metamodel</title>
<para>
A <emphasis>static metamodel</emphasis> is a series of classes that "mirror" the entities and embeddables
in the domain model and provide static access to the metadata about the mirrored class's attributes. We
will exclusively discuss what the &jpa2Cite; terms a <emphasis>Canonical Metamodel</emphasis>:
</para>
<blockquote>
<attribution>
<citation><xref linkend="JPA2"/>, section 6.2.1.1, pp 198-199</citation>
</attribution>
<para>
<itemizedlist>
<listitem>
<para>
For each managed class <classname>X</classname> in package <package>p</package>,
a metamodel class <classname>X_</classname> in package <package>p</package> is created.
</para>
</listitem>
<listitem>
<para>
The name of the metamodel class is derived from the name of the managed class by appending
"_" to the name of the managed class.
</para>
</listitem>
<listitem>
<para>
The metamodel class <classname>X_</classname> must be annotated with the
<interfacename>javax.persistence.StaticMetamodel</interfacename>annotation
<footnote>
<para>
<emphasis>(from the original)</emphasis> If the class was generated, the
<interfacename>javax.annotation.Generated</interfacename> annotation should be
used to annotate the class. The use of any other annotations on static metamodel
classes is undefined.
</para>
</footnote>
</para>
</listitem>
<listitem>
<para>
If class <classname>X</classname> extends another class <classname>S</classname>, where
<classname>S</classname> is the most derived managed class (i.e., entity or mapped
superclass) extended by <classname>X</classname>, then class <classname>X_</classname> must
extend class <classname>S_</classname>, where <classname>S_</classname> is the metamodel
class created for <classname>S</classname>.
</para>
</listitem>
<listitem>
<para>
For every persistent non-collection-valued attribute <emphasis>y</emphasis> declared by
class <classname>X</classname>, where the type of <emphasis>y</emphasis> is
<classname>Y</classname>, the metamodel class must contain a declaration as follows:
<programlisting><![CDATA[public static volatile SingularAttribute<X, Y> y;]]></programlisting>
</para>
</listitem>
<listitem>
<para>
For every persistent collection-valued attribute <emphasis>z</emphasis> declared by class
<classname>X</classname>, where the element type of <emphasis>z</emphasis> is
<classname>Z</classname>, the metamodel class must contain a declaration as follows:
<itemizedlist>
<listitem>
<para>
if the collection type of <emphasis>z</emphasis> is
<interfacename>java.util.Collection</interfacename>, then
<programlisting><![CDATA[public static volatile CollectionAttribute<X, Z> z;]]></programlisting>
</para>
</listitem>
<listitem>
<para>
if the collection type of <emphasis>z</emphasis> is
<interfacename>java.util.Set</interfacename>, then
<programlisting><![CDATA[public static volatile SetAttribute<X, Z> z;]]></programlisting>
</para>
</listitem>
<listitem>
<para>
if the collection type of <emphasis>z</emphasis> is
<interfacename>java.util.List</interfacename>, then
<programlisting><![CDATA[public static volatile ListAttribute<X, Z> z;]]></programlisting>
</para>
</listitem>
<listitem>
<para>
if the collection type of <emphasis>z</emphasis> is
<interfacename>java.util.Map</interfacename>, then
<programlisting><![CDATA[public static volatile MapAttribute<X, K, Z> z;]]></programlisting>
where <classname>K</classname> is the type of the key of the map in class
<classname>X</classname>
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
<para>
Import statements must be included for the needed <package>javax.persistence.metamodel</package> types
as appropriate (e.g., <interfacename>javax.persistence.metamodel.SingularAttribute</interfacename>,
<interfacename>javax.persistence.metamodel.CollectionAttribute</interfacename>,
<interfacename>javax.persistence.metamodel.SetAttribute</interfacename>,
<interfacename>javax.persistence.metamodel.ListAttribute</interfacename>,
<interfacename>javax.persistence.metamodel.MapAttribute</interfacename>) and all classes
<classname>X</classname>, <classname>Y</classname>, <classname>Z</classname>, and <classname>K</classname>.
</para>
</blockquote>
<example id="metamodel-static-ex">
<title>Static metamodel example</title>
<para>
For the <classname>Person</classname> entity
<programlisting><![CDATA[package org.hibernate.jpa2.metamodel.example;
import java.util.Set;
import javax.persistence.Entity;
@Entity
public class Person {
@Id private Long id;
private String name;
private int age;
private Address address;
@OneToMany private Set<Order> orders;
}]]></programlisting>
The corresponding canonical metamodel class, <classname>Person_</classname> would look like
<programlisting><![CDATA[package org.hibernate.jpa2.metamodel.example;
import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.SetAttribute;
import javax.persistence.metamodel.StaticMetamodel;
@StaticMetamodel( Person.class )
public class Person_ {
public static volatile SingularAttribute<Person, Long> id;
public static volatile SingularAttribute<Person, String> name;
public static volatile SingularAttribute<Person, Integer> age;
public static volatile SingularAttribute<Person, Address> address;
public static volatile SetAttribute<Person, Order> orders;
}]]></programlisting>
</para>
</example>
<note>
<para>
These canonical metamodel classes can be generated manually if you wish though it is expected
that most developers will prefer use of an &apt;. Although annotation processors themselves are
beyond the scope of this document, the Hibernate team does develop an annotation processor tool for
generating a canonical metamodel. See <citetitle>Hibernate Metamodel Generator</citetitle>.
</para>
</note>
<para>
When the Hibernate <interfacename>EntityManagerFactory</interfacename> is being built, it will
look for a canonical metamodel class for each of the managed typed is knows about and if it finds
any it will inject the appropriate metamodel information into them, as outlined in
<citation><xref linkend="JPA2"/>, section 6.2.2, pg 200</citation>
</para>
</section>
</chapter>