Refined dynamic model/XML doco

git-svn-id: https://svn.jboss.org/repos/hibernate/trunk/Hibernate3/doc@6083 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Christian Bauer 2005-03-16 11:44:48 +00:00
parent bf75f1c24c
commit 4f2d1c22fc
4 changed files with 138 additions and 49 deletions

View File

@ -372,9 +372,10 @@
<para>
<literal>entity-name</literal> (optional): Hibernate3 allows a class to be mapped
multiple times (to different tables, potentially), and allows entity mappings that
are represented by Maps or XML at the java level. In these cases, you should
are represented by Maps or XML at the Java level. In these cases, you should
provide an explicit arbitrary name for the entity. See
<xref linkend="persistent-classes-dynamic"/> for more information.
<xref linkend="persistent-classes-dynamicmodels"/> and <xref linkend="xml"/>
for more information.
</para>
</callout>
<callout arearefs="class18">

View File

@ -377,7 +377,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
the other techniques described above.
</para>
<table frame="topbot" id="configuration-optional-properties" revision="7">
<table frame="topbot" id="configuration-optional-properties" revision="8">
<title>Hibernate Configuration Properties</title>
<tgroup cols="2">
<colspec colname="c1" colwidth="1*"/>
@ -482,6 +482,19 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.default_entity_mode</literal>
</entry>
<entry>
Set a default mode for entity representation for all sessions
opened from this <literal>SessionFactory</literal>
<para>
<literal>dynamic-map</literal>, <literal>dom4j</literal>,
<literal>pojo</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.order_updates</literal>

View File

@ -309,18 +309,38 @@ public class DomesticCat extends Cat {
</sect1>
<sect1 id="persistent-classes-dynamic" revision="2">
<title>Dynamic models</title>
<sect1 id="persistent-classes-dynamicmodels">
<title>Dynamic modelss</title>
<para>
Hibernate also supports dynamic domain models, using <literal>Map</literal>s of
<literal>Map</literal>s. With this approach, you don't write persistent classes,
a Hibernate mapping file for each "entity" is sufficient:
<emphasis>Note that the following features are currently considered
experimental and may change in the near future.</emphasis>
</para>
<para>
Persistent entities don't necessarily have to be represented as POJO classes
or as JavaBean objects at runtime. Hibernate also supports dynamic models
(using <literal>Map</literal>s of <literal>Map</literal>s at runtime) and the
representation of entities as DOM4J trees. With this approach, you don't
write persistent classes, only mapping files.
</para>
<para>
By default, Hibernate works in normal POJO mode. You may set a default entity
representation mode for a particular <literal>SessionFactory</literal> using the
<literal>default_entity_mode</literal> configuration option (see
<xref linkend="configuration-optional-properties"/>.
</para>
<para>
The following examples demonstrates the representation using <literal>Map</literal>s.
First, in the mapping file, an <literal>entity-name</literal> has to be declared
instead of (or in addition to) a class name:
</para>
<programlisting><![CDATA[<hibernate-mapping>
<class entity-name="TestMap">
<class entity-name="Customer">
<id name="id"
type="long"
@ -336,16 +356,16 @@ public class DomesticCat extends Cat {
column="ADDRESS"
type="string"/>
<many-to-one name="parent"
column="PARENT_ID"
class="TestMap"/>
<many-to-one name="organization"
column="ORGANIZATION_ID"
class="Organization"/>
<bag name="children"
<bag name="orders"
inverse="true"
lazy="false"
cascade="all">
<key column="PARENT_ID"/>
<one-to-many class="TestMap"/>
<key column="CUSTOMER_ID"/>
<one-to-many class="Order"/>
</bag>
</class>
@ -353,23 +373,38 @@ public class DomesticCat extends Cat {
</hibernate-mapping>]]></programlisting>
<para>
At runtime, you just instantiate <literal>HashMap</literal>s and use
the Hibernate entity name to refer to a particular type:
Note that even though associations are declared using target class names,
the target type of an associations may also be a dynamic entity instead
of a POJO.
</para>
<para>
After setting the default entity mode to <literal>dynamic-map</literal>
for the <literal>SessionFactory</literal>, we can at runtime work with
<literal>Map</literal>s of <literal>Map</literal>s:
</para>
<programlisting><![CDATA[Session s = openSession();
Transaction t = s.beginTransaction();
Map parent = new HashMap();
parent.put("name", "foo");
parent.put("address", "bar");
Transaction tx = s.beginTransaction();
Session s = openSession();
Map child = new HashMap();
child.put("name", "fooTwo");
child.put("address", "barTwo");
child.put("parent", parent);
// Create a customer
Map david = new HashMap();
david.put("name", "David");
s.save("TestMap", parent);
t.commit();
// Create an organization
Map foobar = new HashMap();
foobar.put("name", "Foobar Inc.");
// Link both
david.put("organization", foobar);
// Save both
s.save("Customer", david);
s.save("Organization", foobar);
tx.commit();
s.close();]]></programlisting>
<para>
@ -380,6 +415,40 @@ s.close();]]></programlisting>
allowing to add a proper domain model implementation on top later on.
</para>
<para>
Entity representation modes can also be set on a per <literal>Session</literal>
basis:
</para>
<programlisting><![CDATA[Session dynamicSession = pojoSession.getSession(EntityMode.MAP);
// Create a customer
Map david = new HashMap();
david.put("name", "David");
dynamicSession.save("Customer", david);
...
dynamicSession.flush();
dynamicSession.close()
...
// Continue on pojoSession
]]></programlisting>
<para>
Please note that the call to <literal>getSession()</literal> using an
<literal>EntityMode</literal> is on the <literal>Session</literal> API, not the
<literal>SessionFactory</literal>. That way, the new <literal>Session</literal>
shares the underlying JDBC connection, transaction, and other context
information. This means you don't have tocall <literal>flush()</literal>
and <literal>close()</literal> on the secondary <literal>Session</literal>, and
also leave the transaction and connection handling to the primary unit of work.
</para>
<para>
More information about the XML representation capabilities can be found
in <xref linkend="xml"/>.
</para>
</sect1>
<para>

View File

@ -1,42 +1,45 @@
<chapter id="xml">
<title>XML Mapping</title>
<emphasis>
Note that this is an experimental feature in Hibernate 3.0 and is under
extremely active development.
</emphasis>
<sect1 id="xml-intro" revision="1">
<title>Working with XML data</title>
<para>
Hibernate lets you work with persistent XML data in much the same way
you work with persistent POJOs. A parsed XML tree can be thought of
as just another way to represent the relational data at the object level.
as just another way to represent the relational data at the object level,
instead of POJOs.
</para>
<para>
Hibernate supports dom4j as API for manipulating XML trees. You can write
queries that retrieve dom4j trees from the database and have any
modification you make to the tree automatically synchronized to the
database. You can even take an XML document, parse it using dom4j, and
write it to the database with any of Hibernate's basic operations:
<literal>persist(), saveOrUpdate(), merge(), delete(), replicate()</literal>
(merge is not yet supported in Hibernate 3.0rc1).
(merging is not yet supported).
</para>
<para>
This feature has many applications including data import/export,
externalization of entity data via JMS or SOAP and XSLT-based reporting.
</para>
<para>
An single mapping may be used to simultaneously map properties of a class
A single mapping may be used to simultaneously map properties of a class
and nodes of an XML document to the database, or, if there is no class to map,
it may be used to map just the XML.
</para>
<para>
<emphasis>
Note that this is an experimental feature in Hibernate 3.0 and is under
extremely active development.
</emphasis>
</para>
<sect2>
<sect2 id="xml-intro-mapping">
<title>Specifying XML and class mapping together</title>
<para>
Here is an example of mapping a POJO and XML simultaneously:
</para>
@ -64,7 +67,8 @@
</sect2>
<sect2>
<title>Specifying just an XML mapping</title>
<title>Specifying only an XML mapping</title>
<para>
Here is an example where there is no POJO class:
</para>
@ -94,19 +98,21 @@
</class>]]></programlisting>
<para>
This mapping will let us access the data as a dom4j tree, or as a graph of
This mapping allows you to access the data as a dom4j tree, or as a graph of
property name/value pairs (java <literal>Map</literal>s). The property names
are purely logical constructs that may be referred to in HQL queries.
</para>
</sect2>
</sect1>
<sect1 id="xml-mapping" revision="1">
<title>XML mapping metadata</title>
<para>
Many Hibernate mapping elements accept the <literal>node</literal> attribute.
This let's us specify the name of an XML attribute or element that holds the
This let's you specify the name of an XML attribute or element that holds the
property or entity data. The format of the <literal>node</literal> attribute
must be one of the following:
</para>
@ -141,7 +147,7 @@
<para>
You should be careful not to leave <literal>embed-xml="true"</literal> for
too many associations, since XMl does not deal well with circularity!
too many associations, since XML does not deal well with circularity!
</para>
<programlisting><![CDATA[<class name="Customer"
@ -202,7 +208,7 @@
</customer>]]></programlisting>
<para>
If we set <literal>embed-xml="true"</literal> on the <literal>&lt;one-to-many&gt;</literal>
If you set <literal>embed-xml="true"</literal> on the <literal>&lt;one-to-many&gt;</literal>
mapping, the data might look more like this:
</para>
@ -230,14 +236,14 @@
<title>Manipulating XML data</title>
<para>
Now that we have mapped our entities to XML, we want to be able to read and
update XML documents in our application. We do this by obtaining a dom4j session:
Let's rearead and update XML documents in the application. We do this by
obtaining a dom4j session:
</para>
<programlisting><![CDATA[Document doc = ....;
Session session = factory.openSession();
Session dom4jSession = session.openSession(EntityMode.DOM4J);
Session dom4jSession = session.getSession(EntityMode.DOM4J);
Transaction tx = session.beginTransaction();
List results = dom4jSession
@ -253,7 +259,7 @@ tx.commit();
session.close();]]></programlisting>
<programlisting><![CDATA[Session session = factory.openSession();
Session dom4jSession = session.openSession(EntityMode.DOM4J);
Session dom4jSession = session.getSession(EntityMode.DOM4J);
Transaction tx = session.beginTransaction();
Element cust = (Element) dom4jSession.get("Customer", customerId);