|
AXgen and OJB |
|
|
AXgen was designed to facilitate generation of java classes and configuration files for use with
OJB (http://db.apache.org/ojb). The following explains some
configuration and modeling concepts AXgen for OJB relies on. |
|
|
Please keep in mind that the following guide describes just one possible usage of AXgen and just
one possible modeling strategy for OJB. If you feel that it does not fit your needs, consider enhancing or
replacing our templates and classes. |
|
|
Templates and generated files |
|
|
AXgen uses the following templates to generate OJB related files:
- OjbInterface.vm
- Used to generate interfaces for each modeled entity (classes and interface).
- OjbClass.vm
- Used to generate persistent classes for each modeled entity (interfaces only).
- OjbAbstractAddOn.vm
- Used to generate abstract add on superclasses for each modeled entity (classes only).
Used to abstract common behaviour away from add on implementations.
- OjbAddOn.vm
- Used to generate add on classes for each modeled entity (classes only). The real
persistent class delegates to this class for user defined behaviour.
- OjbRepository.vm
- Used to generate the OJB repository. Only the repository_user.xml part is generated.
- OjbDdl.vm
- Used to generate a DDL script to set up the database.
|
|
|
The following figure illustrates how the four java classes/interfaces
generated for each entity integrate to a class hierarchy. |
|
|
 |
|
|
Each entity implements a common interface (AXentity). Four classes are
generated for each entity class, only the interface is generated for entity interfaces.
The SuperXXX classes are added to illustrate the inheritance hierarchy. |
|
|
Configuring the ANT job for use with OJB |
|
|
Of course you may configure the ANT job as described in the Use
AXgen section. But, at you convinience, you may use the AXgenOjb task instead of the AXgen task. This
specialized task is the same as the standard AXgen task with some predefined generate subtasks for use with
our OJB templates. Furthermore AXojbHelper.class is used as default helper class |
|
You ANT build file could look like the follwing: |
|
...
<path id="axgen.path">
<fileset dir="${axgen.lib.dir}">
<include name="**/*.jar"/>
</fileset>
</path>
<taskdef name="axgen" classname="de.armax.ax.devtools.generator.AXgenOjb">
<classpath>
<path refid="axgen.path"/>
</classpath>
</taskdef>
...
<axgen>
... <!-- global axgen configuration -->
<check/>
<generateInterface/>
<generateClass/>
<generateAbstractAddOn/>
<generateAddOn/>
<generateRepository/>
<generateDdl/>
</axgen> |
|
|
Please refer to the API docs and
the Use AXgen section for more details on the generate shortcuts
and the general syntax of the AXgen task. |
|
AXojbHelper |
|
|
The helper class registered with the AXgenOjb task is AXojbHelper, as long as you do not
specify another helper class. It uses its own properties file (ojbhelper.properties), that must be located
in the same directory than the ANT build.xml file. The following section briefly descibes this property file.
An example axojbhelper.properties can be found in the example directory. All entries are commented so it won't
be to hard to understand. |
|
AXojbHelper is mainly used for type conversion. If you wish to use any non standard type,
you need to register this type in ojbhelper.properties, possibly along with an OJB field-conversion class. |
|
The following defines that the foo.bar.Duration type is mapped to the JDBC type BIGINT and
that the conversion class to be used is foo.bar.conversions.DurationToLongFieldConversion. |
|
##
## JDBC TYPES
##
# User defined Mapping between java types and JDBC types. Typically used to map
# a custom class to an existing JDBC type. In this case you need a conversion class,
# see section below.
#
# You may also use this to override the default JDBC <-> Java mapping.
#
# The keys consist of the prefix jdbc.type followed by a slash and the fully
# qualified name of the java type.
# The values should be legal JDBC types.
#
#
jdbc.type/foo.bar.Duration = BIGINT
##
## CONVERSION CLASSES
##
# Define ojb field conversion classes for Java/JDBC type pairs. Typically used to
# define a conversion class for a custom class/JDBC Type mapping which has been defined
# in the section above.
#
# The keys consist of the prefix conversion.class followed by a slash, the fully
# qulified name of the java type, a second slash and the JDBC type to convert to
# The values are fully qualified names of OJB field conversion classes
#
#
conversion.class/foo.bar.Duration/BIGINT = foo.bar.conversions.DurationToLongFieldConversion |
|
Additionally, the ojbhelper.properties file contains some database specific type
conversion iformation an syntax specifications. Finally there is a section defining which tagged values
are allowed for which kind of element. This is used by the model checker to produce warnings for illegal
tagged values. |
|
Modeling entities |
|
|
You need to create one model class/interface for each entity. An interface is either a UML
interface or a UML class with stereotype <<interface>> (we need this, because we may whish to model
interfaces with attributes). See the inheritance section for details on inheriting
from superclasses or interfaces. |
|
|
Each persistent field is modeled as an attribute in the UML type. Do not model the
accessors (setter and getter) as operations. AXgen will generate these methods on its own. Each entity implicitely
inherits the unique id field "oID" as well as the lock fields "lockTimestamp" and
"lockUser" from the common interface AXentity. So your modeled entities must not contain these
attributes. |
|
|
Make sure that you model attribute type correctly. They need to be fully qualified. Consequently,
you should e.g. create the package java.lang with the String type if you wish to use java.lang.String as attribute
type. Primitive Java types must be located in either the java.lang package or the model root package. We encourage
you to use object types instead of Java primitive types (as they presevere null values and are easier to manager
when using reflection) but primitive types will work as well. |
|
|
The modeled attributes are mapped one to one to database columns. If you need more complex
attributes or operations you may define them in the UML type and implement them by hand later on. This is where
the AddOn classes come into play. You may either model attributes with stereotype <<abstract>>, in which
case AXgen generates getter and setter method stubs to be implemented by hand, or you may model any operations
that will equally result in the according method stubs. The advantage of abstract attributes towards operations is
that an abstract attribute results in exactly the same interface as an ordinary (persistent) attribute, including
property change listeners and static define variables for the property name whereas the advantage of operations is
greater flexibility (arbitrary argument lists, ...). |
|
|
As you implement the AddOn classes by hand, you should not overwrite them by later generation runs.
We suggest to generate all source into a separate directory and copy *AddOn.java files to your working dir only if
they do not already exist. The add-on implementation inherits from an abstract add-on class declaring all method
stubs as abstract methods. This way you can use an Java IDE to generate missing methods in your add-on implementation
class. |
|
|
The AXgen OJB templates use stereotypes and tagged values to specify specific
information (e.g. cascade behaviour, type conversion, etc.). |
|
|
Stereotypes for UML types |
Stereotype |
Meaning |
<<interface>> |
Declares a type as an interface. |
<<transient>> |
Used to exclude type from code generation (e.g. to use them as return type or
attribute type). |
<<reference>> |
Declares a type as a reference to another model (see Writing
Models). |
|
|
|
Tagged values for UML types |
Name |
Description |
Default |
table |
The table name |
The type name |
colPrefix |
The column prefix to use for all columns in the table for this type |
The first three characters of the type name (converted to lower case) |
|
|
|
Stereotypes for attributes |
Stereotype |
Meaning |
<<abstract>> |
Declares an attribute to be a complex attribute with getter and setter
implemented in the add-on class. |
|
|
|
Tagged values for attributes |
Name |
Description |
Default |
length |
The length of the db-column (where it applies). |
50 |
db-column |
The database column to map this attribute to. |
The name of the attribute. |
db-type |
The database column type. |
The JDBC type corresponding to the attribute type. |
|
|
|
Modeling associations |
|
|
Use UML associations to model associations between two entities. The standard
properties of the UML associations result in just what you expect in the generated files. AXgen
generates acessor methods for associated entities automatically, consequently you must not model
these accessor methods. |
|
|
The OJB templates distinguish to-1 and to-N association ends (multiplicity 0
and 1 are both treated as to-1 association ends, 0..* and 1..* are both treated as to-N
association ends). For to-1 association ends, a getter/setter pair is generated at the other end,
for to-N association ends, there are five accessor methods: addXXX, addAllXXXs, removeXXX,
removeAllXXXs and getXXXs. |
|
|
The name of the association property in the generated entity classes will be
the name of the association end (if any) plus the name of the associated entity plus a plural 's'
if it is a to-N association. Of course, if an association is modeled unidirectional, there will
be neither public association attributes for the non navigable direction nor accessor methods. |
|
|
If an association is modeled as a composition, this translates in delete cascading
(auto-delete="true" in the OJB reference-descriptor). You can achieve update cascading by
adding a dependency with stereotype <<autoupdate>> between the two associated entities
(update will be cascaded from the dependency supplier to the dependency client). The dependency needs
to have the same name as the association end at the dependency client side. |
|
|
You may model M:N associations directly. Our templates will manage the creation
of the indirection table needed at the RDBMS level and the necessary configuration in OJB. |
|
|
Please have a look at the example for some more hints on associations. |
|
|
Modeling inheritance |
|
|
Since version 2.0 of AXgen, our templates support mapping inheritance. Two types
are supported: inheriting from interfaces and inheriting from superclasses. RDBMS systems do not
support inheritance directly, though different strategies exist how to map inheritance to RDBMS.
Please refer to the OJB manuals for details
on supported strategies. |
|
|
We choose the table per concrete class strategie, i.e. each class has its own table
with all attributes (inherited from other classes or not). This strategy is especially usefull when
queries are most oftenly performed on the subclass and rarely on the super type. In fact, using this
strategy, the RDBMS relations do not reflect the inheritance hierarchy at all, but all inheritance
handling is done at OJB level. |
|
|
Simply model the abstractions/realizations and generalizations/specializations in
your UML model. Do not add inherited attributes, operations or associations to the inheriting type. Let's
say you model Superclass and Subclass, Subclass being a specialization of Superclass. So all attributes,
operations and associations defined in Superclass are implicitely defined in Subclass. You must not
remodel them. |
|
|
As the model will result in Java classes, each class may have at most one superclass
(but it may implement more than one interface). |
|