Hibernate is an open-source object/relational mapping tool for accessing relational databases from Java applications. JavaGen allows you to specify your object model in UML and generate high-quality Java source containing Hibernate-specific XDoclet mapping tags.
This guide focuses on JavaGen-specific techniques for transforming UML class diagrams to persistent object models and assumes proficient knowledge of UML, Hibernate, Java and XDoclet. See references for excellent, more general sources on these topics.
JavaGen generates Java source code decorated with XDoclet tags:
/**
* @hibernate.class
* table="CUSTOMER"
* schema="SALES"
*/
public class Customer
{
/**
* @hibernate.id
* generator-class="assigned"
*/
public String getId() { return id; }
...XDoclet is also a primary means of customizing the generated code.
You can modify the generated code and mappings by attaching @hibernate
XDoclet tags in the UML at the class, attribute or association levels. JavaGen passes through
whatever is present in the UML (including source code in method bodies) only generating
what is necessary to produce a working Hibernate mapping
(see Customization).
In order to map classes to database tables, JavaGen must know which classes to make persistent.
There are two UML stereotypes for achieving this, <<entity>> and <<entity-value-object>>
corresponding to the two different ways Hibernate maps classes: entities and components of entities.
<<entity>> StereotypeClasses marked with the <<entity>> stereotype are mapped to their own tables with their own
primary keys. Entities have independent life-cycles and have few restrictions on the
types of relations they can form with other entities. Entities must have a unique primary
key. If you do not define one, JavaGen will add a private primary key property for you.
Here is a simple entity class (TODO: update the stereotype in this diagram):

which is mapped to a database table that looks something like this:
+-------------------------------------------------------------------+ | customer table | +------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+----------------+ | id | int(11) | | PRI | NULL | auto_increment | | name | varchar(255) | YES | | NULL | | +------------+--------------+------+-----+---------+----------------+
<<entity-value-object>> StereotypeClasses marked with the <<entity-value-object>> stereotype are mapped to value objects
by JavaGen. A value object can be persisted as a Hibernate component, but cannot exist
in the database independently of its owning entity, nor can it have true relations with other objects.
The following UML diagram illustrates two equivalent representations (Parent1 and Parent2) of a one-to-one relation between an entity and value object (TODO: update the stereotype in this diagram).

Whichever representation is chosen the results are the same; Hibernate maps all the value object attributes into the entity table roughly as follows:
TODO show SQL table
Value objects can be nested to any level with the only limitation being only one level of one-to-many mapping is allowed (eg one-to-many relation cannot contain a nested one-to-many relation).
By default JavaGen does not emit table names. Hibernate provides a more flexible way to achive this using the NamingStrategy interface. To turn on table name generation set:
javagen.hibernate.generate.sql.names="true"
You can set a table name on a specific class with a UML Tagged Value, for example:
@hibernate.class
table="CAT_TBL"(Currently not tested or supported)
JavaGen will try to infer the best mapping based on the UML model. As usual you can override
JavaGen by specifying the @hibernate.class, @hibernate.subclass and
@hibernate.joined-subclass XDoclet tags as UML tagged values on the class.
The three types of inheritance supported by Hibernate are:
| Inheritance | Description |
|---|---|
| Table per subclass | This is the default JavaGen mapping between <<entity>> classes resulting
in the joined-subclass Hibernate mapping. |
| Table per concrete class | JavaGen generates this mapping when each concrete class in an entity hierarchy has a
@hibernate.class tagged value. |
| Table per class hierarchy | To specify this mapping define a discriminator name for each UML generalization in
the hierarchy. The discriminator name becomes the value placed in the discriminator
column defined in the super class.
The alternative technique is to explicitly define a @hibernate.subclass
tagged value with the discriminator-value attribute assigned to each subclass.
You'll also need to specify the @hibernate.discriminator tag and
column attribute on the super class. |
UML attributes usually correspond to Java fields or properties, which in turn are mapped to columns in the database.
JavaGen will map attributes to Java properties, unless they are static,
transient or marked with the <<field>> stereotype.
JavaGen automatically generates get and set methods for properties unless they are frozen
(read-only) or addOnly (write-only). Likewise, if either a get or set property method is
found JavaGen will only generate absent XDoclet tags.
Because XDoclet tags are attached to the get method, JavaGen must generate a private getter method for write-only properties to hang the tags on.
Primary keys are properties that uniquely identify rows in a database.
Entity tables must have a primary key, if no key is declared JavaGen, will create a
private syntheticId property as a java.lang.Integer.
JavaGen generates primary key mappings based on the following UML stereotypes:
| Stereotype | Description |
|---|---|
| <<synthetic-key>> | Synthetic keys are generated by the database and must be integer types: (short, int, long,
java.lang.Short, java.lang.Integer or java.lang.Long).
By default JavaGen emits:
@hibernate.id
generator-class="native"nativevalue delegates the key generation decision to Hibernate which in turn picks identity,
sequence or hilo based on the selected database.
This setting reportedly does not work well with some databases. It can be specified per-class using XDoclet tags
or globally using the following property:
javagen.hibernate.default.generator.class="hilo" java.lang.String or primitive wrappers) to avoid these issues.
|
| <<primary-key>> | This primary key type is often called a natural key (think social security number) and must
be supplied by the user or application. JavaGen emits the following for this stereotype:
@hibernate.id
generator-class="assigned" |
| <<business-key>> | Not a real primary key from the database point of view, JavaGen includes properties with this
stereotype when overriding the equals and hashCode methods. This is necessary in
situation where new entities (who's primary key are null) are in a mixed collection. In such
cases so-called business keys must be used to establish equality and this stereotype helps
JavaGen streamline the implementation of these two methods.
|
For one-to-one primary key type relations (i.e. when no foreign key is involved) JavaGen emits the
foreign generator type (see constrained relations).
Finally you can override the type of primary key emitted by attaching an XDoclet attribute to the property as a UML Tagged Value. For example:
@hibernate.id
generator-class="identity"| Don't use attributes to represent associations | UML attributes should map to simple Java types; in other words Java value
types that have a Hibernate mapping type defined. Java collection types
(Collection, Set, Map, List, etc.) should always be specified using associations.
(How else are you going to specify what type the collection contains?)
Likewise, JavaGen will complain if you define an attribute using an <<entity>>
type because this is really a one-to-one association.
|
|---|---|
| Transient and static attributes are not persisted | Following Java semantics, transient associations are not stored in the database. Nor does it make sense to store static attributes. |
| Avoid Java Arrays | JavaGen supports one-dimensional arrays of simple types, but you get better performance and more control if you model arrays as associations. |
Fine-grained modeling is encouraged in Hibernate and you may nest POJOs (plain old Java objects) as deep as you wish with the only restriction being composition collections cannot contain nested collections. The nested POJO attributes are mapped using composition (i.e. by flattening the object tree into a single table).
By default JavaGen does not emit column names. Hibernate provides a more flexible way to
achive this using the NamingStrategy interface.
javagen.hibernate.generate.sql.names="true"
You can specify a column name on a specific attribute by attaching either of the following XDoclet tags:
@hibernate.property
column="FIRST_NAME"or
@hibernate.column
name="FIRST_NAME"TODO: explain the duplication above.
Labeling a property with the <<order-by-asc>> or <<order-by-desc>> stereotypes
results in the order-by="column_name asc|desc" Hibernate mapping and Java collection
types that behave like LinkedHashMap, LinkedHashSet and LinkedHashList.
If the SQL column name is not the same as the property name you need to specify this mapping using XDoclet tags, for example:
@hibernate.set
order-by="purchase_date desc"Primary keys are always mapped as not-null="true". You can specify this on non-key properties by setting the multiplicity to '1'. By default nulls are allowed which corresponds to a multiplicity of 0..1 (or no value in Poseidon).
UML Associations should generally be used between <<entity>> classes
(i.e. classes that have primary keys). Associations can be one-to-one, one-to-many,
many-to-one or many-to-many. In most cases JavaGen will generate an appropriate mapping,
but you can customize the results by attaching XDoclet tags on the association ends
as UML Tagged Value pairs.
It is good practice to name your association ends, as this results in higher quality generated code with more meaningful property, method, column and table names. If no name is found on an association end JavaGen uses the class name - which works most of the time. However, in situations were you have multiple relations between the same two entities or relations to a single entity (i.e. self referential relations) you will encounter naming conflicts if you do not assign unique names to the association ends.
Optionally, you can use singular or plural names to reflect the cardinality (one or many) of the relation end.
JavaGen does not support association classes. It is easy to work around this limitation by making the association class an entity and using two one-to-many associations for either side. Because JavaGen achieves its Hibernate mapping using XDoclet tags, any limitations in XDoclet limit JavaGen's capabilities (NEED SPECIFICS).
There are two categories of one-to-one associations:
| Key | Description |
|---|---|
| Foreign Key | This is the default one-to-one mapping and is between a foreign key in one table and a primary key
in the other. JavaGen picks the foreign key end based on visibility and efficiency constraints. To explicitly
specify foreign key placement, attach the following XDoclet tag to the desired association end:
@hibernate.many-to-one
foreign-key="MY_FK"@hibernate.many-to-one tag is significant to JavaGen,
the attribute can be anything - noop='ignore' would work as well.
|
| Primary Key | These are relations in which the primary keys have the same value and are specified using a constrainedrelation end. To specify this in JavaGen add the following XDoclet tag to the constrained association end: @hibernate.one-to-one
constrained="true" |
One-to-many associations are generated true to their UML representation:
java.util.Set is the default container for unordered
association ends and
java.util.List is used for ordered association ends.
Other container types can be specified using XDoclet tags.composition will generate parent/child relation with cascading update
and delete behavior.Unidirectional and bidirectional relations are set with the
navigable setting.* cardinality generate NULLABLE foreign key mappings whereas
1..* ends generate NOT-NULL foreign key mappings.Many-to-many associations result in a third association table
being generated,
otherwise they are similar to one-to-many associations. If you need more control over
the mapping details, many-to-many associations can be modeled as two one-to-many associations
with a common association
class in the middle.
JavaGen will generate the appropriate Java collection class based on the UML settings specified. Other collection types can be specified using XDoclet tags.
| Class | Description |
|---|---|
| java.lang.Set |
java.lang.Set is the default class generated for
manyended unorderedassociations. Hibernate limits the members to non-null values. |
| java.lang.List | The List interface is generated for ordered manyended UML associations. An index column ( @hibernate.collection-index) is generated to maintain list order.
|
| Bag | There is no way to specify bag semantics in UML (at least in a standard way) so
you must place the @hibernate.bag XDoclet attribute on the correct association end.
At the time of this writting |
| java.lang.Map | Use the @hibernate.map XDcolet tag or parameterized associations. |
| Java arrays | You must place @hibernate.array or @hibernate.primitive-array
XDcolet tags in your UML to generate an arrays in JavaGen.
|
JavaGen is best used when generating database schemas form object models verses working backwards from the database schema. If your working with an existing database, you'll want to convert the database schema to UML before proceeding or use an alternate tool such as MiddelGen (see Tools for Hibernate).
XDoclet imposes a few limitations on some
of Hibernate's more exotic
mapping types, however one can usually achieve the desired
result using other techniques. An XSLT template is provided in the JAM build to
correct a few minor bugs with XDoclet and more importantly can serve as the basis for
custimizing your mapping files.
Currently only XDoclet 1.2.2 is supported. The Hibernate module in XDoclet 2.0 uses slightly different tag names and is not supported for the time being. A persuasive request from a loyal user could change this ;-)
| Stereotype | UML Element | Description |
|---|---|---|
| <<entity>> |
Class
| Generates a Hibernate entity mapping. See entity |
| <<entity-value-object>> |
Class
| Generates a Hibernate component mapping. See entity-value-object |
| <<synthetic-key>> |
Attribute
| Generates a auto-increment primary key mapping. See synthetic-key |
| <<primary-key>> |
Attribute
| Generates a primary key mapping. See primary-key |
| <<business-key>> |
Attribute
| Generates a special equals and hashCode methods. See business-key
|
| <<order-by-desc>> |
Attribute
| Generates a order-by="column_name desc" mapping. See order-by-desc
|
| <<order-by-asc>> |
Attribute
| Generates a order-by="column_name asc" mapping. See order-by-asc
|
Set these properties in your build.xml or props-javagen.xml file:
| Property | Default | Description |
|---|---|---|
| javagen.hibernate.flag |
false
| Switch that turns on hibernate module, set to true to activate. |
| javagen.hibernate.generate.sql.names |
false
| Set to true to have JavaGen generate table and column names. |
| javagen.hibernate.default.generator.class |
native
| Specifies the default generator class to use. |
| javagen.hibernate.version |
2
| Specifies the Hibernate version to generate for. Valid values are 2 or 3. |
Due to a few API changes Hibernate 3.x is not compatible with Hibernate 2.x code. By setting
<property name="javagen.hibernate.version" value="3"/>
JavaGen will generate Hibernate 3.x compatible Java source code.
Alternatively, you can develop in 2.x and upgrade to 3.x latter. Upgrading is trivial because JavaGen generated entity classes work without change and non-entity DAO (Data Access Objects) classes only require the following changes:
net.sf.hibernate to org.hibernate and net.sf.hibernate.expression with
org.hibernate.criterion.session.delete("FROM Orders") statements with session.createQuery("DELETE FROM Orders").executeUpate().HibernateException from method signatures. FetchMode.LAZY and FetchMode.EAGER with FetchMode.SELECT and FetchMode.JOIN.As a temporary measure, JAM provides a XSLT stylesheet
that updates mapping files generated by XDoclet from Hibernate 2.x to 3.x. To activate this
transformation set the following property in your build.xml file:
<property name="hibernate.mapping.stylesheet" location="${jam.home}/xsl/hibernate3Upgrade.xsl"/>If you're not using JAM, you can obtain the above stylesheet for JAM's CVS repository.
UML, Java, XDoclet and relational databases all have their own terminology for
describing overlapping concepts or in some cases the same word for different concepts.
The most confusing term is attribute
which is used in UML to describe a field or property
and in XDoclet to describe a meta-data key/value pair. We use the term
both ways depending on the context.
UML terms are also unfamiliar to many people. Common UML terms and how they relate to Java and database concepts are as follows:
| UML | Java | Database |
|---|---|---|
| Class | class | table |
| Attribute | property/field | column |
| Association | reference | relation |
| One-to-one Association | one-to-one reference/pointer | one-to-one relation |
| One-to-many association | collection/array | one-to-many relation |
| Generalization | inheritance | (no equivalent) |
| Abstraction | implementation | (no equivalent) |
| Association End/Role | reference (get/set methods) | relation name |
| Composition | life cycle dependency | cascading deletes |
| Aggregation | ? | ? |
| Navigable | public accessors | reference navigation |
| 1 Multiplicity | required field | NOT NULL |
| 0..1 multiplicity | optional field | NULLABLE |
| Changeability | read-write access | ? |
| <<Entity>> | persistent object | table with primary key |
| transient | transient | no column defined |
Finally Hibernate has its own terms of which some of the more confusing are:
foreign-key-associationbecause it maps a relation with a foreign key. It is actually used to map both
one-to-one and many-to-one relations!