Return to Javelin home
© 2005. Step Ahead Software Pty Ltd. All rights reserved.
Table of Contents
This document discusses two technologies: Javelin and Hibernate and how they can now work together for a better world. (Well at least a better world for programmers)
Javelin is an intuitive, visual, full life cycle, modelling and implementation tool for object oriented development in Java. Design and coding is driven from a class diagram (with notation based on UML) that generates and updates underlying .java files on the fly without the need for explicit export/import operations. Use it in conjunction with your favourite IDE to facilitate your entire development process from design to delivery:
perform design related tasks and generation of persistence support artefacts in Javelin
perform implementation of methods in Javelin and/or your IDE
perform compiling, testing and debugging in your IDE.
With Javelin’s InSync code-model synchronization technology you can switch between Javelin and your IDE and back again in zero time – there’s no export/import phase. Did we mention that Javelin is tiny and blindingly fast? The initial release of Javelin was developed almost a decade ago so the user interface (UI) and code synchronisation engine had to perform fast on a 486 processor with 2MB of RAM! So you won’t have any noticeable performance hit when you leave Javelin running all day next to your IDE.
Hibernate, well you already know all about Hibernate and that is why you’re reading this. Suffice to say that Hibernate is an extremely popular and successful Object Relational Persistence service. In lots of ways Hibernate completes the Javelin picture as it enters its second decade of life: For ten years Javelin users have been developing via the “Model Driven Architecture” MDA but effective technologies for implementing persistence of those object models have been elusive. Persistence of any OO model has traditionally been hard work but with Hibernate, all that changes and the Javelin picture is complete.
Javelin’s Hibernate Persistence option automatically generates mapping files and other artefacts that are required inputs to the Hibernate persistence service. This makes the O/R mapping of the classes in a Javelin project virtually zero effort.
Most of the important Hibernate mapping options are available right there where you need them in the appropriate Javelin UI elements that can be accessed quickly via the class diagram. This is much more convenient and much less awkward that opening a class’ mapping file in a text editor, locating the appropriate tag and making a change. Javelin takes care of creating and maintaining your mapping files for you so you should never need to edit one manually ever again.
Hibernate support in Javelin has been implemented to a level whereby it is one of the most productive visual object oriented development platforms with automatic relational mapping in the universe (see disclaimer regarding the possible existence of other life forms who may have stumbled across object oriented software development before us). O/R Mapping with Javelin is fun because there’s not much to do. Javelin makes sensible decisions from the information contained in your object model to create the necessary mapping artefacts for Hibernate. Occasionally there are some times when customization would be desirable and that is allowed for in the Javelin model. Step Ahead Software are focussing their current efforts on implementing customizations at nearly every level of your model: class, attributes, inheritance and associations. For this reason we say that the Hibernate plugin is in beta.
While some of these customizations are already in place others are in progress though it should be reiterated that these are merely customization features used mainly for fine tuning or adopting certain formatting and so will not prevent Javelin from creating functional, efficient Hibernate mappings.
To turn on the hibernate persistence option for the classes in a Javelin class diagram:
*A note about Class IDs:
Classes will be automatically allocated IDs that are immutable (can't be changed) and unique within this class diagram. These are used by Hibernate to enable it to discriminate between objects of different class types at run time. Hibernate uses a discriminator field in the database when implementing inheritance. The value of each class ID is not important so long as it is immutable and unique across your system. The allocation range begins at the specified value. The first 100 ID’s in the range are reserved for system use. Choose the start range of different class diagrams in your system such that they don't overlap. eg., first class diagram - 1000, next class diagram 1200, next 1400 etc., leave a gap of at least 200 in each successive class diagram.
Javelin supports both persistent and non persistent classes. By default new classes are persistent. To make a class non persistent simply uncheck the “Persistent class” check box in the class details form.
With Javelin’s Hibernate plugin enabled the task of mapping the class in object models to automates the generation and maintenance of a set of Hibernate specific artefacts that . These artefacts include:
For each class a XML mapping file, compliant with the Hibernate 3.0 DTD, is generated. This is automatically updated whenever a class is added to or modified. This file contains, among other things an entry for each data member and each relationship marked as persistent in Javelin in the appropriate properties form. The filename is formed by classname.htm.xml and will be located in the same directory/package as the class’ java source file.
For each class that is not a subclass an identity attribute, called
‘id’ with private access and its accessor methods are generated in the class’
.java file. The id attribute and it’s getter and setter are not shown in the class
icon as they just add clutter – their presence is implied for any persistent
class. The identity attribute is not generated for subclasses because they
inherit the super class’ identity attribute.
[Although not mandatory Hibernate recommends the addition of an identity field to each class. Javelin implements this recommendation]
Javelin generates a Hibernate O/R Mapping file according to the following policies:
The name of the table representing a class will be the same as name of the class. For example: for a class named Employee Javelin will generate a mapping file specifying Employee as the name of the database table. Other table naming conventions will become available in future releases if developers request it.
The primary key field name will be the name of the class with the a lowercase first letter followed by the suffix ‘Id’. For example: for a class named Employee Javelin will generate a mapping file specifying employeeId as the primary key field.
The mapping file will specify “native” as the generator type for the id field. The id field is implicitly added by Javelin and should not be used by the application to represent any problem domain field so using increment as the generator type should not cause any problems to developers. If this becomes a problem for you project please let us know and we will make changed to Javelin to accommodate your needs.
Javelin’s Hibernate generator automatically maps your object oriented models, represented in the Javelin class diagrams, according to a combination of three mechanisms. The first two mechanisms are
Mapping via implicit “built in” rules.
Mapping based on persistence flags or options
These rules work fine for most projects. You can effectively perform pure object oriented modelling of the classes in your project and the relationships between them and let Javelin’s implicit mapping rules make smart decisions about which hibernate mapping options are appropriate for each component of your model.
The values of persistence flags or options, specified in the Javelin UI, for various components of the model (classes, attributes, relationships). These options let you change aspects of the implicit mapping rules from their default values.
The details of the explicit mapping mechanisms are given coverage in their own section later in this document.
The above two mechanisms in the Javelin mapping strategy satisfy most of the common mapping requirements “right out of the box”. Hibernate, however, provides a set of mapping directives that is of gigantic proportions, many of them only used in rare, specialized cases or when mapping to particularly clumsy legacy schemas. Obviously not every Hibernate mapping directive can be presented as an explicitly configurable option in the Javelin UI (nor would this be useful as it would clutter an otherwise very clean UI).
To accommodate mappings using Hibernate directives, not explicitly supported by Javelin by the first two mechanisms, a third mechanism is available: “Extra Persistence Directives”. This mechanism allows the developer user to specify, as free form text, extra code to be inserted into the mapping file(s) in various places.
The extra persistence directives can be configured in various UI components in the Javelin UI. They contain a header and/or body section that allow freeform text input. Text entered in the header section will be added to the corresponding tag’s header. An example of an extra persistence for a class follows. The same pattern applies to the mapping of other entities in the Javelin UI also.
<class . . . extraHeaderDirectives >
Text entered in the body will be added prior to the closing token for example:
. . .
All appropriate Javelin entities support extra persistence directives. They are listed below with directions on how to access them and their effect.
Project, persistence code generation engine (obviously only when Hibernate is selected as the persistence technology).
Main menu: Options|Persistence
Directives will appear in the <hibernate-mapping> tag in the mapping file of all classes in the project. Use this for project wide options.
Right click on desired class, choose “Details…”
Directives will appear in the <class> tag of the class’s mapping file.
Right click on either end of a relationship, choose “Reference details”
Directives will appear in the <many-to-one>, <one-to-one> or whatever tag is used to implement the relationship.
Right click on desired class and choose “Inheritance…”
Directives will appear in the tag used to map the inheritance relationship.
Data Member/ Property/ Attribute/ Instance Variable (many names have arisen over the years but they all essentially refer to the same thing!)
Right click on desired class, choose “Members”. Double click on desired data member.
Directives will appear in the <property> tag after the explicitly supported directives. The <property> tag differs from the others by not having a body.
When generating a Hibernate mapping file Javelin makes intelligent mapping decisions based on information that it obtains from your design.
Before we start discussing the mapping of associations we need to introduce, for those who have not heard of it before, the term “cardinality”. Some prefer to use the term multiplicity instead of cardinality but they essentially refer to the same concept: the potential number of entities that may exist on one end of an association relationship. Given that an association relationship always involves two classes we always have two cardinalities for each association relationship.
Examples of cardinality are:
A cardinality of 0..1 means that there can be exactly 0 or 1 entities on that end of the relationship.
A cardinality of 1..m means that there is at least 1 entity and possibly many entities on that end of the relationship.
An association in Javelin is anchored to its associated classes via two “cardinality anchors” – one at each end of the association. These are configured by right clicking at the end points of the relationship and choosing Reference Details. The options configured for each cardinality anchor in an association determine how Javelin maps the association.
For each cardinality anchor you can configure the following:
Role name - this becomes the name of the property that implements the relationship in the Java class. It is also used to form the column name (by appending ‘Id’) in the mapping file.
Cardinality – this can be either 0..1, 1, 0..m, 1..m. With four cardinality combinations available at each end of a relationship you can describe a wide variety of one-to-one, one-to-many, many-to-one and many-to-many. Cardinalities values of 1 and 1..m dictate that there is at least 1 entity on the other side of the relationship and cause Javelin to add the not-null=“true” constraint.
Ownership – this can be ‘none’, ‘uses’ or ‘contains’. If either end of a relationship is ‘none’ then the relationship is unidirectional otherwise the relationship is bidirectional. If one end is ‘contains’ then the contained entities will be deleted when the owning entity is deleted. In the Javelin class diagram these are shown as a diamond icon next to the owning entity. The mapping of associations using ‘contains’ will include the cascade=all option. The mapping of associations using ‘uses’ will leave cascade unspecified (which defaults to none) so that the developer can customize the cascading if required via the extra persistence directives. eg., a developer might add an extra directive: cascade="persist,merge,save-update"
Extra persistence directives – these additional directives will be added to the header and/or body, as appropriate, of the tag that Javelin uses to map this end of the relationship.
Many-to-one and many-to-many relationships are implemented using a joining table. This represents good relational database practice for many-to-one relationships and is unavoidable for many-to-many relationships.
Most of the examples in the Hibernate documentation form the table name by concatenating both class names in the relationship. This is fine for examples but in practice this could result in table name clashes if there is a need for multiple joining tables representing relationships between the same two classes. To avoid this type of name clash Javelin forms the name of joining tables from the role names if available or the class name if not. Multiple many-to-many relationships between the same classes must have different names for the Java source to be compilable. The role name are easily changed in Javelin to accommodate this.
Javelin uses the “table per subclass” strategy to map inheritance. All subclasses classes are mapped in their own separate mapping file with an “extends” reference to the super class (which is map in its own mapping file).
Currently containment via the <component> mapping is not explicitly supported. To work around this limitation simply use an association relationship in Javelin or turn off code generation for that individual relationship and add the appropriate extra persistence directives to the class to map the component yourself.
The developers of Javelin use agile, incremental development processes so we are continuously improving the product to meet our users’ needs. If there is sufficient demand from users to add explicit support for a particular Hibernate directive not yet supported explicitly in the UI then we will add support for that option in a timely fashion. You just have to let us know via our web site, ok!