This tutorial uses the example code from the Quick Start page to demonstrate how to do basic RevGen configuration.
Open the RevGen properties file located under src/revgen/revgen.properties. All the configuration in this tutorial will be done editing this file.
For each step you will change the properties file and regenerate using:
mvn hsql:start revgen:revgen
Tip: you can use ant clearall to remove ALL source code directories between steps in this tutorial. Be careful not to zap any hand-coded artifacts!
The first thing you'll probably wish to do is change the base package name.
One thing to be aware of is that package names are shared by artifact emitters and templates, so they serve as both file paths and Java package names. Always use the forward-slash notation and RevGen will do the package dot notation conversion for you.
basePackageName=org/acme/myplace
Many database schemas use plural names, but class names are usually in the singular. To have RevGen convert them for you set:
pluralTableNames = true
By default RevGen uses the target class name as the basis for property names when converting from foreign key constraints to class references. Because this example uses a single table with several self-referential relationships, we end up with meaningless property names in our Person.java class:
@ManyToOne(cascade = {})
@JoinColumn(name="MOTHER_ID", referencedColumnName="ID")
protected Person person;
@ManyToOne(cascade = {})
@JoinColumn(name="FATHER_ID", referencedColumnName="ID")
protected Person person2;To have RevGen use foreign key columns as property names set:
referenceNamingStrategy = useFkColumn
This setting results in motherId and fatherId property names:
@ManyToOne(cascade = {})
@JoinColumn(name="MOTHER_ID", referencedColumnName="ID")
protected Person motherId;
@ManyToOne(cascade = {})
@JoinColumn(name="FATHER_ID", referencedColumnName="ID")
protected Person fatherId;Better... but now we have another problem: our names have 'Id' suffixes in them:
Not to worry, we can use regular expression renaming to clean this up:
regexReplacePairs = ^(father|mother)Id$>$1
This is a little cryptic, but it consists of a regular expression and a replacement pattern separated by the '>' symbol. In this case $1 is replaced with the first regular expression group (i.e. the text in the first set of parentheses) which is a string matching either mother or father.
See Regex Tutorial if this is all new to you.
You can have multiple regular expression, replacement pattern pairs separated by commas. To clean our names up further, let's change persons to children:
regexReplacePairs = ^(father|mother)Id$>$1,^persons$>children
As a little background investigation for the next step, have a look at the serialized model which can be found in: target/revgen-metadata.xml
It contains both the database model and the reverse engineered class model.
Having an externalized model representation allows you to:
Let's take advantage of this to customize RevGen's output...
By default RevGen generates bidirectional relationships. By setting the navigable property of Reference on one side of the relationship to false, you can specify a unidirectional relationship.
There is an empty XML model file provided for just such purposes located under src/revgen/merge-metadata.xml:
<model id="root">
<database id="db:DATABASE">
<!-- table metadata goes here -->
</database>
<!-- class metadata goes here -->
</model>As the name suggests, any model data from this file will be merged with data generated by RevGen. By cutting-and-pasting from target/revgen-metadata.xml, you can easily customize just about anything in the model. You just have to be careful to preserve the IDs, so that the two models can be matched up.
The children2 side of the father-to-children2 relationship is redundant, so lets drop it and make a unidirectional relation by modifying src/revgen/merge-metadata.xml to look like this:
<model id="root">
<database id="db:DATABASE">
<!-- table metadata goes here -->
</database>
<!-- class metadata goes here -->
<class id="oo:Person">
<reference navigable="false" id="oo:Person.children2"/>
</class>
</model>Assuming you've renamed persons to children, RevGen will match the merge node with the oo:Person.children2 ID with the generated model's node and set navigable to false.
One advantage of using code generation is that it is relatively easy to swap one technology for another.
Three flavors of DAOs (Data Access Objects) are currently supported:
DAO implementation is selected by setting the daoImplType property to jpa, spring or hibernate respectively. For example:
daoImplType = spring
Round Tripping refers to the ability to freely mix hand written and generated code throughout the development process.
By default RevGen generates a single model class for each entity, but it can be configured to generate two classes:
extensionByInheritance = true
genEntityNameTemplate = #{modelName}GenThis is called extension-by-inheritance and results in a empty class being emitted that looks something like this:
public class Person extends PersonGen { ... }The second Person class can be extended with hand-written code without interfering with the generated class, PersonGen.
If you've made all the changes discussed here, your revgen.properties file should look like this:
basePackageName=org/acme/myplace
pluralTableNames = true
referenceNamingStrategy = useFkColumn
regexReplacePairs = ^(father|mother)Id$>$1,^persons$>children
daoImplType = spring
extensionByInheritance = true
genEntityNameTemplate = #{modelName}GenThe resulting code is cleaner and more concise than what you started with:
TODO paste code in
This is just the first level of RevGen configuration. You can completely reconfigure the code generator without re-compiling by tweaking the RevGenSpringConfig.xml file. See the User's Guide for an explanation of this and other capabilities.