Top Banner
Hyperjaxb 2 - Relation persistence for JAXB objects Reference Documentation Aleksei Valikov
54
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: HyperJaxb2

Hyperjaxb 2 - Relation persistence forJAXB objects

Reference Documentation

Aleksei Valikov

Page 2: HyperJaxb2

Hyperjaxb 2 - Relation persistence for JAXB objects: ReferenceDocumentationby 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 andfurther provided that each copy contains this Copyright Notice, whether distributed in print or electronically.

Page 3: HyperJaxb2
Page 4: HyperJaxb2

Table of ContentsPreface ...................................................................................................................... v1. Introduction ............................................................................................................ 1

Overview ........................................................................................................................... 1Worked example ................................................................................................................. 2

2. Basics .................................................................................................................. 11Classes and interfaces ........................................................................................................ 11Fields .............................................................................................................................. 11Single fields ..................................................................................................................... 12Collection fields ................................................................................................................ 12Simple fields .................................................................................................................... 12Enum fields ..................................................................................................................... 12DOM fields ...................................................................................................................... 13Complex fields ................................................................................................................. 13Wildcard fields ................................................................................................................. 13Heterogeneous fields ......................................................................................................... 13Field accessors ................................................................................................................. 13

3. Generating Hibernate mappings ................................................................................ 15The overall process ............................................................................................................ 15Customizations ................................................................................................................. 15Common customization elements and types ............................................................................ 17Ignoring classes and fields .................................................................................................. 18Class mapping .................................................................................................................. 19Customizing class mapping ................................................................................................. 20Marking class as component ................................................................................................ 22Identifier and version properties ........................................................................................... 23Inheritance mapping .......................................................................................................... 25Single fields ..................................................................................................................... 27Simple, enum and DOM single fields .................................................................................... 27Complex single fields ........................................................................................................ 29Wildcard single fields ........................................................................................................ 30Heterogeneous single fields ................................................................................................. 31Collection fields ................................................................................................................ 31Generic collection mapping ................................................................................................. 31Simple, enum and DOM collection fields ............................................................................... 33Complex collection fields ................................................................................................... 33Wildcard collection fields ................................................................................................... 35Heterogeneous collection fields ........................................................................................... 36

4. Generating Hibernate configuration ........................................................................... 375. Using Hyperjaxb ................................................................................................... 38

Compile-time usage: generating the mapping ......................................................................... 38Ant usage ........................................................................................................................ 38Maven2 usage .................................................................................................................. 40TODO: Generating/exporting the database schema with Hyperjaxb and Hibernate ......................... 43Run-time usage: working with objects ................................................................................... 43Initializing JAXB context, marshaller and unmarshaller ............................................................ 43Setting up the Hibernate session factory ................................................................................ 44Importing data .................................................................................................................. 45Exporting data .................................................................................................................. 45Executing queries .............................................................................................................. 46

6. Extending Hyperjaxb .............................................................................................. 47Understanding Hyperjaxb strategies ...................................................................................... 47

7. Credits and acknowledgements ................................................................................. 49

iv

Page 5: HyperJaxb2

PrefaceThis 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 adaptedthe DocBook-XSL software in order to be able to create Hibernate's reference guide, also allowing us tocreate this one.

v

Page 6: HyperJaxb2

Chapter 1. IntroductionOverview

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 solutionwith the following requirements and properties:

XML Schema-driven XML documents conforms to the certain XML Schema, whichdefines 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 stockquotes) rather than those intended for human consumption (books,email, advertisements, and almost any hand-written XHTML).

Automatically generated databaseschema

Database schema is automatically generated based on the givenXML 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 ofthe XML Schema).

These properties make possible the integration on the databaselevel.

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 onthe XML Schema.

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

1

Page 7: HyperJaxb2

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

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 forthe marshalling and unmarshalling of XML data. Together with the JAXB runtime, they allow parsingXML into content objects (instances of schema-derived classes).

Hibernate in its turn implements object-relational persistence. Provided the object-relational mappingconfiguration, Hibernate is capable of saving objects into the relational database, loading them back aswell as processing queries. Moreover, Hibernate also provides a very handy schema export tool whichcan 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 classesmust be generated out of the XML Schema (as well as the schema-derived classes themselves). For thispurpose, Hyperjaxb includes an XJC add-on which analyzes classes and fields generated by JAXB andproduces 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 ofschema-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 marshallresults as XML.

Worked exampleThis 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"/>

Introduction

2

Page 8: HyperJaxb2

<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>

Introduction

3

Page 9: HyperJaxb2

<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 generatedpackage for null namespaces). I'll also instruct JAXB to generate isSetField methods for fields (thisis 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 wayto start a Hyperjaxb project is to use the project template [???]. Hyperjaxb distribution provides projecttemplates for Ant and Maven out of the box. We will start with Ant since this is what most developersare 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).

Introduction

4

Page 10: HyperJaxb2

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/samplesdirectory.

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 theroundtrip 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, complextypes). 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.tests.po

Interface package.

org.jvnet.hyperjaxb2.tests.po.impl

Implementation package.

org.jvnet.hyperjaxb2.tests.po.impl.runtime

Utility classes.

Structure of the generated classes may be illustrated by the following diagram (since implementationclasses 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 ofthe generated classes are named after the corresponding elements and attributes of the schema. Note thatHyperjaxb 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 theorg.jvnet.hyperjaxb2.tests.po.USAddress andorg.jvnet.hyperjaxb2.tests.po.impl.USAddressImpl pair:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-mappingPUBLIC "-//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"><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.CheckingPropertyAccessor"name="Hjid"

Introduction

5

Page 11: HyperJaxb2

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.CheckingPropertyAccessor"

name="State"><column name="State"/><type name="org.hibernate.type.StringType"/>

</property><property access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPropertyAccessor"

name="Zip"><column name="Zip"/><type name="org.hibernate.type.BigDecimalType"/>

</property><property access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPropertyAccessor"

name="Country"><column name="Country"/><type name="org.hibernate.type.StringType"/>

</property><property access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPropertyAccessor"

name="City"><column name="City"/><type name="org.hibernate.type.StringType"/>

</property><property access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPropertyAccessor"

name="Street"><column name="Street"/><type name="org.hibernate.type.StringType"/>

</property><property access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPropertyAccessor"

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 theHibernate 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),

Introduction

6

Page 12: HyperJaxb2

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_Item_Hjid) references Items;alter table PurchaseOrderType add constraint FK1C959F87D456BE41 foreign key (Items) references Items;alter table PurchaseOrderType add constraint FK1C959F876D216E99 foreign key (BillTo) references USAddress;alter table PurchaseOrderType add constraint FK1C959F878A146B8E foreign key (ShipTo) references USAddress;

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 backto 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 asHibernate 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 appearwithin the purchase order.

The tuning above can be done with Hyperjaxb customzations. I'll also customize few more things, fordemonstration 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 differentpurchase orders defined in two different XML files have items with the same partNum, they willrefer to the same object stored in the database.

Introduction

7

Page 13: HyperJaxb2

To customize schema processing with Hyperjaxb, I'll declare the binding extension namespace and addcustomization 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>

Introduction

8

Page 14: HyperJaxb2

</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 Avenue','Robert Smith')

INSERT INTO ADDRESS VALUES(2,'org.jvnet.hyperjaxb2.tests.po.USAddress','CA',90952,'US','Mill Valley','123 Maple Street','Alice Smith')

Introduction

9

Page 15: HyperJaxb2

INSERT INTO PO VALUES(1,'org.jvnet.hyperjaxb2.tests.po.PurchaseOrder','1999-10-20 02:00:00.0','Hurry, my lawn is going wild!',1,2)

INSERT INTO ITEM VALUES('872-AA','org.jvnet.hyperjaxb2.tests.po.Items.ItemType','Confirm this is electric',148.95,'Lawnmower',NULL,1,NULL,NULL)

INSERT INTO ITEM VALUES('926-AA','org.jvnet.hyperjaxb2.tests.po.Items.ItemType',NULL,39.98,'Baby Monitor','1999-05-21 02:00:00.0',1,NULL,NULL)

DELETE FROM ITEM WHERE PARTNUM='872-AA'

INSERT INTO ITEM VALUES('872-AA','org.jvnet.hyperjaxb2.tests.po.Items.ItemType','Confirm this is electric',148.95,'Lawnmower',NULL,1,1,0)

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','1999-05-21 02:00:00.0',1,1,1)

Introduction

10

Page 16: HyperJaxb2

Chapter 2. BasicsThe 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 onabout how these mappings are generated, you first need to understand what should be mapped. An thisimplies 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 essentiallyPOJOs 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 classesand fields that Hyperjaxb is busy with.

Classes and interfacesWhen 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 thepair of PurchaseOrderType interface and PurchaseOrderTypeImpl class. JAXB also respectstype derivation: if complex type B extends (or restricts) type A, this will be represented by the followingtype 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.

FieldsWhen 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 derivedfrom repeatable elements, but there may be other options (for instance, list type as content type), so don'tbe scared if your attribute field is collection.

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

• simple fields;

11

Page 17: HyperJaxb2

• enum fields;

• DOM fields;

• wildcard fields;

• complex fields;

• heterogeneous fields.

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

Single fieldsSingle 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 fieldsCollection fields are represented by a collection-valued object properties. JAXB generatesjava.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 maxOccursgreater 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 fieldsSimple field is a field which contains value of a any simple type (with the exception of typesafe enumer-ations).

Enum fieldsJAXB allows you to customize enumerated simple types so that they will be processed as type-safeenums. 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"/>

Basics

12

Page 18: HyperJaxb2

<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 ofthe TypeSafeStringEnumeration class.

DOM fieldsIn 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 ofsome product in your schema may contain an XHTML fragment in the description, you probably won'twant to make JAXB parse all these ps, brs, divs and so on. In this case, you simply mark descriptionelement 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 fieldsComplex fields represent schema elements with complex types.

Wildcard fieldsXML 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 fieldsIn 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 ofAType or BType classes (assuming aType and bType are complex).

Field accessors

Basics

13

Page 19: HyperJaxb2

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

First complication is "null" semantics of fields. For the primitive field, judging only by its value, it isnot 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 withvalue 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 takesadvantage of this feature and defines its own Hibernate property accessor which checks if field is emptyor 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.

Basics

14

Page 20: HyperJaxb2

Chapter 3. Generating Hibernatemappings

Previous chapter described basic constructs which we need to map. This chapter goes on and describeshow these constructs are mapped by Hyperjaxb, i.e. what do the generated mappings look like and howthese mappings can be customized.

The overall processHyperjaxb is implemented as an XJC add-on. Hyperjaxb implements specific interface (and followssome further deployment procedures) which allows it to be picked up by XJC in the runtime. The add-onis invoked by XJC after XML Schema is processed into class and field items but before the actual codeis written to the disk. This allows Hyperjaxb to analyze classes and fields generated by XJC and addsome 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 typesof fields and classes, their types and hierarchy. Consider customizations.

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

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 configurationand mapping DTDs compiled with JAXB. So instead of manipulating pure XML, Hyperjaxb works withneat and nice object structures which are afterwards simply marshalled by JAXB into *.hbm.xml and*.cfg.xml resources.

CustomizationsHyperjaxb 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 correspondingXML 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 thegenerated 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 seehibernate-customizations/src/main/resources/customizations.xsd[https://hyperjaxb2.dev.java.net/source/browse/hyperjaxb2/schemas/hibernate-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

Page 21: HyperJaxb2

declare the http://hyperjaxb2.jvnet.org/customizations as JAXB extension bindingnamespace. This is done by declaring the namespace with a prefix and specifying the declared prefix injaxb:extensionBindingPrefixes attribute. Below are examples of declarations in schema andexternal binding files.

<xs:schemaxmlns: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:appinfointo 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 thedesired 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>

Generating Hibernate mappings

16

Page 22: HyperJaxb2

</jaxb:bindings>

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

</jaxb:bindings>

</jaxb:bindings>

</jaxb:bindings>

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

Common customization elements and typesThere 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 catalogwith 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.

<tablename="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.

<columnname="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:

<typename="type_name"/>

Generating Hibernate mappings

17

Page 23: HyperJaxb2

key

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

<keyproperty-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 innested column elements).

cache

You may also customize caching of classes and collections.

<cacheusage="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 fieldsIf 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" minOccurs="0"/><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 ignoredelement field property.

Generating Hibernate mappings

18

Page 24: HyperJaxb2

Class mappingFor each of the class items, JAXB generates a pair of interface and implementation class. That is, yourmyComplexType complex type will be represented by an interfaceorg.jvnet.hyperjaxb2.tests.foo.MyComplexType and implementation classorg.jvnet.hyperjaxb2.tests.foo.impl.MyComplexTypeImpl. Hyperjaxb generates asingle mapping file for each interface/implementation class pair. Typical structure of the mapping file isas follows:

<!DOCTYPEhibernate-mapping

PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mappingauto-import="false"default-cascade="all-delete-orphan"default-lazy="false">

<!-- Interface mapping --><classdiscriminator-value="[org.jvnet.hyperjaxb2.tests.foo.MyComplexType]"name="org.jvnet.hyperjaxb2.tests.foo.MyComplexType"table="MyComplexType"><!-- ... -->

<!-- Implementation class mapping --><subclassdiscriminator-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 onthe 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 interand database table):

<classdiscriminator-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

Generating Hibernate mappings

19

Page 25: HyperJaxb2

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"><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 tothe 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 ofthe interface itself. However, this can be easily customized.

<classname="org.jvnet.hyperjaxb2.test.one.RootType"table="RootType"><id ... /><discriminatortype="org.hibernate.type.StringType">

<!-- ... --><version ... /><!-- ... -->

</class>

Customizing class mappingYou can customize class mapping by including the class element into the annotation.

<classproxy="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 ... />

Generating Hibernate mappings

20

Page 26: HyperJaxb2

<discriminatortype="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 anddiscriminator 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, butin 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 - itsimply returns a specific value. In more complex cases a more complex expression may be required. Forinstance, one could check certain columns to be not null, analyze identifiers and so on.

Generating Hibernate mappings

21

Page 27: HyperJaxb2

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

<componentaccess="..."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.CheckingPropertyAccessor"

name="D"><column name="B_D"/><type name="org.hibernate.type.StringType"/>

</property><list access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.ListAccessor" name="E"

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>

Generating Hibernate mappings

22

Page 28: HyperJaxb2

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

Identifier and version propertiesHibernate requires mapped classes to have an identifier property. Since schema-derived classes usuallydo 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. Hibernateuses 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 calledHjversion and has the java.lang.Long type.

<classname="org.jvnet.hyperjaxb2.test.one.RootType"table="RootType"><!-- ... --><idname="Hjid"type="org.hibernate.type.LongType"><generator class="native"/>

</id><!-- ... --><versionname="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 existingelements or attributes with id and version elements and Hyperjaxb will use the marked fields asidentifier 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:

<idaccess="field|property|className"unsaved-value="null|any|undefined|id_value"><column ... /><generatorgeneratorClass="generatorClass"><param

name="paramName"value="paramValue"/>

</generator><type ... />

</id>

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

Generating Hibernate mappings

23

Page 29: HyperJaxb2

<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 usedas 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 theforeign generator).

version

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

<versionaccess="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">

Generating Hibernate mappings

24

Page 30: HyperJaxb2

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

</xsd:appinfo></xsd:annotation>

</xsd:attribute></xsd:complexType>

Inheritance mappingIn Hibernate, both implementation of the interface and extension of the class are considered inheritanceand 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 referenceparent tables rather than copy inherited property columns;

• table-per-concrete-class, where each class is mapped onto its own table and each table definescolumns 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 isoften 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 implementationclass table, complex type interface table and complex type implementation class table. Three of fourtables 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 mappedonto the table of its parent class. If subclass has some additional properties, they will be mapped onto ajoined 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:

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

Generating Hibernate mappings

25

Page 31: HyperJaxb2

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><subclassdiscriminator-value="org.jvnet.hyperjaxb2.test.one.SequenceType"name="org.jvnet.hyperjaxb2.test.one.impl.SequenceTypeImpl"/>

</class>

<subclassdiscriminator-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><subclassdiscriminator-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 astheir implementation classes) will be stored in the SequenceType table. Additional properties C and Dof 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)

);

Generating Hibernate mappings

26

Page 32: HyperJaxb2

alter table ExtendedSequenceTypeadd constraint FK439D9A94383B3433foreign key (Hjid)references SequenceType;

This strategy generates fewer tables than table-per-subclass strategy (table is generated only if subclasshas 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 ofpersistent instances. By default, Hyperjaxb generates a string Hjtype column in the root table of thehierarchy. Default value of the discriminator is the fully qualified name of the interface.

Single fieldsSimple, enum and DOM single fields

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

<propertyaccess="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPropertyAccessor"name="PropertyName"><columnname="ColumnName">

<typename="TypeClass"/>

</property>

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

Hyperjaxb uses a custom property accessor to take advantage ofisSetMyProperty/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-definedorg.jvnet.hyperjaxb2.runtime.hibernate.type.ElementType custom Hibernatetype which is used to map DOM content. When saving into the database, this type serializes DOM treesinto 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"/>

Generating Hibernate mappings

27

Page 33: HyperJaxb2

<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"><!-- ... --><propertyname="String"access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPropertyAccessor"><column name="String"/><type name="org.hibernate.type.StringType"/>

</property><property name="TypeSafeStringEnumeration"access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPropertyAccessor"><column name="TypeSafeStringEnumeration"/><type name="org.jvnet.hyperjaxb2.test.one.TypeSafeStringEnumeration$Type"/>

</property><property name="Content"access="org.jvnet.hyperjaxb2.runtime.hibernate.accessor.CheckingPropertyAccessor"><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:

<simpleSinglePropertyaccess="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 detailedsemantics, please consult the Hibernate documentation.

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

Generating Hibernate mappings

28

Page 34: HyperJaxb2

<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 fieldsBy default, Hyperjaxb generates many-to-one mapping for complex singe fields. There are two moreoptions, namely one-to-one and component mappings, which can be chosen by the customization.

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

</many-to-one>

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

<componentname="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-oneaccess="field|property|ClassName"cascade="..."outer-join="..."fetch="..."constrained="true|false"foreign-key="..."property-ref="..."

Generating Hibernate mappings

29

Page 35: HyperJaxb2

lazy="true|false|proxy"/>

Please note that this type of mapping requires parent and child entities to have identical identifiers. Youmay 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-oneaccess="..."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 thecustomized property. In the contrast to component customization of the class, this customization willbe limited to the customized property only.

Wildcard single fieldsHyperjaxb represents wildcard single fields with Hibernate's any mapping. By default, wildcard fieldwill 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>

<anyid-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:

<wildcardSinglePropertyaccess="..."update="true|false"insert="true|false"

Generating Hibernate mappings

30

Page 36: HyperJaxb2

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 describedpreviously. 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 fieldsAt the moment, Hyperjaxb treats heterogeneous single fields as wildcard fields. That is, any mapping isgenerated. This is far not optimal mapping (single possible types of the heterogeneous fields are knownin the compile-time) and will be changed in future.

Collection fieldsGeneric 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 alsocontains the list-index subelement, idbag has an additional collection-id element.

Default collection mapping is list:

<listaccess="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, butdon't provide the collection-id customization, Hyperjaxb will generate bag mapping:

Generating Hibernate mappings

31

Page 37: HyperJaxb2

<bagaccess="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 torecreate 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:

<idbagaccess="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 columnnames using class name and property name. If generated names are too long, provide your own namesthrough the customization.

Generic collection mapping customizations

Customizations for collection mappings also share the same base structure:

<...CollectionPropertyaccess="..."lazy="true|false"inverse="true|false"cascade="..."where="..."batch-size="..."outer-join="..."fetch="..."persister="..."check="..."optimistic-lock="true|false"><table ... /><cache ... /><key ... /><list-indexbase="..."><column ... />

</list-index><no-index/><collection-id><column ... /><generator ... /><type ... />

</list-index>

Generating Hibernate mappings

32

Page 38: HyperJaxb2

<!-- Type-specific customizations --></...CollectionProperty>

Simple, enum and DOM collection fieldsSimple, 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 besomething 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 Hyperjaxbuses the generated Hibernate type-safe enum user class andorg.jvnet.hyperjaxb2.runtime.hibernate.type.ElementType for enum and DOMfields 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 fieldsComplex collection are mapped with either one-to-many or many-to-many subelements of listmapping. The one-to-many mapping is the default option; many-to-many may be selectedthrough the customization.

Generating Hibernate mappings

33

Page 39: HyperJaxb2

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

</list>

<list ...><key ... /><list-index ... /><many-to-manyclass="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 indexcolumns:

<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 propertiesMyClass_MyList_Hjid bigint,MyClass_MyList_Hjindex integer,primary key (Hjid)

);

alter table MyChildClassadd constraint FK7A84E5A1D308C2EAforeign 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 thiscase, 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"/>

Generating Hibernate mappings

34

Page 40: HyperJaxb2

</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_MyListadd constraint FKB72EC39CFF0186B1foreign key (MyClass_MyList_Hjchildid)references MyChildClass;

alter table MyClass_MyListadd constraint FKB72EC39CE0B300BFforeign key (MyClass_MyList_Hjid)references MyClass;

Customizations

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

<complexCollectionProperty><!-- table, cache, key, list-index, no-index --><one-to-manynot-found="..."/>

<many-to-manynot-found="..."outer-join="..."fetch="..."lazy="false|proxy"foreign-key="..."unique="..."where="..."><column ... />

</complexCollectionProperty>

Wildcard collection fieldsWildcard 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,

Generating Hibernate mappings

35

Page 41: HyperJaxb2

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-anyid-type="..."><classColumn ... /><idColumn ... />

</many-to-any></wildcardCollectionProperty>

Heterogeneous collection fieldsCurrently, heterogeneous collections are processed as wildard collections.

Generating Hibernate mappings

36

Page 42: HyperJaxb2

Chapter 4. Generating Hibernateconfiguration

It is currently a common practice to include Hibernate mapping files (*.hbm.xml) into the JAR filestogether with the mapped classes. In this case Hibernate needs to know, which resources should beloaded 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-configurationPUBLIC"-//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

Page 43: HyperJaxb2

Chapter 5. Using HyperjaxbIn 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 producedby 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 mappingBasically, 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 theXJC 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. Ihope 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 usageThe easiest way to use Hyperjaxb with Ant is to base your project on the Ant project template providedby Hyperjaxb2. This template project may get you started with Hyperjaxb in seconds. It is made in apure "just add water" style - that means, it contains all the required libraries and preconfiguredbuild.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.pathdefined 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

Page 44: HyperJaxb2

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/samplesagainst 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-derivedclasses, 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 arepath 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 equalsand 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-

Using Hyperjaxb

39

Page 45: HyperJaxb2

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 Hyperjaxbinternals. If not set, default configuration will be used. This is the extension pointallowing developers for cuztomizing the behaviour of Hyperjaxb, please do notmix it with the generated Hibernate configuration.

In the example above rt is set to RoundtripTest. This will make Hyperjaxb add an implementationof the roundtrip test case named RoundtripTest (this is fully qualified class name, so the class willbelong 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 theJaxbcommons project.

Troubleshooting Ant builds

Building Hyperjaxb2 projects with Ant may be quite uneasy since this process involves a relativelycomplex 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 classpathof the XJC task. Carefully check this class path - it must include all the libraries required by Hyperjaxbas well as the resource file META-INF/services/com.sun.tools.xjc.CodeAugmenter (inhyperjaxb2-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 usageUsing 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 generationwith 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>

Using Hyperjaxb

40

Page 46: HyperJaxb2

<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>

Using Hyperjaxb

41

Page 47: HyperJaxb2

<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 foryou.

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 insrc/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 themaven-jaxb1-plugin). Hyperjaxb2 own configuration elements are the following:

target (directory) Location of the target directory to output Hibernate mappings andHibernate configuration. By default mappings are written to theXJC'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 notspecified, not roundtrip test case produced.

resourceIncludes/include (file pat-terns)

Patterns of the files to be treated as resources. By default,**/*.hbm.xml and **/*.cfg.xml (Hibernate mapping andconfiguration).

hashCodeAndEquals(normal/extended/none)

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

Using Hyperjaxb

42

Page 48: HyperJaxb2

methods, but these methods will fail on structures with cycles.The extended mode generates a less performant methods alsosuitable for cyclic structures. Finally, the none disables the gen-eration of the hashCode() and equals(...) methods (notrecommended).

TODO: Generating/exporting the database schema withHyperjaxb and Hibernate

TODO

Run-time usage: working with objectsThis section demonstrates the run-time usage of Hibernate with JAXB-generated classes and mappingsproduced by Hyperjaxb.

Initializing JAXB context, marshaller and unmarshallerWith 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 JAXBcontext:

final JAXBContext context = JAXBContext.newInstance(packageNames);

In the code fragment above, packageNames is the list of schema-derived packages that JAXB hasgenerated 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().getName());

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.gml:net.opengis.ogc");

If you have a complex run-time environment with multiple classloaders, you may also need to specifythe 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

Using Hyperjaxb

43

Page 49: HyperJaxb2

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 youcan pool them if needed.

Unmarshallers are used to convert XML into an object structure. To unmarshal the XML, simply feedyour 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 streamsjavax.xml.transform.Results and java.io.Writers as targets.

Setting up the Hibernate session factoryIn order to work with Hibernate, you will need to configure the Hibernate session factory. If you did notturn of generaion of the Hibernate configuration, then factory set-up is trivial. First of all, take care ofcertain preconditions:

• Add JAR file with your classes/Hibernate mappings/Hibernate configuration to the class path ofyour 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 themappingDirectoryLocations:

<!-- TODO: Spring config. --><bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"><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>

Using Hyperjaxb

44

Page 50: HyperJaxb2

</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 objectssession.saveOrUpdate(myObject);

transaction.commit();session.close();

Importing dataImport 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 unmarshallerfinal Unmarshaller unmarshaller = context.createUnmarshaller();// Unmarshall the XMLfinal Object object = unmarshaller.unmarshal(xml);

// Open the sessionfinal Session saveSession = sessionFactory.openSession();// Save the unmarshalled object into the databasesaveSession.saveOrUpdate(object);// Get the idfinal Serializable id = saveSession.getIdentifier(object);

// Flush and close the sessionsaveSession.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 dataIn 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 sessionfinal Session loadSession = sessionFactory.openSession();// Load the objectfinal Object loadedObject = loadSession.load(object.getClass(), id);// Close the sessionloadSession.close();

// Create a marshallerfinal Marshaller marshaller = context.createMarshaller();// Marshall the objectmarshaller.marshall(loadedObject, xml);

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

Using Hyperjaxb

45

Page 51: HyperJaxb2

the database while get exits gracefully.

Executing queriesHyperjaxb imposes no limitation on querying your content objects with Hibernate - you may use HQLqueries 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 ofPurchaseOrder.

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 XMLSchema. 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 Smithfinal 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();

Using Hyperjaxb

46

Page 52: HyperJaxb2

Chapter 6. Extending HyperjaxbHyperjaxb is written with extensibility in mind. There is no single way to generate Hibernate mappingsfor 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 behaviourof Hyperjaxb using Hyperjaxb strategies.

Understanding Hyperjaxb strategiesTo 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 areseparated and put into two different classes. This allows you to switch the algorithm that you areusing at any time. There are several advantages to doing this. First, if you have several differentbehaviours 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 toadd, remove, or change any of the behaviours, it is a much simpler task, since each one is its ownclass. 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 arestrategies that generate mappings, analyze classes and fields, deal with customizations, define namingconventions and so on. Thus if you need to redefine some part of Hyperjaxb behaviour, you just replacecertain 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-faceorg.jvnet.hyperjaxb2.hibernate.mapping.strategy.principal.PrincipalStrategy). This principal strategy, in its turn, containes a number of further smaller strategies responsiblefor smaller specific functions. For instance, there is a naming strategy responsible for generation ofnames for tables and fields, strategies that generate class and field mappings, identifiers and versionsand 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 configurevia 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 thepricipal 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 youwant to override Hyperjaxb behaviour somehow:

1. Deside which strategy you need to change. Discussion of Hyperjaxb strategies is out of the scope ofthis 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

Page 53: HyperJaxb2

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

Extending Hyperjaxb

48

Page 54: HyperJaxb2

Chapter 7. Credits andacknowledgements

Hyperjaxb is developed by Aleksei Valikov with the help of many individuals providing test scenariosand 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