Note that the following features are currently considered experimental and may change in the near future.
Persistent entities don't necessarily have to be represented as POJO classes
or as JavaBean objects at runtime. Hibernate also supports dynamic models
(using Map
s of Map
s at runtime) and the
representation of entities as DOM4J trees. With this approach, you don't
write persistent classes, only mapping files.
By default, Hibernate works in normal POJO mode. You may set a default entity
representation mode for a particular SessionFactory
using the
default_entity_mode
configuration option (see
Table 3.3, “Hibernate Configuration Properties”.
The following examples demonstrates the representation using Map
s.
First, in the mapping file, an entity-name
has to be declared
instead of (or in addition to) a class name:
<hibernate-mapping> <class entity-name="Customer"> <id name="id" type="long" column="ID"> <generator class="sequence"/> </id> <property name="name" column="NAME" type="string"/> <property name="address" column="ADDRESS" type="string"/> <many-to-one name="organization" column="ORGANIZATION_ID" class="Organization"/> <bag name="orders" inverse="true" lazy="false" cascade="all"> <key column="CUSTOMER_ID"/> <one-to-many class="Order"/> </bag> </class> </hibernate-mapping>
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.
After setting the default entity mode to dynamic-map
for the SessionFactory
, we can at runtime work with
Map
s of Map
s:
Session s = openSession(); Transaction tx = s.beginTransaction(); Session s = openSession(); // Create a customer Map david = new HashMap(); david.put("name", "David"); // 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();
The advantages of a dynamic mapping are quick turnaround time for prototyping without the need for entity class implementation. However, you lose compile-time type checking and will very likely deal with many exceptions at runtime. Thanks to the Hibernate mapping, the database schema can easily be normalized and sound, allowing to add a proper domain model implementation on top later on.
Entity representation modes can also be set on a per Session
basis:
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
Please note that the call to getSession()
using an
EntityMode
is on the Session
API, not the
SessionFactory
. That way, the new Session
shares the underlying JDBC connection, transaction, and other context
information. This means you don't have tocall flush()
and close()
on the secondary Session
, and
also leave the transaction and connection handling to the primary unit of work.
More information about the XML representation capabilities can be found in Chapter 18, XML Mapping.