• No results found

Guiding the reverse-engineering process

In document Manning.seam.in.action.sep (Page 93-96)

Putting seam-gen to work

2.5 Show and tell, change, and repeat

2.5.2 Guiding the reverse-engineering process

Hibernate’s reverse-engineering tool is very capable of interpreting what the database schema has to say about the entity relationships. But it can’t read what is not there and it can’t do much about poorly named columns. For example, the property for men’s par on the Hole entity is mPar, which is a rather cryptic name. The relative position of a tee set is represented by the pos property on the TeeSet entity, another name lack-ing clarity. These names are a reflection of abbreviated column names. As the saylack-ing goes, “garbage in, garbage out.” What’s worse is the situation where the information isn’t in the database at all. If a foreign key is missing in the table, seam-gen can’t make the leap that the table is related to another. Thus, the corresponding entities won’t be linked and that means you won’t get any of the support in the UI that you observed during the walkthrough.

Both of the shortcomings just cited can be corrected by tuning the Hibernate reverse-engineering configuration. Despite its long, foreboding name, the configura-tion is quite straightforward. Its purpose is to tweak the decisions made by seam-gen when generating the entity classes. These adjustments then affect all the downstream UI code generation. Using the reverse-engineering configuration, you can make any of the following adjustments:

Customize a property name on an entity class

Customize the Java type of a property on an entity class

Change the mapping between SQL column type and Java property type globally

Exclude tables from participating in code generation

Establish an entity relationship that isn’t represented by a foreign key

Exclude the reverse mapping of an entity relationship

Enable generation of the toString() and hashCode() methods

Add extra code and imports to the generated class

Let’s apply customization to clean up the prototype application using the <table> ele-ment. This element can be used to fix the problematic property names as well as add some convenience methods to the entity classes that will be useful later on. The reverse-engineering configuration file that seam-gen uses is resources/seam-gen.reveng.xml inside the generated project. Listing 2.4 shows the contents of this file populated with the customizations just mentioned.

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-reverse-engineering SYSTEM

"http://hibernate.sourceforge.net/hibernate-reverse-engineering-3.0.dtd">

<hibernate-reverse-engineering>

<table name="HOLE">

<column name="M_PAR" property="mensPar"/>

<column name="L_PAR" property="ladiesPar"/>

<column name="M_HANDICAP" property="mensHandicap"/>

<column name="L_HANDICAP" property="ladiesHandicap"/>

</table>

Listing 2.4 Customizes property names of entity classes and adds extra methods

Customizes the HOLE table mapping Maps

nonabbreviated property name

<table name="TEE_SET">

<meta attribute="extra-import">

javax.persistence.Transient </meta>

<meta attribute="class-code">

@Transient

<column name="POS" property="position"/>

<column name="M_SLOPE_RATING" property="mensSlopeRating"/>

<column name="M_COURSE_RATING" property="mensCourseRating"/>

<column name="L_SLOPE_RATING" property="ladiesSlopeRating"/>

<column name="L_COURSE_RATING" property="ladiesCourseRating"/>

</table>

</hibernate-reverse-engineering>

When you’re done customizing, you can run seam generate restart to apply the changes. Please note that running generate will clobber any changes you previously made to the generated files. Thus, you need to be cautious about enhancing the appli-cation if you plan on executing the reverse engineering again. One way to avoid losing the customizations to entity classes is to define the extra class code in the reverse-engi-neering configuration, as shown in listing 2.4. You also have the option of tweaking the seam-gen templates to achieve the output you desire.

Instead of running the code generation full scale, you can split the code generation into two steps. As of Seam 2.0.1.GA, the generate command is a combination of the generate-model and generate-ui commands. You can run generate-model to incre-mentally develop the JPA entity classes and then run generate-ui once you’ve tweaked the domain model to your liking. You can even skip generate-model altogether and simply use generate-ui to build a CRUD user interface from an existing set of JPA entity classes8 that reside under the src/model tree.

8 If you’re working without an existing database schema, you can set the Hibernate flag hibernate.

hbm2ddl.auto to create-drop, create, or update to have the database schema autogenerated when the application starts.The first two options will also execute custom SQL in the import.sql file.

Adds imports to support custom code Appends custom code to generated class

DEALINGWITHLEGACYDATABASES

Code generation customization is useful when you find yourself having to reverse- engineer a much larger, perhaps more loosely defined database than the one prepared for the Open 18 prototype application. Faced with this task, you may need to use only portions of the schema or simply exclude temporary tables. The reverse-engineering tool offers the <table-filter> element to satisfy this requirement. The <table- filter> accepts a schema name and a table name, which it uses in a LIKE clause to locate tables in the database. You can use the string .* in the name, which is replaced with % when the lookup is executed to allow for a fuzzy search. If you set the exclude attribute on <table-filter> to false, then the filter works by including tables from an empty set. Otherwise, the table filter excludes tables from the full set of tables.

Legacy databases tend to lack consistent naming. For instance, you may encounter the need to specify a name for the generated entity class if the table name is abbrevi-ated or includes an unnecessary prefix. It’s also possible that the database is missing foreign keys, in which case you must specify the entity relationship explicitly. These two changes can be made using additional elements within the <table> node.

The configuration in listing 2.5 presents an example of how to work around the challenges just described for a hypothetical golf equipment database.

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-reverse-engineering SYSTEM

"http://hibernate.sourceforge.net/hibernate-reverse-engineering-3.0.dtd">

<hibernate-reverse-engineering>

<table-filter

match-schema="EQUIPMENT" match-name="PRDCT" exclude="false"/>

<table-filter

match-schema="EQUIPMENT" match-name="MFR" exclude="false"/>

<table-filter

match-schema="EQUIPMENT" match-name="EQ_TYP" exclude="false"/>

<table name="EQ_TYP" class="org.open18.model.EquipmentType"/>

<table name="PRDCT" class="org.open18.model.Product">

<foreign-key foreign-table="MFR">

<column-ref local-column="MFR_ID" foreign-column="ID"/>

</foreign-key>

<foreign-key foreign-table="EQ_TYP">

<column-ref local-column="EQ_TYP_ID" foreign-column="ID"/>

</foreign-key>

</table>

<table name="MFR" class="org.open18.model.Manufacturer"/>

</hibernate-reverse-engineering>

The goal of this section was not to cover the reverse engineering exhaustively, but to introduce you to it and inform you of the fact that it can help you fine-tune your application. There are a handful of features that were not highlighted here, so I encourage you to do some more digging, starting with the Hibernate tools reference

Listing 2.5 Filters tables and establishes missing relationships

documentation.9 Even then, there are still some areas where the reverse engineering comes up short when handling advanced mappings such as embeddable entities, enums, and entity inheritance.

If you’re still not pleased with the classes that the reverse-engineering tool creates, you can further customize them by modifying the FreeMarker templates used to con-struct them. Hibernate includes an entire reverse-engineering API that you can tap into during this process. The templates it uses reside in the seam-gen/pojo directory.

There, you’ll find a small set of customizations to support the seam-gen tasks. Hiber-nate falls back on its own default template if the one it’s looking for is not present in this directory. Chapter 2 of Java Persistence with Hibernate has an excellent section covering reverse engineering customizations.

Once you’re satisfied with the entity model that seam-gen creates, you’re ready to move into the development phase. Because you don’t know anything about the struc-ture of the project that seam-gen has created, you may feel uneasy about this task. Rest assured that seam-gen has prepared a well-organized source tree for you. I’ll now help you become acquainted with that structure.

In document Manning.seam.in.action.sep (Page 93-96)