Anda di halaman 1dari 54

Hyperjaxb 2 - Relation persistence for

JAXB objects
Reference Documentation

Aleksei Valikov
Hyperjaxb 2 - Relation persistence for JAXB objects: Reference
Documentation
by Aleksei Valikov
Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and
further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.
Table of Contents
Preface ...................................................................................................................... v
1. Introduction ............................................................................................................ 1
Overview ........................................................................................................................... 1
Worked example ................................................................................................................. 2
2. Basics .................................................................................................................. 11
Classes and interfaces ........................................................................................................ 11
Fields .............................................................................................................................. 11
Single fields ..................................................................................................................... 12
Collection fields ................................................................................................................ 12
Simple fields .................................................................................................................... 12
Enum fields ..................................................................................................................... 12
DOM fields ...................................................................................................................... 13
Complex fields ................................................................................................................. 13
Wildcard fields ................................................................................................................. 13
Heterogeneous fields ......................................................................................................... 13
Field accessors ................................................................................................................. 13
3. Generating Hibernate mappings ................................................................................ 15
The overall process ............................................................................................................ 15
Customizations ................................................................................................................. 15
Common customization elements and types ............................................................................ 17
Ignoring classes and fields .................................................................................................. 18
Class mapping .................................................................................................................. 19
Customizing class mapping ................................................................................................. 20
Marking class as component ................................................................................................ 22
Identifier and version properties ........................................................................................... 23
Inheritance mapping .......................................................................................................... 25
Single fields ..................................................................................................................... 27
Simple, enum and DOM single fields .................................................................................... 27
Complex single fields ........................................................................................................ 29
Wildcard single fields ........................................................................................................ 30
Heterogeneous single fields ................................................................................................. 31
Collection fields ................................................................................................................ 31
Generic collection mapping ................................................................................................. 31
Simple, enum and DOM collection fields ............................................................................... 33
Complex collection fields ................................................................................................... 33
Wildcard collection fields ................................................................................................... 35
Heterogeneous collection fields ........................................................................................... 36
4. Generating Hibernate configuration ........................................................................... 37
5. Using Hyperjaxb ................................................................................................... 38
Compile-time usage: generating the mapping ......................................................................... 38
Ant usage ........................................................................................................................ 38
Maven2 usage .................................................................................................................. 40
TODO: Generating/exporting the database schema with Hyperjaxb and Hibernate ......................... 43
Run-time usage: working with objects ................................................................................... 43
Initializing JAXB context, marshaller and unmarshaller ............................................................ 43
Setting up the Hibernate session factory ................................................................................ 44
Importing data .................................................................................................................. 45
Exporting data .................................................................................................................. 45
Executing queries .............................................................................................................. 46
6. Extending Hyperjaxb .............................................................................................. 47
Understanding Hyperjaxb strategies ...................................................................................... 47
7. Credits and acknowledgements ................................................................................. 49

iv
Preface
This is a reference guide for Hyperjaxb 2. java.net project page: https://hyperjaxb2.dev.java.net/

Before we go on, a few words of gratitude: Chris Bauer (of the Hibernate team) prepared and adapted
the DocBook-XSL software in order to be able to create Hibernate's reference guide, also allowing us to
create this one.

v
Chapter 1. Introduction
Overview
In one sentence, Hyperjaxb provides a solution for the prevalent task of XML persistence which essen-
tially lies in the following three operations:

• importing or saving the document;

• exporting or loading the document;

• querying for documents or their parts.

Of course, the task of XML persistence is very generic. Hyperjaxb concentrates on a partial solution
with the following requirements and properties:

XML Schema-driven XML documents conforms to the certain XML Schema, which
defines their format, structure, data types and so on.

Relational back-end XML data is persisted in a relational database.

Data-centric Focused on documents and schemas that use XML as a data trans-
port (like sales orders, flight schedules, scientific data, and stock
quotes) rather than those intended for human consumption (books,
email, advertisements, and almost any hand-written XHTML).

Automatically generated database Database schema is automatically generated based on the given
schema XML Schema.

Nice database schema The generated database schema has the following properties:

• At least third normal form.

• Strong referential integrity.

• Human-readable.

• Names of tables and columns are based on the names of types,


elements and attributes of the initial schema (so that it is pos-
sible to associate relational constructs with the constructs of
the XML Schema).

These properties make possible the integration on the database


level.

Querying Queries are formulated in the the terms, which are close to XML.

Customizations The solution allows high level of customization.

Basically, Hyperjaxb's task is to generate the database schema and accompanying middleware based on
the XML Schema.

To solve this task, Hyperjaxb combines two technogies: Java Architecture for XML Binding and Hi-

1
Introduction

bernate. JAXB converts between XML and objects; Hibernate is used to persist object in a relational
database.

JAXB implements the conversion between XML and Java objects. To accomplish this, XML Schema
(with some additional binding configuration) is processed by the binding compiler (XJC) which gener-
ates so-called schema-derived classes (their source code). These classes bear information required for
the marshalling and unmarshalling of XML data. Together with the JAXB runtime, they allow parsing
XML into content objects (instances of schema-derived classes).

Hibernate in its turn implements object-relational persistence. Provided the object-relational mapping
configuration, Hibernate is capable of saving objects into the relational database, loading them back as
well as processing queries. Moreover, Hibernate also provides a very handy schema export tool which
can automatically generate the database schema based on the Hibernate mapping.

In order to for JAXB and Hibernate to be combined, Hibernate mapping for schema-derived classes
must be generated out of the XML Schema (as well as the schema-derived classes themselves). For this
purpose, Hyperjaxb includes an XJC add-on which analyzes classes and fields generated by JAXB and
produces the appropriate mapping.

The overall usage of Hyperjaxb in a project (provided the schema) may be sketched out as follows:

• Build phase:

• Use binding compiler (XJC) together with Hyperjaxb add-on to generate the source code of
schema-derived classes and Hibernate mapping.

• Compile the generated classes.

• Use Hibernate toolset to export the database schema.

• Runtime phase:

• Use JAXB runtime and schema-derived classes to convert between XML and content objects.

• Use Hibernate to save content objects into the database and load them back.

• Use HQL to formulate queries and process them with Hibernate. Again, use JAXB to marshall
results as XML.

Worked example
This section demonstrates the use of Hyperjaxb on the well-known purchase order
[http://www.w3.org/TR/xmlschema-0/#po.xsd] example from the XML Schema Primer
[http://www.w3.org/TR/xmlschema-0/]. Below is the original schema:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:annotation>
<xsd:documentation xml:lang="en">
Purchase order schema for Example.com.
Copyright 2000 Example.com. All rights reserved.
</xsd:documentation>
</xsd:annotation>
<xsd:element name="purchaseOrder" type="PurchaseOrderType"/>
<xsd:element name="comment" type="xsd:string"/>

2
Introduction

<xsd:complexType name="PurchaseOrderType">
<xsd:sequence>
<xsd:element name="shipTo" type="USAddress"/>
<xsd:element name="billTo" type="USAddress"/>
<xsd:element ref="comment" minOccurs="0"/>
<xsd:element name="items" type="Items"/>
</xsd:sequence>
<xsd:attribute name="orderDate" type="xsd:date"/>
</xsd:complexType>
<xsd:complexType name="USAddress">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="street" type="xsd:string"/>
<xsd:element name="city" type="xsd:string"/>
<xsd:element name="state" type="xsd:string"/>
<xsd:element name="zip" type="xsd:decimal"/>
</xsd:sequence>
<xsd:attribute name="country" type="xsd:NMTOKEN" fixed="US"/>
</xsd:complexType>
<xsd:complexType name="Items">
<xsd:sequence>
<xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="productName" type="xsd:string"/>
<xsd:element name="quantity">
<xsd:simpleType>
<xsd:restriction base="xsd:positiveInteger">
<xsd:maxExclusive value="100"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="USPrice" type="xsd:decimal"/>
<xsd:element ref="comment" minOccurs="0"/>
<xsd:element name="shipDate" type="xsd:date" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="partNum" type="SKU" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<!-- Stock Keeping Unit, a code for identifying products -->
<xsd:simpleType name="SKU">
<xsd:restriction base="xsd:string">
<xsd:pattern value="\d{3}-[A-Z]{2}"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>

XML Schema Primer [http://www.w3.org/TR/xmlschema-0/] also provides a sample XML of the pur-
chase order:

<purchaseOrder orderDate="1999-10-20">
<shipTo country="US">
<name>Alice Smith</name>
<street>123 Maple Street</street>
<city>Mill Valley</city>
<state>CA</state>

3
Introduction

<zip>90952</zip>
</shipTo>
<billTo country="US">
<name>Robert Smith</name>
<street>8 Oak Avenue</street>
<city>Old Town</city>
<state>PA</state>
<zip>95819</zip>
</billTo>
<comment>Hurry, my lawn is going wild!</comment>
<items>
<item partNum="872-AA">
<productName>Lawnmower</productName>
<quantity>1</quantity>
<USPrice>148.95</USPrice>
<comment>Confirm this is electric</comment>
</item>
<item partNum="926-AA">
<productName>Baby Monitor</productName>
<quantity>1</quantity>
<USPrice>39.98</USPrice>
<shipDate>1999-05-21</shipDate>
</item>
</items>
</purchaseOrder>

First of all, I'd like to add binding configuration for JAXB. I want schema-derived classes to be gener-
ated in the org.jvnet.hyperjaxb2.tests.po package (instead of the default generated
package for null namespaces). I'll also instruct JAXB to generate isSetField methods for fields (this
is required by Hyperjaxb):

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="1.0">
<!-- ... -->
<xsd:annotation>
<xsd:appinfo>
<jaxb:globalBindings generateIsSetMethod="true"/>
<jaxb:schemaBindings>
<jaxb:package name="org.jvnet.hyperjaxb2.tests.po"/>
</jaxb:schemaBindings>
</xsd:appinfo>
</xsd:annotation>
<!-- ... -->
</xsd:schema>

At this point, the purchase order XML Schema is already processable with Hyperjaxb. The easiest way
to start a Hyperjaxb project is to use the project template [???]. Hyperjaxb distribution provides project
templates for Ant and Maven out of the box. We will start with Ant since this is what most developers
are used to.

So the next steps are:

1. Get the template project distribution (hyperjaxb2-template-basic-version-


ant-src.zip).

2. Unzip it into the target project directory (I'll refer to this directory as to the basedir directory).

4
Introduction

3. Save the XML Schema as an *.xsd file (for instance, schema.xsd) in the basedir/
main/resources directory.

4. Save the sample XML as *.xml file (for instance, po.xml) in the basedir/test/samples
directory.

5. Run ant to execute the project build. This will generate the source code of schema-derived classes
(together with Hibernate mappings and configuration), compile the generated code, test it with the
roundtrip test case and pack it in a JAR file.

Having build the project, we can take a closer look at the generated stuff.

Let's start with examination of the produced classes (take a look into the basedir/tar-
get/generated-sources/xjc). JAXB generates two types of classes:

• Schema-derived classes that reflect constructs of the XML Schema (elements, attributes, complex
types). Each schema-derived class is represented by the interface (ex.
org.jvnet.hyperjaxb2.tests.po.Comment) and the implementing class (ex.
org.jvnet.hyperjaxb2.tests.po.impl.CommentImpl ).

• Utility runtime classes used by the generated implementation classes internally.

Therefore you'll get three packages:

org.jvnet.hyperjaxb2.tes Interface package.


ts.po
org.jvnet.hyperjaxb2.tes Implementation package.
ts.po.impl
org.jvnet.hyperjaxb2.tes Utility classes.
ts.po.impl.runtime

Structure of the generated classes may be illustrated by the following diagram (since implementation
classes parallel interfaces, they are omitted for better readability):

[TODO: UML]

You should not have any problem matching the generated classes and the constructs of the purchase or-
der schema. There is one pair of interface and implementing class per complex type (including the an-
onymous complex type for the item element of the items type) and per global element. Properties of
the generated classes are named after the corresponding elements and attributes of the schema. Note that
Hyperjaxb appends one additional property Hjid which carries entity identifier.

Next, consider the Hibernate mappings generated by Hyperjaxb. There is one *.hbm.xml file gener-
ated per interface/class pair. Here's an example of the Hibernate mapping for the
org.jvnet.hyperjaxb2.tests.po.USAddress and
org.jvnet.hyperjaxb2.tests.po.impl.USAddressImpl pair:

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge
<hibernate-mapping auto-import="false" default-cascade="all-delete-orphan" default-
<class discriminator-value="[org.jvnet.hyperjaxb2.tests.po.USAddress]"
name="org.jvnet.hyperjaxb2.tests.po.USAddress"
table="address">
<id access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPropertyA
name="Hjid"

5
Introduction

type="org.hibernate.type.LongType">
<generator class="native"/>
</id>
<discriminator type="org.hibernate.type.StringType">
<column name="Hjtype"/>
</discriminator>
<property access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPro
name="State">
<column name="State"/>
<type name="org.hibernate.type.StringType"/>
</property>
<property access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPro
name="Zip">
<column name="Zip"/>
<type name="org.hibernate.type.BigDecimalType"/>
</property>
<property access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPro
name="Country">
<column name="Country"/>
<type name="org.hibernate.type.StringType"/>
</property>
<property access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPro
name="City">
<column name="City"/>
<type name="org.hibernate.type.StringType"/>
</property>
<property access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPro
name="Street">
<column name="Street"/>
<type name="org.hibernate.type.StringType"/>
</property>
<property access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPro
name="Name">
<column name="Name"/>
<type name="org.hibernate.type.StringType"/>
</property>
<subclass discriminator-value="org.jvnet.hyperjaxb2.tests.po.USAddress"
name="org.jvnet.hyperjaxb2.tests.po.impl.USAddressImpl"/>
</class>
</hibernate-mapping>

[TODO: database schema]

The last and the most interesting is the database schema generated out of the *.hbm.xml files with the
Hibernate schema export utility:

create table Comment (


Hjid bigint generated by default as identity (start with 1),
Hjtype varchar(255) not null,
Value varchar(255),
primary key (Hjid));
create table Items (
Hjid bigint generated by default as identity (start with 1),
Hjtype varchar(255) not null,
primary key (Hjid));
create table Items_ItemType (
Hjid bigint generated by default as identity (start with 1),
Hjtype varchar(255) not null,
Comment varchar(255),
USPrice numeric,
ProductName varchar(255),

6
Introduction

PartNum varchar(255),
ShipDate timestamp,
Quantity numeric,
Items_Item_Hjid bigint,
Items_Item_Hjindex integer,
primary key (Hjid));
create table PurchaseOrderType (
Hjid bigint generated by default as identity (start with 1),
Hjtype varchar(255) not null,
Items bigint,
OrderDate timestamp,
Comment varchar(255),
BillTo bigint,
ShipTo bigint,
primary key (Hjid));
create table USAddress (
Hjid bigint generated by default as identity (start with 1),
Hjtype varchar(255) not null,
State varchar(255),
Zip numeric,
Country varchar(255),
City varchar(255),
Street varchar(255),
Name varchar(255),
primary key (Hjid));
alter table Items_ItemType add constraint FKF680EECC6C841C0B foreign key (Items_Ite
alter table PurchaseOrderType add constraint FK1C959F87D456BE41 foreign key (Items)
alter table PurchaseOrderType add constraint FK1C959F876D216E99 foreign key (BillTo
alter table PurchaseOrderType add constraint FK1C959F878A146B8E foreign key (ShipTo

At this moment we already have a working relational persistence layer for our schema-derived classes.
We can unmarshall XML data, save content objects into the database, load them and marshall them back
to XML. You can download this sample project ("PO Initial") here
[https://hyperjaxb2.dev.java.net#downloads].

Nevertheless, our solution leaves some space for further tuning, namely:

• The Comment table is effectively superfluous. It is only needed by the top-level comment element.
If we assume that purchase orders may not consist of a single comment element, this table as well as
Hibernate mapping for the Component interface and the ComponentImpl class) become redund-
ant.

• There's also no need in a separate table for Items, since we can assume that items will only appear
within the purchase order.

The tuning above can be done with Hyperjaxb customzations. I'll also customize few more things, for
demonstration purposes:

• I will rename PurchaseOrderType table into po, Items_ItemType into item and USAd-
dress into address for the better database schema readability.

• The partNum attribute of the Item should be the treated as an identifier. That is, if two different
purchase orders defined in two different XML files have items with the same partNum, they will
refer to the same object stored in the database.

7
Introduction

To customize schema processing with Hyperjaxb, I'll declare the binding extension namespace and add
customization elements in appinfo annotations:

<?xml version="1.0" encoding="ISO-8859-1"?>


<xsd:schema ...
xmlns:hj="http://hyperjaxb2.jvnet.org/customizations"
jaxb:extensionBindingPrefixes="hj">
...
<xsd:element name="comment" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<hj:ignored/>
<hj:component/>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:complexType name="PurchaseOrderType">
<xsd:annotation>
<xsd:appinfo>
<hj:class>
<hj:table name="po"/>
</hj:class>
</xsd:appinfo>
</xsd:annotation>
...
</xsd:complexType>
<xsd:complexType name="USAddress">
<xsd:annotation>
<xsd:appinfo>
<hj:class>
<hj:table name="address"/>
</hj:class>
</xsd:appinfo>
</xsd:annotation>
...
</xsd:complexType>
<xsd:complexType name="Items">
<xsd:annotation>
<xsd:appinfo>
<hj:ignored/>
<hj:component/>
</xsd:appinfo>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:annotation>
<xsd:appinfo>
<hj:class>
<hj:table name="item"/>
</hj:class>
</xsd:appinfo>
</xsd:annotation>
...
<xsd:attribute name="partNum" type="po:SKU" use="required">
<xsd:annotation>
<xsd:appinfo>
<hj:id>
<hj:generator generatorClass="assigned"/>
</hj:id>
</xsd:appinfo>

8
Introduction

</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
...
</xsd:schema>

XJC compiles this schema into the following class structure:

[UML]

These classes are mapped onto three tables:

[ER]

Now, let's take a look, what happens in the database when we import the simple document:

<?xml version="1.0"?>
<purchaseOrder xmlns="http://hyperjaxb2.jvnet.org/tests/po"
orderDate="1999-10-20">
<shipTo country="US">
<name>Alice Smith</name>
<street>123 Maple Street</street>
<city>Mill Valley</city>
<state>CA</state>
<zip>90952</zip>
</shipTo>
<billTo country="US">
<name>Robert Smith</name>
<street>8 Oak Avenue</street>
<city>Old Town</city>
<state>PA</state>
<zip>95819</zip>
</billTo>
<comment>Hurry, my lawn is going wild!</comment>
<items>
<item partNum="872-AA">
<productName>Lawnmower</productName>
<quantity>1</quantity>
<USPrice>148.95</USPrice>
<comment>Confirm this is electric</comment>
</item>
<item partNum="926-AA">
<productName>Baby Monitor</productName>
<quantity>1</quantity>
<USPrice>39.98</USPrice>
<shipDate>1999-05-21</shipDate>
</item>
</items>
</purchaseOrder>

Hibernate will issue the following statements:

INSERT INTO ADDRESS VALUES


(1,'org.jvnet.hyperjaxb2.tests.po.USAddress','PA',95819,'US','Old Town','8 Oak Aven
INSERT INTO ADDRESS VALUES
(2,'org.jvnet.hyperjaxb2.tests.po.USAddress','CA',90952,'US','Mill Valley','123 Map

9
Introduction

INSERT INTO PO VALUES


(1,'org.jvnet.hyperjaxb2.tests.po.PurchaseOrder','1999-10-20 02:00:00.0','Hurry, my
INSERT INTO ITEM VALUES
('872-AA','org.jvnet.hyperjaxb2.tests.po.Items.ItemType','Confirm this is electric'
INSERT INTO ITEM VALUES
('926-AA','org.jvnet.hyperjaxb2.tests.po.Items.ItemType',NULL,39.98,'Baby Monitor',
DELETE FROM ITEM WHERE PARTNUM='872-AA'
INSERT INTO ITEM VALUES
('872-AA','org.jvnet.hyperjaxb2.tests.po.Items.ItemType','Confirm this is electric'
DELETE FROM ITEM WHERE PARTNUM='926-AA'
INSERT INTO ITEM VALUES
('926-AA','org.jvnet.hyperjaxb2.tests.po.Items.ItemType',NULL,39.98,'Baby Monitor',

10
Chapter 2. Basics
The goal of Hyperjaxb is to make schema-derived classes generated by XJC persistable with Hibernate.
To do this, Hyperjaxb needs to generate Hibernate mappings for JAXB objects. But before we go on
about how these mappings are generated, you first need to understand what should be mapped. An this
implies understanding, what exactly does JAXB produce out of your XML Schemas.

Well, it is obvious JAXB compiles the XML Schema into a set of Java classes, which are essentially
POJOs or beans. Mapping these classes with Hibernate would mean mapping the classes as well as ne-
cessary fields (or properties, in POJO terminology). Following sections take a closer look at Java classes
and fields that Hyperjaxb is busy with.

Classes and interfaces


When XJC compiles the schema, it produces a pair of interface and implementation class for each com-
plex schema construct. For instance, complex type PurchaseOrderType will be represented by the
pair of PurchaseOrderType interface and PurchaseOrderTypeImpl class. JAXB also respects
type derivation: if complex type B extends (or restricts) type A, this will be represented by the following
type hierarchy on Java side:

• Interface A

• Class AImpl implements interface A.

• Interface B extends interface A.

• Class BImpl extends class AImpl and implements interface B (and therefore interface A).

According to the structure above, Java entity can be either interface of implementing class correspond-
ing to the root or derived type. This results in four cases of mapped entities:

1. Root interface.

2. Implementation class for the root interface.

3. Derived interface.

4. Implementation class for the derived interface.

Fields
When mapping fields of schema-derived classes, Hyperjaxb considers their cardinality and type.

Depending on cardinality, fields can be single or collection fields. Collection fields are typically derived
from repeatable elements, but there may be other options (for instance, list type as content type), so don't
be scared if your attribute field is collection.

As for the content type, Hyperjaxb considers the following six categories:

• simple fields;

11
Basics

• enum fields;

• DOM fields;

• wildcard fields;

• complex fields;

• heterogeneous fields.

Cardinality and type are orthogonal, so there's actually twelve field types.

Single fields
Single fields are represented by single-valued object properties. In the schema, they are typically ele-
ments with maxOccurs set to 1 (or not set at all) and attributes (with the exception of list-typed attrib-
utes).

Collection fields
Collection fields are represented by a collection-valued object properties. JAXB generates
java.util.List-typed or array-typed properties, but Hyperjaxb only supports list-typed collections.
Collection fields are typically derived from repeatable XML Schema elements (those with maxOccurs
greater than one or set to unbounded) or list-typed attributes or elements. Here's an example of a com-
plex type with two collection fields:

<xs:complexType name="complexType">
<xs:sequence>
<xs:element name="element" type="xs:string" minOccurs="0" maxOccurs="unbounded"
</xs:sequence>
<xs:attribute name="attribute" type="listType" use="optional"/>
</xs:complexType>
<xs:simpleType name="listType">
<xs:list itemType="xs:string"/>
</xs:simpleType>

Simple fields
Simple field is a field which contains value of a any simple type (with the exception of typesafe enumer-
ations).

Enum fields
JAXB allows you to customize enumerated simple types so that they will be processed as type-safe
enums. Here's an example:

<xs:element name="typeSafeStringEnumeration" minOccurs="0">


<xs:simpleType>
<xs:annotation>
<xs:appinfo>
<jaxb:typesafeEnumClass name="TypeSafeStringEnumeration"/>
</xs:appinfo>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:enumeration value="a"/>
<xs:enumeration value="b"/>

12
Basics

<xs:enumeration value="c"/>
<xs:enumeration value="d"/>
</xs:restriction>
</xs:simpleType>
</xs:element>

Your code will operate instances TypeSafeStringEnumeration.A, TypeSafeStringEnu-


meration.B, TypeSafeStringEnumeration.C and TypeSafeStringEnumeration.D of
the TypeSafeStringEnumeration class.

DOM fields
In JAXB RI, you can annotate an element with xjc:dom and it will be managed as a DOM element.
This is very useful in case of heterogeneous/semistructural content. For instance, if your description of
some product in your schema may contain an XHTML fragment in the description, you probably won't
want to make JAXB parse all these ps, brs, divs and so on. In this case, you simply mark description
element as DOM and enjoy our XHTML as a DOM object tree:

<xsd:complexType name="RootType">
<xsd:sequence>
<xsd:element name="description">
<xsd:annotation>
<xsd:appinfo>
<xjc:dom/>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>

Complex fields
Complex fields represent schema elements with complex types.

Wildcard fields
XML Schema also defines "wildcard" xs:any construct. Wildcard fields have no strict content model.
In the Java code they are typically represented by java.lang.Object -valued properties.

Heterogeneous fields
In certain cases, fields may contain values of more than one type. This type of fields is called "heterogen-
eous". A typical scenario where henerogeneous fields apper is repeatable xs:choice or xs:sequence:

<xs:sequence maxOccurs="unbounded">
<xs:element name="a" type="aType"/>
<xs:element name="b" type="bType"/>
</xs:sequence>

In the example above, your class will have a collection property AAndB which could contain values of
AType or BType classes (assuming aType and bType are complex).

Field accessors

13
Basics

Field accessors in JAXB/Hibernate/RDBMS junction are a bit more complex than simple setters/getters
combinations in JavaBeans.

First complication is "null" semantics of fields. For the primitive field, judging only by its value, it is
not possible to say, if the field is empty or not. The dangerous effect of this is that primitive fields are
"initialized" with the default value of a primitive type. For instance, when having a boolean field with
value set to false, it is not clear if the field is empty or it was explicitly assigned this value.

JAXB addresses this issue by giving the possibility to generate "isSetMyField" and "unsetMy-
Field" methods (via generateIsSetMethod flag in global binding declaration). Hyperjaxb takes
advantage of this feature and defines its own Hibernate property accessor which checks if field is empty
or not before returning the actual value.

Another problem is that, JAXB does not generate setters for collection fields. Hibernate, in its turn re-
quires a method to set the value of collection field read from the database.

This issue is also resolved through a property accessor. Hyperjaxb's list property accessor simulates set-
ter through reflection. It also uses isSet and unset methods.

14
Chapter 3. Generating Hibernate
mappings
Previous chapter described basic constructs which we need to map. This chapter goes on and describes
how these constructs are mapped by Hyperjaxb, i.e. what do the generated mappings look like and how
these mappings can be customized.

The overall process


Hyperjaxb is implemented as an XJC add-on. Hyperjaxb implements specific interface (and follows
some further deployment procedures) which allows it to be picked up by XJC in the runtime. The add-on
is invoked by XJC after XML Schema is processed into class and field items but before the actual code
is written to the disk. This allows Hyperjaxb to analyze classes and fields generated by XJC and add
some new methods or resources to the code generated by XJC.

Now you should understand what Hyperjaxb actually does:

1. Analyze the structure of class and field items created by XJC out of the XML Schema. Detect types
of fields and classes, their types and hierarchy. Consider customizations.

2. Append additional required methods or fields (for instance for identifier properties) to the code
model.

3. Generate Hibernate mappings and add them as resources to the code model.

4. Add Hibernate configuration (hibernate.cfg.xml) as resource to the code model.

Hibernate configuration and Hibernate mapping files are XML files conforming to DTDs defined in Hi-
bernate. To ease the construction of XML these XML files, Hyperjaxb contains hibernate-
configuration and hibernate-mapping modules. These modules are Hibernate configuration
and mapping DTDs compiled with JAXB. So instead of manipulating pure XML, Hyperjaxb works with
neat and nice object structures which are afterwards simply marshalled by JAXB into *.hbm.xml and
*.cfg.xml resources.

Customizations
Hyperjaxb gives you high level of control over the generated mappings through the customization mech-
anism. You can customize mappings generated for classes and fields by annotating the corresponding
XML Schema constructs - either directly in the schema or in external binding declaration.

Please note that customizations are purely optional. You only need them if you want to fine-tune the
generated mappings - for instance customize table or column names, association cardinality and so on.
Moreover, if you omit optional customization attributes or elements, Hyperjaxb will pick up default val-
ues for you - thus making the customization really easy.

Being XML by themselves, Hyperjaxb customizations are specified by the XML Schema. Please see
hibernate-customizations/src/main/resources/customizations.xsd
[https://hyperjaxb2.dev.java.net/source/browse/hyperjaxb2/schemas/hibe
rnate-customiza-
tions/src/main/resources/customizations.xsd?view=markup] for reference.

To use Hyperjaxb customizations (directly in schema or in the external binding file), you'll first need to

15
Generating Hibernate mappings

declare the http://hyperjaxb2.jvnet.org/customizations as JAXB extension binding


namespace. This is done by declaring the namespace with a prefix and specifying the declared prefix in
jaxb:extensionBindingPrefixes attribute. Below are examples of declarations in schema and
external binding files.

<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:hj="http://hyperjaxb2.jvnet.org/customizations"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:extensionBindingPrefixes="hj"
jaxb:version="1.0">
<!-- ... -->
</xs:schema>

<jaxb:bindings version="1.0"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:hj="http://hyperjaxb2.jvnet.org/customizations"
jaxb:extensionBindingPrefixes="hj">
<!-- ... -->
</jaxb:bindings>

To customize field or class in the schema itself, you have to include xs:annotation/xs:appinfo
into the corresponding construct:

<xs:complexType name="myType">
<xs:annotation>
<xs:appinfo>
<hj:class>
<hj:table name="my_custom_table_name"/>
</hj:class>
</xs:appinfo>
</xs:annotation>
<xs:sequence>
<xs:element name="id" type="xs:long" minOccurs="0">
<xs:annotation>
<xs:appinfo>
<hj:id/>
</xs:appinfo>
</xs:annotation>
</xs:element>
<!-- ... -->
</xs:sequence>
</xs:complexType>

In the external binding file, simply include the customization into jaxb:bindings element bound to the
desired schema construct:

<jaxb:bindings version="1.0"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:hj="http://hyperjaxb2.jvnet.org/customizations"
jaxb:extensionBindingPrefixes="hj">
<jaxb:bindings schemaLocation="schema.xsd" node="/xs:schema">
<jaxb:bindings node="xs:complexType[@name='myType']">
<hj:class>
<hj:table name="my_custom_table_name"/>
</hj:class>

16
Generating Hibernate mappings

</jaxb:bindings>
<jaxb:bindings node="xs:complexType[@name='myType']/xs:sequence/xs:element[@nam
<hj:id/>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>

Providing customizations in an external file is a bit less convenient than annotating the schema, but is
useful in those cases where you can't actually edit the schema.

Common customization elements and types


There are several common elements and types of the customization schema which are used by other cus-
tomizations. To avoid duplication, these constructs are described below

table
In case you XML Schema construct maps onto a table, you can customize table name, schema or catalog
with a table customization element. Attributes of this customization element correspond to table,
schema and catalog attributes of Hibernate mapping elements (like class, join, joined-
subclass, list etc.). The name attribute is required.

<table
name="table_name"
schema="owner"
catalog="catalog"/>

column
You can also customize properties of the target columns with column element. This customization ele-
ment corresponds to Hibernate's column element.

<column
name="column_name"
length="L"
precision="P"
scale="S"
not-null="true|false"
unique="true|false"
unique-key="unique_key_id"
sql-type="sql_type"
check="SQL Expression">
<comment>Comment</comment>
</column>

type
You can specify the type of identifier, version or simple single properties as well as types of simple col-
lection elements with the type customization element:

<type
name="type_name"/>

17
Generating Hibernate mappings

key
Class and collections mapping customization use the key element. It is used to customize the foreign
key in the joined table, that references the primary key of the original table.

<key
property-ref="propertyName"
foreign-key="foreign_key"
on-delete="cascade|noaction"
not-null="true|false"
update="true|false"
unique="true|false">
<column ... />
</key>

This element corresponds to the Hibernate key element (except that column properties are defined in
nested column elements).

cache
You may also customize caching of classes and collections.

<cache
usage="read-only|read-write|nonstrict-read-write|transactional"
region="region"/>

This element corresponds to Hibernate cache element. The usage attribute is required.

Ignoring classes and fields


If you do not want some of the classes or fields to be persisted (read: you don't want mapping to be gen-
erated for them), you can mark them as ignored using the ignored element.

<xs:element name="ignoredRoot" type="rootType">


<xs:annotation>
<xs:appinfo>
<hj:ignored/>
</xs:appinfo>
</xs:annotation>
</xs:element>
<xs:complexType name="rootType">
<xs:sequence>
<xs:element name="sequence" type="sequenceType" minOccurs="0"/>
<xs:element name="simpleTypes" type="simpleTypesType" minOccurs="0"/>
<xs:element name="elementWithListAttribute1" type="elementWithListAttribute1" m
<xs:element name="facet" type="facetType" minOccurs="0"/>
<xs:element name="ignored" type="xs:string">
<xs:annotation>
<xs:appinfo>
<hj:ignored/>
</xs:appinfo>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>

Hyperjaxb will generate no mappings for the ignoredRoot element class as well as the ignored
element field property.

18
Generating Hibernate mappings

Class mapping
For each of the class items, JAXB generates a pair of interface and implementation class. That is, your
myComplexType complex type will be represented by an interface
org.jvnet.hyperjaxb2.tests.foo.MyComplexType and implementation class
org.jvnet.hyperjaxb2.tests.foo.impl.MyComplexTypeImpl. Hyperjaxb generates a
single mapping file for each interface/implementation class pair. Typical structure of the mapping file is
as follows:

<!DOCTYPE
hibernate-mapping
PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping
auto-import="false"
default-cascade="all-delete-orphan"
default-lazy="false">
<!-- Interface mapping -->
<class
discriminator-value="[org.jvnet.hyperjaxb2.tests.foo.MyComplexType]"
name="org.jvnet.hyperjaxb2.tests.foo.MyComplexType"
table="MyComplexType">
<!-- ... -->
<!-- Implementation class mapping -->
<subclass
discriminator-value="org.jvnet.hyperjaxb2.tests.foo.MyComplexType"
name="org.jvnet.hyperjaxb2.tests.foo.impl.MyComplexTypeImpl"/>
</class>
</hibernate-mapping>

Root element of the mapping file is hibernate-mapping, which defines generic mapping proper-
ties. By default, Hyperjaxb disables auto import, sets all-delete-orphan as default cascade meth-
od and default lazy to false.

The root hibernate-mapping element contains a single interface mapping element. Depending on
the schema and inhertitance mapping strategy, this could be class for base types or subclass
(joined-subclass etc.) for derived types.

By default, Hyperjaxb generates a very simple interface mapping (which only defines name of the inter
and database table):

<class
discriminator-value="[org.jvnet.hyperjaxb2.tests.foo.MyComplexType]"
name="org.jvnet.hyperjaxb2.tests.foo.MyComplexType"
table="MyComplexType">
<!-- ... -->
</class>

Default inhertitance mapping strategy of Hyperjaxb is mixed table-per-class-hierarchy and table-


per-subclass strategy (will be covered in detail in the Inheritance mapping section). In this strategy, ex-
tensions are mapped using a subclass element:

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE hibernate-mapping

19
Generating Hibernate mappings

PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"


"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping auto-import="false" default-cascade="all-delete-orphan" default-
<subclass discriminator-value="[de.baw.nokis.RecordElement]"
extends="de.baw.nokis.Record"
name="de.baw.nokis.RecordElement">
<subclass discriminator-value="de.baw.nokis.RecordElement"
name="de.baw.nokis.impl.RecordElementImpl"/>
</subclass>
</hibernate-mapping>

Interface mapping element contains mapping of the implementation class. In Hibernate, classes are con-
sidered to "extend" their interfaces therefore implementation class is mapped as a subclass according to
the chosen inheritance mapping strategy. Default strategy of Hyperjaxb will produce a subclass ele-
ment:

<subclass discriminator-value="de.baw.nokis.RecordElement"
name="de.baw.nokis.impl.RecordElementImpl"/>

The subclass mapping of the implementation class is generated without any content (since implementa-
tion class does not add any significant properties as compared to the interface).

To allow Hibernate distinguish between several classes mapped onto the same table, Hyperjaxb gener-
ates discriminator element in the interface mapping. By default, value of the discriminator is the name of
the interface itself. However, this can be easily customized.

<class
name="org.jvnet.hyperjaxb2.test.one.RootType"
table="RootType">
<id ... />
<discriminator
type="org.hibernate.type.StringType">
<!-- ... -->
<version ... />
<!-- ... -->
</class>

Customizing class mapping


You can customize class mapping by including the class element into the annotation.

<class
proxy="ProxyInterface"
lazy="true|false"
discriminator-value="discriminator_value">
polymorphism="implicit|explicit"
where="arbitrary sql where condition"
persister="PersisterClass"
dynamic-update="true|false"
dynamic-insert="true|false"
batch-size="N"
select-before-update="true|false"
optimistic-lock="none|version|dirty|all"
check="arbitrary sql check condition"
rowid="rowid" />
<table ... />
<cache ... />

20
Generating Hibernate mappings

<discriminator
type="discriminator_type"
force="true|false"
insert="true|false"
formula="formula">
<no-column/>
<column ... />
</discriminator>
<key ... />
<id ... /> <!-- TODO -->
<version ... /> <!-- TODO -->
</class>

For the documentation of attribuite values, please consult Hibernate documentation on class and
discriminator elements.

The example below demonstrates class customization:

<xs:complexType name="myClassType">
<xs:annotation>
<xs:appinfo>
<hj:class discriminator-value="mc">
<hj:table name="my_class_table"/>
<hj:cache usage="read-write" region="myRegion"/>
</hj:class>
</xs:appinfo>
</xs:annotation>
<xs:sequence>
<!-- ... -->
</xs:sequence>
</xs:complexType>

In some cases (for instance, legacy DB schema that you need to map onto), you may need to avoid gen-
erating an additional discriminator column. This can be done with the formula attribute and
<no-column/> sub-element. The formula attribute specifies a SQL experession returning the dis-
criminator value and <no-column/> instructs Hyperjaxb that it must not generate and additional dis-
criminator column. For example, consider the following schema:

<xsd:element name="Institution" type="lbk:Institution"/>


<xsd:complexType name="Institution">
<xsd:annotation>
<xsd:appinfo>
<hj:class>
<hj:discriminator formula="'de.disy.preludio2.lbk.InstitutionElement'">
<hj:no-column/>
</hj:discriminator>
</hj:class>
</xsd:appinfo>
</xsd:annotation>
...
</xsd:complexType>

For the schema above, we'll get two interfaces (InstitutionElement extends Institution)
and two implementation classes (InstitutionElementImpl extends Institution). Theoretic-
ally, Hibernate need to distinguish between InstitutionElement and InstitutionImpl, but
in this case we have explicitly specified that we only have InstitutionElements and therefore dis-
criminator column can be avoided. In this example, discriminator formula is very straightforward - it
simply returns a specific value. In more complex cases a more complex expression may be required. For
instance, one could check certain columns to be not null, analyze identifiers and so on.

21
Generating Hibernate mappings

Marking class as component


You may also mark class as a component. In this case all other classes that reference the given class
as a complex single property, will declare component mapping instead of one-to-one or many-
to-one mappings. Here's the customization:

<component
access="..."
unique="..."
update="..."
insert="..."
lazy="..."
optimistic-lock="..."/>

Consider the following example:

<xs:complexType name="bType">
<xs:annotation>
<xs:appinfo>
<hj:ignored/>
<hj:component/>
</xs:appinfo>
</xs:annotation>
<xs:sequence>
<xs:element name="d" type="xs:string" minOccurs="0"/>
<xs:element name="e" type="xs:int" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>

This will produce the following mapping:

<class discriminator-value="[org.jvnet.hyperjaxb2.tests.component.AType]"
name="org.jvnet.hyperjaxb2.tests.component.AType"
table="AType">
<!-- ... -->
<component class="org.jvnet.hyperjaxb2.tests.component.impl.BTypeImpl" name="B">
<property access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPrope
name="D">
<column name="B_D"/>
<type name="org.hibernate.type.StringType"/>
</property>
<list access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.ListAccessor" nam
table="B_E">
<key>
<column name="B_E_Hjid"/>
</key>
<list-index>
<column name="B_E_Hjindex"/>
</list-index>
<element type="org.hibernate.type.IntegerType">
<column name="Hjvalue"/>
</element>
</list>
</component>
<!-- ... -->
<subclass discriminator-value="org.jvnet.hyperjaxb2.tests.component.AType"
name="org.jvnet.hyperjaxb2.tests.component.impl.ATypeImpl"/>
</class>

22
Generating Hibernate mappings

Note that Hyperjaxb applied the corresponding naming: names of the component fields are prefixed with
the field name of the aggregating class to avoid confusions.

Identifier and version properties


Hibernate requires mapped classes to have an identifier property. Since schema-derived classes usually
do not posess identifier properties, Hyperjaxb generates them by default. By default, Hyperjaxb gener-
ates java.lang.Long-typed Hjid property and maps it using the native generator class.

Apart from the identifier property, Hibernate class mapping may also have version properties. Hibernate
uses versions for optimistic locking detection, in replication and so on. Versions are optional in Hibern-
ate, but Hyperjaxb generates them (as well as mappings) by default. Default version property is called
Hjversion and has the java.lang.Long type.

<class
name="org.jvnet.hyperjaxb2.test.one.RootType"
table="RootType">
<!-- ... -->
<id
name="Hjid"
type="org.hibernate.type.LongType">
<generator class="native"/>
</id>
<!-- ... -->
<version
name="Hjversion"
type="org.hibernate.type.LongType"/>
<!-- ... -->
</class>

Customizing id and version fields


By default, Hyperjaxb generates two new fields (Hjid and Hjversion) to hold the identifier and ver-
sion values. You may customize these fields by including id and version elements into the class cus-
tomization (this is still a TODO). Alternatively, instead of generating new fields, you can mark existing
elements or attributes with id and version elements and Hyperjaxb will use the marked fields as
identifier and version properties. This is especially useful in distributed scenarios, when you want to re-
tain identifier values when replicating data between systems.

id
Identifier properties are marked and customized with the id element:

<id
access="field|property|className"
unsaved-value="null|any|undefined|id_value">
<column ... />
<generator
generatorClass="generatorClass">
<param
name="paramName"
value="paramValue"/>
</generator>
<type ... />
</id>

This element corresponds to the id element of Hibernate mapping. Here is a small example:

23
Generating Hibernate mappings

<xsd:complexType name="record">
<xsd:sequence>
<xsd:element name="mdRecordInfo" type="nokis:MetaData">
<xsd:annotation>
<xsd:appinfo>
<hj:complexSingleProperty>
<hj:one-to-one/>
</hj:complexSingleProperty>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<hj:id>
<hj:generator generatorClass="foreign">
<hj:param name="property" value="MdRecordInfo"/>
</hj:generator>
</hj:id>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="MetaData">
<xsd:sequence>
<xsd:element name="mdFileID" type="nokis:documentID">
<xsd:annotation>
<xsd:appinfo>
<hj:id>
<hj:generator generatorClass="uuid"/>
</hj:id>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>

In this example, child entity (MetaData) has a simple single element mdFileID, which will be used
as its identifier. New value of this property will be generated with an UUID algorithm. Parent entity
(record) has one-to-one mapping with this child enitity and will share the same identifier (through the
foreign generator).

version
You may mark an existing field as version property with the version customization element:

<version
access="field|property|className"
unsaved-value="null|negative|undefined">
<column ... />
<type ... />
</version>

Note that in Hibernate the unsaved-value of the version property has the priority over the identi-
fier's unsaved-value.

Here is the example of version customization:

<xsd:complexType name="record">
<xsd:attribute name="version" type="xsd:long" default="0">

24
Generating Hibernate mappings

<xsd:annotation>
<xsd:appinfo>
<hj:version/>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>

Inheritance mapping
In Hibernate, both implementation of the interface and extension of the class are considered inheritance
and treated similarly. Hibernate supports several strategies for inheritance mapping:

• table-per-class-hierarchy, where all classes of the hierarchy are mapped onto one table;

• table-per-subclass, where each subclass is mapped onto its own table and subclass tables reference
parent tables rather than copy inherited property columns;

• table-per-concrete-class, where each class is mapped onto its own table and each table defines
columns for all the properties of the class, including inherited properties.

The first strategy may result is very large tables (i.e. tables that have large number of columns), which is
often undesirable.

Two last strategies generate too many tables. For instance, if your schema has a complex top-level ele-
ment, there'll be four tables generated for this element: element interface table, element implementation
class table, complex type interface table and complex type implementation class table. Three of four
tables will not define any columns but only reference their parent table.

Hyperjaxb uses mixed table-per-class/table-per-subclass strategy (also described in the Hibernate refer-
ence) which is much more suitable for JAXB-generated structures. In this strategy, subclass is mapped
onto the table of its parent class. If subclass has some additional properties, they will be mapped onto a
joined table:

<xs:complexType name="sequenceType">
<xs:sequence>
<xs:element name="a" type="xs:string"/>
<xs:element name="b" type="xs:long"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="extendedSequenceType">
<xs:complexContent>
<xs:extension base="sequenceType">
<xs:sequence>
<xs:element name="c" type="xs:dateTime"/>
<xs:element name="d" type="xs:base64Binary"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>

Generated mappings:

<class
discriminator-value="[org.jvnet.hyperjaxb2.test.one.SequenceType]"
name="org.jvnet.hyperjaxb2.test.one.SequenceType"

25
Generating Hibernate mappings

table="SequenceType">
<id name="Hjid" type="org.hibernate.type.LongType">
<generator class="native"/>
</id>
<discriminator type="org.hibernate.type.StringType">
<column name="Hjtype"/>
</discriminator>
<property name="A">
<column name="A"/>
<type name="org.hibernate.type.StringType"/>
</property>
<property name="B">
<column name="B"/>
<type name="org.hibernate.type.LongType"/>
</property>
<subclass
discriminator-value="org.jvnet.hyperjaxb2.test.one.SequenceType"
name="org.jvnet.hyperjaxb2.test.one.impl.SequenceTypeImpl"/>
</class>
<subclass
discriminator-value="[org.jvnet.hyperjaxb2.test.one.ExtendedSequenceType]"
extends="org.jvnet.hyperjaxb2.test.one.SequenceType"
name="org.jvnet.hyperjaxb2.test.one.ExtendedSequenceType">
<join table="ExtendedSequenceType">
<key>
<column name="Hjid"/>
</key>
<property name="D">
<column name="D"/>
<type name="org.hibernate.type.BinaryType"/>
</property>
<property name="C">
<column name="C"/>
<type name="org.jvnet.hyperjaxb2.runtime.hibernate.type.CalendarType"/>
</property>
</join>
<subclass
discriminator-value="org.jvnet.hyperjaxb2.test.one.ExtendedSequenceType"
name="org.jvnet.hyperjaxb2.test.one.impl.ExtendedSequenceTypeImpl"/>
</subclass>

In this example, properties A and B of SequenceType and ExtendedSequenceType (as well as


their implementation classes) will be stored in the SequenceType table. Additional properties C and D
of ExtendedSequenceType will be stored in the ExtendedSequenceType table which refer-
ences the SequenceType table. Here's how the database schema will look like:

create table SequenceType (


Hjid bigint generated by default as identity (start with 1),
Hjtype varchar(255) not null,
A varchar(255),
B bigint,
primary key (Hjid)
);
create table ExtendedSequenceType (
Hjid bigint not null,
D varbinary(255),
C timestamp,
primary key (Hjid)
);

26
Generating Hibernate mappings

alter table ExtendedSequenceType


add constraint FK439D9A94383B3433
foreign key (Hjid)
references SequenceType;

This strategy generates fewer tables than table-per-subclass strategy (table is generated only if subclass
has additional properties) and smaller (in number of columns) tables than table-per-class-hierarchy ap-
proach.

Please note that this mixed strategy still requires a discriminator column to distinguish actual types of
persistent instances. By default, Hyperjaxb generates a string Hjtype column in the root table of the
hierarchy. Default value of the discriminator is the fully qualified name of the interface.

Single fields
Simple, enum and DOM single fields
Single, enum and DOM single fields are mapped using the property element:

<property
access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPropertyAccessor"
name="PropertyName">
<column
name="ColumnName">
<type
name="TypeClass"/>
</property>

Hyperjaxb automatically choses the column name (as defined in by in the naming strategy) and picks up
the appropriate Hibernate type based on the XML Schema type of the attribute or element.

Hyperjaxb uses a custom property accessor to take advantage of


isSetMyProperty/unsetMyProperty methods generated by Hyperjaxb. This allows for distin-
guishing null semantics for primitive types.

For the typesafe enum fields, Hyperjaxb generates a custom Hibernate type.

There is also a pre-defined


org.jvnet.hyperjaxb2.runtime.hibernate.type.ElementType custom Hibernate
type which is used to map DOM content. When saving into the database, this type serializes DOM trees
into string; upon loading, DOM is parsed back.

Consider the schema fragment below:

<xs:complexType name="simpleTypesType">
<xs:sequence>
<xs:element name="string" type="xs:string" minOccurs="0"/>
<xs:element name="typeSafeStringEnumeration" minOccurs="0">
<xs:simpleType>
<xs:annotation>
<xs:appinfo>
<jaxb:typesafeEnumClass name="TypeSafeStringEnumeration"/>
</xs:appinfo>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:enumeration value="a"/>

27
Generating Hibernate mappings

<xs:enumeration value="b"/>
<xs:enumeration value="c"/>
<xs:enumeration value="d"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xsd:element name="content">
<xsd:annotation>
<xsd:appinfo>
<xjc:dom/>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
</xs:sequence>
</xs:complexType>

Hyperjaxb will generate the following mapping:

<class
...
name="org.jvnet.hyperjaxb2.test.one.SimpleTypesType"
table="SimpleTypesType">
<!-- ... -->
<property
name="String"
access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPropertyAccesso
<column name="String"/>
<type name="org.hibernate.type.StringType"/>
</property>
<property name="TypeSafeStringEnumeration"
access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPropertyAccesso
<column name="TypeSafeStringEnumeration"/>
<type name="org.jvnet.hyperjaxb2.test.one.TypeSafeStringEnumeration$Type"/>
</property>
<property name="Content"
access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPropertyAccesso
<column name="Content"/>
<type name="org.jvnet.hyperjaxb2.runtime.hibernate.type.ElementType"/>
</property>
<!-- ... -->
</class>

Customizations
Simple, enum and DOM single fields are customized with the simpleSingleProperty element:

<simpleSingleProperty
access="field|property|ClassName"
update="true|false"
insert="true|false"
optimistic-lock="true|false"
lazy="true|false">
<column ... />
<type ... />
</simpleSingleProperty>

Atributes of this customization element override default values generated by Hyperjaxb. For the detailed
semantics, please consult the Hibernate documentation.

Here's an example of simple single property customization (we've customized the name of the database
column and its length):

28
Generating Hibernate mappings

<xs:element name="myProperty" type="xs:string" minOccurs="0">


<xs:annotation>
<xs:appinfo>
<hj:simpleSingleProperty>
<hj:column name="my_property" length="32"/>
</hj:simpleSingleProperty>
</xs:appinfo>
</xs:annotation>
</xs:element>

Complex single fields


By default, Hyperjaxb generates many-to-one mapping for complex singe fields. There are two more
options, namely one-to-one and component mappings, which can be chosen by the customization.

<many-to-one
name="PropertyName"
class="ChildClassName" >
<column name="ColumnName"/>
</many-to-one>

<one-to-one
name="PropertyName"
class="ChildClassName"/>

<component
name="PropertyName"
class="ChildClassName">
<!-- Component properties -->
</component>

Customizations
You can customize complex single field with the complexSingleProperty element. This custom-
ization element simply offers the choice of one-to-one, many-to-one and component subele-
ments:

<complexSingleProperty>
<one-to-one ... />
<many-to-one ... />
<component ... />
</complexSingleProperty>

one-to-one
Use one-to-one element to select and customize one-to-one mapping for your complex single prop-
erty:

<one-to-one
access="field|property|ClassName"
cascade="..."
outer-join="..."
fetch="..."
constrained="true|false"
foreign-key="..."
property-ref="..."

29
Generating Hibernate mappings

lazy="true|false|proxy"/>

Please note that this type of mapping requires parent and child entities to have identical identifiers. You
may use foreign identifier generator class to achieve this.

many-to-one
Use many-to-one element to select or customize many-to-one mapping for you property.

<many-to-one
access="..."
update="true|false"
insert="true|false"
optimistic-lock="true|false"
cascade="..."
outer-join="..."
fetch="..."
foreign-key="..."
property-ref="..."
not-found="..."
lazy="...">
<column ... />
</many-to-one>

component
You may also use the component customization element to map child entity as a component in the
customized property. In the contrast to component customization of the class, this customization will
be limited to the customized property only.

Wildcard single fields


Hyperjaxb represents wildcard single fields with Hibernate's any mapping. By default, wildcard field
will be mapped onto two columns, holding id of the child antity and its class name.

<xsd:complexType name="RootType">
<xsd:sequence>
<xsd:any processContents="strict"/>
</xsd:sequence>
</xsd:complexType>

<any
id-type="org.hibernate.type.LongType"
meta-type="org.hibernate.type.StringType"
name="PropertyName">
<column name="PropertyName_Hjclass"/>
<column name="PropertyName_Hjid"/>
</any>

Customizations
Use wildcardSingleProperty customization to configure wildcard single field mapping:

<wildcardSingleProperty
access="..."
update="true|false"
insert="true|false"

30
Generating Hibernate mappings

optimistic-lock="true|false"
meta-type="..."
cascade="..."
lazy="true|false">
<classColumn ... />
<idColumn ... />
</wildcardSingleProperty>

The elements classColumn and idColumn have the same format as the column element described
previously. These elements customize class column and identifier column respectively. For instance,
you could rename them:

<xs:any processContents="strict">
<xs:annotation>
<xs:appinfo>
<hj:wildcardSingleProperty>
<hj:classColumn name="anyclass"/>
<hj:idColumn name="anyid"/>
</hj:wildcardSingleProperty>
</xs:appinfo>
</xs:annotation>
</xs:any>

Heterogeneous single fields


At the moment, Hyperjaxb treats heterogeneous single fields as wildcard fields. That is, any mapping is
generated. This is far not optimal mapping (single possible types of the heterogeneous fields are known
in the compile-time) and will be changed in future.

Collection fields
Generic collection mapping
All collections map onto Hibernate list, bag or idbag structures. All mappings contain key sub-
element and content mapping (element, composite-element, one-to-many, many-
to-many or many-to-any depending on the field type and customization). The list element also
contains the list-index subelement, idbag has an additional collection-id element.

Default collection mapping is list:

<list
access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.ListAccessor"
name="PropertyName"
table="ClassName_PropertyName">
<key>
<column name="ClassName_PropertyName_Hjid"/>
</key>
<list-index>
<column name="ClassName_PropertyName_Hjindex"/>
</list-index>
<!-- Content -->
</list>

If you specify (using the customization) that collection mapping should not include the list index, but
don't provide the collection-id customization, Hyperjaxb will generate bag mapping:

31
Generating Hibernate mappings

<bag
access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.ListAccessor"
name="PropertyName"
table="ClassName_PropertyName">
<key>
<column name="ClassName_PropertyName_Hjid"/>
</key>
<!-- Content -->
</bag>

The bag mapping requires no additional list index column, but poor performance since Hibernate has to
recreate the whole collection on every change. If you don't want the index column, use <no-index/>
customization together with the <collection-id/>. This will result in idbag mapping:

<idbag
access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.ListAccessor"
name="PropertyName"
table="ClassName_PropertyName">
<collection-id column="ClassName_PropertyName_Hjindex" type="Hibernate type">
<generator .../>
</collection-id>
<key>
<column name="ClassName_PropertyName_Hjid"/>
</key>
<!-- Content -->
</bag>

Hyperjaxb auto-generates collection table name as well as key, index and collection identifier column
names using class name and property name. If generated names are too long, provide your own names
through the customization.

Generic collection mapping customizations


Customizations for collection mappings also share the same base structure:

<...CollectionProperty
access="..."
lazy="true|false"
inverse="true|false"
cascade="..."
where="..."
batch-size="..."
outer-join="..."
fetch="..."
persister="..."
check="..."
optimistic-lock="true|false">
<table ... />
<cache ... />
<key ... />
<list-index
base="...">
<column ... />
</list-index>
<no-index/>
<collection-id>
<column ... />
<generator ... />
<type ... />
</list-index>

32
Generating Hibernate mappings

<!-- Type-specific customizations -->


</...CollectionProperty>

Simple, enum and DOM collection fields


Simple, enum and DOM collections are mapped using the element subelement of the list mapping.
Here is an example of simple collection with elements of the string type:

<list ...
name="MyList" table="MyClass_MyList">
<key>
<column name="MyClass_MyList_Hjid"/>
</key>
<list-index>
<column name="MyClass_MyList_Hjindex"/>
</list-index>
<element type="org.hibernate.type.StringType">
<column name="Hjvalue"/>
</element>
</list>

By default, Hyperjaxb uses Hjvalue as element column name. DDL for the mapping above will be
something like:

create table MyClass_MyList (


MyClass_MyList_Hjid bigint not null,
Hjvalue varchar(255),
MyClass_MyList_Hjindex integer not null,
primary key (MyClass_MyList_Hjid, MyClass_MyList_Hjindex)
);

Enum and DOM collection fields mapping is almost identical. The only difference is that Hyperjaxb
uses the generated Hibernate type-safe enum user class and
org.jvnet.hyperjaxb2.runtime.hibernate.type.ElementType for enum and DOM
fields respectively.

Customizations
Use simpleCollectionProperty element to customize simple, enum and DOM collection fields.
This customization element extends base customization with the element subelement which config-
ures the element subelement of Hibernate mapping:

<simpleCollectionProperty ...>
<!-- table, cache, key, list-index, no-index, collection-id -->
<element>
<type ... />
<column ... />
</element>
</simpleCollectionProperty>

Complex collection fields


Complex collection are mapped with either one-to-many or many-to-many subelements of list
mapping. The one-to-many mapping is the default option; many-to-many may be selected
through the customization.

33
Generating Hibernate mappings

<list ...>
<key ... />
<list-index ... />
<one-to-many
class="ChildClass"/>
</list>

<list ...>
<key ... />
<list-index ... />
<many-to-many
class="ChildClass">
<column name="ClassName_PropertyName_Hjid"/>
</many-to-many>
</list>

In case of the one-to-many mapping, the child class table will be augmented with parent id and list index
columns:

<list ...
name="MyList">
<key>
<column name="MyClass_MyList_Hjid"/>
</key>
<list-index>
<column name="MyClass_MyList_Hjindex"/>
</list-index>
<one-to-many class="MyChildClass"/>
</list>

DDL:

create table MyChildClass (


Hjid bigint generated by default as identity (start with 1),
Hjtype varchar(255) not null,
Hjversion bigint not null,
-- Other column properties
MyClass_MyList_Hjid bigint,
MyClass_MyList_Hjindex integer,
primary key (Hjid)
);
alter table MyChildClass
add constraint FK7A84E5A1D308C2EA
foreign key (MyClass_MyList_Hjid)
references MyClass;

In case of the many-to-many mapping, no columns are added to parent or child class tables. In this
case, the association is managed in a third table:

<list ...
name="MyList" table="MyClass_MyList">
<key>
<column name="MyClass_MyList_Hjid"/>
</key>
<list-index>
<column name="MyClass_MyList_Hjindex"/>
</list-index>
<many-to-many class="MyChildClass"/>

34
Generating Hibernate mappings

</list>

DDL:

create table MyClass_MyList (


MyClass_MyList_Hjid bigint,
MyClass_MyList_Hjchildid bigint,
MyClass_MyList_Hjindex integer,
primary key (MyClass_MyList_Hjid, MyClass_MyList_Hjindex)
);
alter table MyClass_MyList
add constraint FKB72EC39CFF0186B1
foreign key (MyClass_MyList_Hjchildid)
references MyChildClass;
alter table MyClass_MyList
add constraint FKB72EC39CE0B300BF
foreign key (MyClass_MyList_Hjid)
references MyClass;

Customizations
Complex collection fields are customized with the complexCollectionProperty element which contains
either one-to-many or many-to-many subelements:

<complexCollectionProperty>
<!-- table, cache, key, list-index, no-index -->
<one-to-many
not-found="..."/>
<many-to-many
not-found="..."
outer-join="..."
fetch="..."
lazy="false|proxy"
foreign-key="..."
unique="..."
where="...">
<column ... />
</complexCollectionProperty>

Wildcard collection fields


Wildcard collections are mapped using the many-to-any subelement of the the list mapping:

<list ... >


<key ... />
<list-index ... />
<many-to-any id-type="org.hibernate.type.LongType">
<column name="PropertyName_Hjclass"/>
<column name="PropertyName_Hjchildid"/>
</many-to-any>
</list>

Much like the many-to-many, many-to-any associations are also managed in a separate table:

create table MyClass_MyList (


MyClass_MyList_Hjid bigint not null,

35
Generating Hibernate mappings

MyClass_MyList_Hjclass varchar(255),
MyClass_MyList_Hjchildid bigint,
MyClass_MyList_Hjindex integer not null,
primary key (MyClass_MyList_Hjid, MyClass_MyList_Hjindex)
);

Customizations
Use wildcardCollectionProperty to customize the wildcard collection:

<wildcardCollectionProperty ... >


<!-- table, cache, key, list-index -->
<many-to-any
id-type="...">
<classColumn ... />
<idColumn ... />
</many-to-any>
</wildcardCollectionProperty>

Heterogeneous collection fields


Currently, heterogeneous collections are processed as wildard collections.

36
Chapter 4. Generating Hibernate
configuration
It is currently a common practice to include Hibernate mapping files (*.hbm.xml) into the JAR files
together with the mapped classes. In this case Hibernate needs to know, which resources should be
loaded as mappings.

The easiest way to provide Hibernate with this information is using the Hibernate configuration file. Hy-
perjaxb2 is capable of generating Hibernate configuration which simply lists all of the generated Hibern-
ate mappings. Below is an example of generated Hibernate configuration:

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE
hibernate-configuration
PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<mapping resource="org/jvnet/hyperjaxb2/tests/component/AType.hbm.xml"/>
<mapping resource="org/jvnet/hyperjaxb2/tests/component/A.hbm.xml"/>
</session-factory>
</hibernate-configuration>

Hyperjaxb2 generates Hibernate configuration by default, but you can turn it off if required.

37
Chapter 5. Using Hyperjaxb
In this chapter we will consider the real world usage of Hyperjaxb.

There are two scopes where the Hyperjaxb is used. First of all, Hyperjaxb is employed to generate Hi-
bernate mappings and configuration alongside with the source code of schema-derived classes produced
by JAXB (the compile scope). In the runtime scope, the usage of Hyperjaxb-mapped classes is not dif-
ferent from just normal Hibernate usage, but I will nevertheless demonstrate it.

Compile-time usage: generating the mapping


Basically, to produce Hibernate mappings for schema-derived classes you "simply" need to make Hy-
perjaxb available to XJC in the compile time. In practice, this "simply" often turns out to be quite com-
plicated. The problem is that Hyperjaxb has its own dependencies, which have to be included into the
XJC class path as well. And if you forget something, you'll be left alone with an error like "unrecog-
nized parameter -Xhyperjaxb2" with no further clues. Managing dependencies is no easy job
(especially if you don't use Maven), so this section is here to help you out.

We will consider two major build systems widely used by the Java community: Ant and Maven 2. I
hope that even if you use something else for build (like, command-line, shell scripts, make or Maven 1),
you'll still get the idea.

Ant usage
The easiest way to use Hyperjaxb with Ant is to base your project on the Ant project template provided
by Hyperjaxb2. This template project may get you started with Hyperjaxb in seconds. It is made in a
pure "just add water" style - that means, it contains all the required libraries and preconfigured
build.xml, reducing set-up of a new project to minimum.

Basic usage:

1. Extract hyperjaxb2-template-basic-ant-version.zip to the target directory.

2. Put your schemas (named *.xsd) into the src/main/resources directory.

3. Run ant clean install.

A bit more advanced usage:

1. Extract hyperjaxb2-template-ant-version.zip to the target directory.

2. Put your schemas (named *.xsd) into the src/main/resources directory.

3. Put your binding files (named *.xjb) into the src/main/resources directory.

4. Put your samples (named *.xml) into the src/test/samples directory.

5. Add your JDBC driver into the lib directory and change hyperjaxb2.runtime.path
defined in the build.xml.

6. Edit src/test/hibernate.properties to change JDBC driver class name, database prop-


erties (URL, username, password etc.), Hibernate SQL dialect and so on.

38
Using Hyperjaxb

7. Run ant clean install.

The default target of the template project carries out following actions:

• generate source code of the schema-derived classes, Hibernate mappings and Hibernate configura-
tion;

• compile the generated code;

• (if generated) run the roundtrip test case for all the *.xml files found in src/test/samples
against the database configured in hibernate.properties;

• package compiled classes and generated resources in a JAR file.

The result of the template project build is the JAR archive which contains the compiled schema-derived
classes, their Hibernate mappings (*.hbm.xml) as well as Hibernate configuration (hibern-
ate.cfg.xml in the root of the JAR).

Feel free to base your own builds on the build.xml from Ant project template. Most important are
path definitions:

hyperjaxb2.compile.path Class path used to produce and compile the generated classes.

hyperjaxb2.runtime.path Runtime and tesin classpath. Contains Hibernate, JAXB and Hy-
perjaxb2 runtime dependencies.

Configuring Hyperjaxb2 from Ant


Hyperjaxb2 has a number of configuration options. You can pass these from Ant using the <args ...
/> element. Below is the fragment of the Ant project template build.xml:

<xjc target="${basedir}/target/generated-sources/xjc" extension="true">


<arg line="
-Xequals
-XhashCode
-Xhyperjaxb2
-Xhyperjaxb2-rt=RoundtripTest"/>
<binding dir="${basedir}/src/main/resources">
<include name="**/*.xjb"/>
</binding>
<schema dir="${basedir}/src/main/resources">
<include name="**/*.xsd"/>
</schema>
</xjc>

You may notice four arguments within the arg element. -Xequals and -XhashCode turn on equals
and hash code JAXB add-ons. -Xhyperjaxb2 turns on the Hyperjaxb2. Finally, -
Xhyperjaxb2-rt=RoundtripTest sets the rt parameter of Hyperjaxb2 to RoundtripTest.
Hyperjaxb2 accepts the following parameters:

rt (string) Name of the roundtrip test case. If not provided, no roundtrip test case generated.

target Target directory (where *.hbm.xml and *.cfg.xml will be generated). De-

39
Using Hyperjaxb

faults to the output directory of XJC.

cfg (boolean) Whether to generate Hibernate configuration (hibernate.cfg.xml) or not. By de-


fault set to true (i.e. Hibernate config will be generated).

config (file) Name of the Spring configuration file which will be used to configure Hyperjaxb
internals. If not set, default configuration will be used. This is the extension point
allowing developers for cuztomizing the behaviour of Hyperjaxb, please do not
mix it with the generated Hibernate configuration.

In the example above rt is set to RoundtripTest. This will make Hyperjaxb add an implementation
of the roundtrip test case named RoundtripTest (this is fully qualified class name, so the class will
belong to the default package) to the generated classes.

It is highly recommended that classes used with Hibernate provide implementations of equals(...)
and hashCode() methods. These methods are generated by the equals and hash code add-ons from the
Jaxbcommons project.

Troubleshooting Ant builds


Building Hyperjaxb2 projects with Ant may be quite uneasy since this process involves a relatively
complex configuration of properties, filesets and class paths. It is not unlikely that you will get build er-
rors during the initial set-up of your project. Don't worry, it works.

The first step to diagnose and resolve build problems is to turn on debug and verbose modes in Ant:

ant -d -v myTarget

Go through the output that Ant produces and check that all the properties and paths are set correctly.

The most frequent problem that Hyperjaxb users report is the "unrecognized parameter -
Xhyperjaxb2" exception thrown by the XJC Ant task. The source of this problem is invalid classpath
of the XJC task. Carefully check this class path - it must include all the libraries required by Hyperjaxb
as well as the resource file META-INF/services/com.sun.tools.xjc.CodeAugmenter (in
hyperjaxb2-core-version.jar) containing class name of the Hyperjaxb add-on
(org.jvnet.hyperjaxb2.addon.AddOn).

If the problem persists, turn on tracing of the add-on instantiation in XJC. This is done by adding -
Dcom.sun.tools.xjc.Options.findServices=true to your ANT_OPTS.

Maven2 usage
Using Hyperjaxb2 from Maven2 is much simpler than from Ant since you don't need to manage the de-
pendencies manually. Moreover, Hyperjaxb2 provides a Maven2 plugin which makes code generation
with XJC and Hyperjaxb2 really simple. Here's what you have to do:

1. Add dev.java.net Maven repositories to your project:

<repositories>
<repository>
<id>maven2-repository.dev.java.net</id>
<url>https://maven2-repository.dev.java.net/nonav/repository</url>
</repository>
<repository>
<id>maven-repository.dev.java.net</id>

40
Using Hyperjaxb

<url>https://maven-repository.dev.java.net/nonav/repository</url>
<layout>legacy</layout>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>maven2-repository.dev.java.net</id>
<url>https://maven2-repository.dev.java.net/nonav/repository</url>
</pluginRepository>
<pluginRepository>
<id>maven-repository.dev.java.net</id>
<url>https://maven-repository.dev.java.net/nonav/repository</url>
<layout>legacy</layout>
</pluginRepository>
</pluginRepositories>

This is required because Hyperjaxb2 artifacts are stored in these repositories.

2. Add dependencies:

<dependencies>
<dependency>
<groupId>org.jvnet.hyperjaxb2</groupId>
<artifactId>hyperjaxb2-shared</artifactId>
<version>0.6.2</version>
</dependency>
<!-- Only required if you generate the roundtrip test case -->
<dependency>
<groupId>org.jvnet.hyperjaxb2</groupId>
<artifactId>hyperjaxb2-testing</artifactId>
<version>0.6.1</version>
</dependency>
<!-- Only required if you generate the roundtrip test case -->
<dependency>
<groupId>hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>1.7.3.3</version>
<scope>test</scope>
</dependency>
</dependencies>

3. Add Hyperjaxb2 Maven plugin to build plugins of your project:

<build>
<plugins>
<plugin>
<groupId>org.jvnet.hyperjaxb2.maven2</groupId>
<artifactId>maven-hyperjaxb2-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<extension>true</extension>

41
Using Hyperjaxb

<roundtripTest>RoundtripTest</roundtripTest>
</configuration>
</plugin>
</plugins>
</build>

Note that you don't need to configure or turn on specific add-ons. Hyperjaxb Maven plugin will do it for
you.

Maven2 project template


Hyperjaxb2 provides a project template for Maven2. It has a preconfigured pom.xml. Usage is analog-
ous to the Ant project template (schema and binding filed in src/main/resources, samples in
src/test/samples). "Just add water".

Configuring Hyperjaxb2 from Maven2


Hyperjaxb2 is conigured from Maven2 via the plugin configuration:

<plugin>
<groupId>org.jvnet.hyperjaxb2.maven2</groupId>
<artifactId>maven-hyperjaxb2-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<extension>true</extension>
<roundtripTest>RoundtripTest</roundtripTest>
</configuration>
</plugin>

See plugin documentation or configuration elements (there's many of them, most inherited from the
maven-jaxb1-plugin). Hyperjaxb2 own configuration elements are the following:

target (directory) Location of the target directory to output Hibernate mappings and
Hibernate configuration. By default mappings are written to the
XJC's target directory.

config (file) Spring configuration of the Hyperjaxb principal strategy.

roundtripTest (string) Fully qualified class name of the roundtrip test case class. If not
specified, not roundtrip test case produced.

resourceIncludes/include (file pat- Patterns of the files to be treated as resources. By default,


terns) **/*.hbm.xml and **/*.cfg.xml (Hibernate mapping and
configuration).

hashCodeAndEquals Selects the generation mode for hashCode() and equals(...) meth-
(normal/extended/none) ods. The normal mode uses straight recursion, it produces faster

42
Using Hyperjaxb

methods, but these methods will fail on structures with cycles.


The extended mode generates a less performant methods also
suitable for cyclic structures. Finally, the none disables the gen-
eration of the hashCode() and equals(...) methods (not
recommended).

TODO: Generating/exporting the database schema with


Hyperjaxb and Hibernate
TODO

Run-time usage: working with objects


This section demonstrates the run-time usage of Hibernate with JAXB-generated classes and mappings
produced by Hyperjaxb.

Initializing JAXB context, marshaller and unmarshaller


With JAXB, object structures are loaded from and saved to XML using the special objects named mar-
shaller and unmarshaller. To obtain marshaller and unmarshaller, you will first need to set up the JAXB
context:

final JAXBContext context = JAXBContext.newInstance(packageNames);

In the code fragment above, packageNames is the list of schema-derived packages that JAXB has
generated for you. In case you have a single package, you may use the following trick to avoid hardcod-
ing the package name:

final JAXBContext context = JAXBContext.newInstance(MyClass.class.getPackage().getN

The class MyClass is one of the schema-derived interfaces.

In case you have multiple schema-derived packages, you should use ":" as separator:

final JAXBContext context = JAXBContext.newInstance("net.opengis.ows:net.opengis.gm

If you have a complex run-time environment with multiple classloaders, you may also need to specify
the classloader to be used by JAXB. Typically, this must be the classloader that loaded your schema-de-
rived classes:

final JAXBContext context =


JAXBContext.newInstance(
MyClass.class.getPackage().getName(),
MyClass.class.getClassLoader());

After JAXB context is initialized, it can be used to produce marshaller and unmarshaller:

final Unmarshaller unmarshaller = context.createUnmarshaller();


final Marshaller marshaller = context.createMarshaller();

Please note that JAXB context is thread safe while marshaller and unmarshaller instances are not. It is

43
Using Hyperjaxb

recommended to have a single instance of JAXB context per application and create marshallers and un-
marshallers just as you need them. Marshallers and unmarshallers are also reusable which means you
can pool them if needed.

Unmarshallers are used to convert XML into an object structure. To unmarshal the XML, simply feed
your data into the unmarshaller:

final Unmarshaller unmarshaller = context.createUnmarshaller();


final Object object = unmarshaller.unmarshal(xml);

Unmarshallers can process files, input streams, URLs, javax.xml.transform.Sources,


org.xml.sax.InputSources and DOM nodes, so there's a whole range to choose from.

Marshallers perform the opposite process - they serialize object structures as XML. To marshall an ob-
ject, create a marshaller and pass your data to it:

final Marshaller marshaller = context.createMarshaller();


marshaller.marshal(object, target);

Marshallers accept SAX content handlers, DOM nodes, output streams


javax.xml.transform.Results and java.io.Writers as targets.

Setting up the Hibernate session factory


In order to work with Hibernate, you will need to configure the Hibernate session factory. If you did not
turn of generaion of the Hibernate configuration, then factory set-up is trivial. First of all, take care of
certain preconditions:

• Add JAR file with your classes/Hibernate mappings/Hibernate configuration to the class path of
your application.

• Add hibernate.properties to the class path of your application.

After that factory initialization is as easy as:

final Configuration configuration = new Configuration().configure();


final SessionFactory sessionFactory = configuration.buildSessionFactory();

If you configure session factory with Spring, simply add your Hibernate mappings directory to the
mappingDirectoryLocations:

<!-- TODO: Spring config. -->


<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFac
<property name="dataSource" ref="dataSource"/>
<property name="mappingDirectoryLocations">
<list>
<value>${hyperjaxb2.hbm.dir}</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.jdbc.batch_size">0</prop>
</props>
</property>

44
Using Hyperjaxb

</bean>

After the factory is initialized, you may open a session to do perform the desired action:

final Session session = sessionFactory.openSession();


final Transaction transaction = session.beginTransaction();
// Do something with your objects
session.saveOrUpdate(myObject);
transaction.commit();
session.close();

Importing data
Import operation consists of unmarshalling the XML data and importing the unmarshalled object struc-
ture into the database. Apart from the initialization procedures, it's actually a couple of lines of code:

// Create the unmarshaller


final Unmarshaller unmarshaller = context.createUnmarshaller();
// Unmarshall the XML
final Object object = unmarshaller.unmarshal(xml);
// Open the session
final Session saveSession = sessionFactory.openSession();
// Save the unmarshalled object into the database
saveSession.saveOrUpdate(object);
// Get the id
final Serializable id = saveSession.getIdentifier(object);
// Flush and close the session
saveSession.flush();
saveSession.close();

The actual operation you perform with the object in the Hibernate session depends on the semantics of
"import" operation, as you see them. It can be one of the save, update, saveOrUpdate, persist,
merge or replicate methods.

Exporting data
In order to export an XML document stored in the database, you first have to load the corresponding ob-
ject and then use a marshaller to serialize it into XML:

// Open the session


final Session loadSession = sessionFactory.openSession();
// Load the object
final Object loadedObject = loadSession.load(object.getClass(), id);
// Close the session
loadSession.close();
// Create a marshaller
final Marshaller marshaller = context.createMarshaller();
// Marshall the object
marshaller.marshall(loadedObject, xml);

To load an object from the database, use one of the load or get methods. The difference between
these two is that the load method will throw an exception if there's no object with given identifier in

45
Using Hyperjaxb

the database while get exits gracefully.

Executing queries
Hyperjaxb imposes no limitation on querying your content objects with Hibernate - you may use HQL
queries as well as native SQL queries, filters and criteria queries.

By default, Hyperjaxb disables auto-import of classes. This means that you have to use the fully quali-
fied class name, for instance, org.jvnet.hyperjaxb2.tests.po.PurchaseOrder instead of
PurchaseOrder.

In your queries, you may use both interfaces and implementation classes (however most users prefer in-
terfaces).

In HQL queries, you have to use property names rather than names of elements or attributes of the XML
Schema. These names are usually very similar (although rarely identical) which makes querying non-
problematic.

Here is an example of HQL query:

// We're interested in purchase orders for Alice Smith


final List purchaseOrders = session.createQuery(
"from org.jvnet.hyperjaxb2.tests.po.PurchaseOrderType po join po.ShipTo shipTo "
"where shipTo.Name = :name")
.setString("name", "Alice Smith")
.list();

46
Chapter 6. Extending Hyperjaxb
Hyperjaxb is written with extensibility in mind. There is no single way to generate Hibernate mappings
for JAXB classes, there are plenty ways to do it. Hyperjaxb tries to implement reasonable default map-
ping generation. It also offers rich customization possibilities, but sometime you need to redefine the de-
fault behaviour of Hyperjaxb just because "reasonable default mappings" for your case differ from Hy-
perjaxb defaults.

This chapter covers Hyperjaxb extensibility. It describes how you could redefine the default behaviour
of Hyperjaxb using Hyperjaxb strategies.

Understanding Hyperjaxb strategies


To allow this ultra-high level of extensibility, Hyperjaxb heavily uses the "strategy" design pattern.
Quote:

The Strategy Design Pattern basically consists of decoupling an algorithm from its host, and en-
capsulating the algorithm into a separate class. More simply put, an object and its behaviour are
separated and put into two different classes. This allows you to switch the algorithm that you are
using at any time. There are several advantages to doing this. First, if you have several different
behaviours that you want an object to perform, it is much simpler to keep track of them if each be-
haviour is a separate class, and not buried in the body of some method. Should you ever want to
add, remove, or change any of the behaviours, it is a much simpler task, since each one is its own
class. Each such behaviour or algorithm encapsulated into its own class is called a Strategy.

With very few exceptions most of the things that Hyperjaxb does are done with strategies. There are
strategies that generate mappings, analyze classes and fields, deal with customizations, define naming
conventions and so on. Thus if you need to redefine some part of Hyperjaxb behaviour, you just replace
certain strategies with your own implementations. The rest of the system will not be influenced.

Hyperjaxb delegates almoust all of its functionality to the central principal strategy (defined in the inter-
face
org.jvnet.hyperjaxb2.hibernate.mapping.strategy.principal.PrincipalStr
ategy). This principal strategy, in its turn, containes a number of further smaller strategies responsible
for smaller specific functions. For instance, there is a naming strategy responsible for generation of
names for tables and fields, strategies that generate class and field mappings, identifiers and versions
and so on.

Hyperjaxb uses Spring to configure/instantiate the principal strategy. During the initialization, the Hy-
perjaxb add-on loads the Spring application context from the configured location (the one you configure
via the config command line argument or classpath*:hyperaxb2.config.xml by default).
After the application context is loaded, Hyperjaxb searches this context for a bean which implements the
pricipal strategy interface and uses this bean further on.

If you understood well this mechanism, you have probably already guessed what you need to do if you
want to override Hyperjaxb behaviour somehow:

1. Deside which strategy you need to change. Discussion of Hyperjaxb strategies is out of the scope of
this document, but you can find good hints in Javadocs and directly in the source code of Hyper-
jaxb.

2. Implement your strategy. Refer to default implementations for the examples.

3. Write your own Hyperjaxb application context configuration.

47
Extending Hyperjaxb

4. Configure your application context wih Hyperjaxb by passing the configuration location via the
config parameter.

48
Chapter 7. Credits and
acknowledgements
Hyperjaxb is developed by Aleksei Valikov with the help of many individuals providing test scenarios
and valuable feedback.

Many thanks to JAXB developers, especially Kohsuke Kawaguchi.

Hyperjaxb uses or includes the following products, libraries, tools and technologies:

• JAXB and JAXB Reference Implementation (http://java.sun.com/xml/jaxb/,


https://jaxb.dev.java.net).

• Hibernate (http://www.hibernate.org).

• Jakarta Commons (http://jakarta.apache.org/commons/).

• HSQLDB (http://hsqldb.org/).

• JUnit (http://www.junit.org).

• Jaxbcommons (http://jaxbcommons.dev.java.net).

• Log4j (http://logging.apache.org/log4j/docs).

• Spring Framework (http://www.springframework.org).

• Saxon (http://www.saxonica.com/).

• DocBook (http://www.docbook.org).

• Docbkx Tools (http://www.agilejava.com/docbkx/).

• Ant (http://ant.apache.org).

• Maven (http://maven.apache.org).

• Maven JAXB1 plugin (https://maven-jaxb1-plugin.dev.java.net).

49

Anda mungkin juga menyukai