Professional Documents
Culture Documents
Hyperjaxb 2 - Relation Persistence For JAXB Objects: Reference Documentation
Hyperjaxb 2 - Relation Persistence For JAXB Objects: Reference Documentation
Hyperjaxb 2 - Relation Persistence For JAXB Objects: Reference Documentation
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:
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.
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:
• Human-readable.
Querying Queries are formulated in the the terms, which are close to XML.
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.
• 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.
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 ).
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:
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>
The last and the most interesting is the database schema generated out of the *.hbm.xml files with the
Hibernate schema export utility:
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:
8
Introduction
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
...
</xsd:schema>
[UML]
[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>
9
Introduction
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.
• 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.
3. 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:
12
Basics
<xs:enumeration value="c"/>
<xs:enumeration value="d"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
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.
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.
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
<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.
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.
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>
19
Generating Hibernate mappings
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>
<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.
<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:
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
<component
access="..."
unique="..."
update="..."
insert="..."
lazy="..."
optimistic-lock="..."/>
<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>
<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.
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>
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.
<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>
26
Generating Hibernate mappings
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.
For the typesafe enum fields, Hyperjaxb generates a custom Hibernate type.
<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>
<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
<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.
<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>
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.
<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.
<...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
<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:
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>
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:
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:
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>
Much like the many-to-many, many-to-any associations are also managed in a separate table:
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:
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:
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.
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:
3. Put your binding files (named *.xjb) into the src/main/resources directory.
5. Add your JDBC driver into the lib directory and change hyperjaxb2.runtime.path
defined in the build.xml.
38
Using Hyperjaxb
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;
• (if generated) run the roundtrip test case for all the *.xml files found in src/test/samples
against the database configured in hibernate.properties;
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.
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
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.
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:
<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>
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>
<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.
<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.
roundtripTest (string) Fully qualified class name of the roundtrip test case class. If not
specified, not roundtrip test case produced.
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
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:
In case you have multiple schema-derived packages, you should use ":" as separator:
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:
After JAXB context is initialized, it can be used to produce marshaller and unmarshaller:
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:
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:
• Add JAR file with your classes/Hibernate mappings/Hibernate configuration to the class path of
your application.
If you configure session factory with Spring, simply add your Hibernate mappings directory to the
mappingDirectoryLocations:
44
Using Hyperjaxb
</bean>
After the factory is initialized, you may open a session to do perform the desired action:
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:
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:
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
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.
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.
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.
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.
Hyperjaxb uses or includes the following products, libraries, tools and technologies:
• Hibernate (http://www.hibernate.org).
• HSQLDB (http://hsqldb.org/).
• JUnit (http://www.junit.org).
• Jaxbcommons (http://jaxbcommons.dev.java.net).
• Log4j (http://logging.apache.org/log4j/docs).
• Saxon (http://www.saxonica.com/).
• DocBook (http://www.docbook.org).
• Ant (http://ant.apache.org).
• Maven (http://maven.apache.org).
49