Mapping Objects


The generated schema is nice for development, but at some point, you'll reach the stage where you want to customize the schema to conform to your naming or datatype needs. Or perhaps your DBA will prefer to take over and provide schema optimized for your database. In that case, you'll need JBoss to play nicely with your schema. In this lab, you'll see how to control table names, field names and type mapping details

How do I do that?

We'll start by looking more closely at the schema JBoss created. JBoss created a table for each entity bean:

     CREATE TABLE TASK     (         id VARCHAR(256) NOT NULL,         name VARCHAR(256),         user VARCHAR(256),          startedDate TIMESTAMP,         completedDate TIMESTAMP,         CONSTRAINT PK_TASK PRIMARY KEY (id)     )             CREATE TABLE COMMENT     (         id VARCHAR(256) NOT NULL,         commentText VARCHAR(256),          date TIMESTAMP,         task VARCHAR(256),         CONSTRAINT PK_COMMENT PRIMARY KEY (id)     ) 


Note: JBoss will select different names when the table or column name is a common SQL reserved word. The full list of reserved words comes from standardjbosscmp-jdbc.xml.

The table names come from the ejb-name name of the beans, and the column names are the field names of persistent fields on the beans. We'll want to update the names to use more normal database conventions.

The type information is slightly more complex. Each supported database has a type-mapping section in the standardjbosscmp-jdbc.xml file that contains mappings from Java classes to JDBC and SQL types. The task and comment beans use only two basic types: java.lang.String and java.util.Date. Here are the mappings for those two types:

     <type-mapping>         <name>Hypersonic SQL</name>         <!-- ... lots of other types deleted ... -->         <mapping>             <java-type>java.lang.String</java-type>             <jdbc-type>VARCHAR</jdbc-type>             <sql-type>VARCHAR(256)</sql-type>          </mapping>          <mapping>             <java-type>java.util.Date</java-type>             <jdbc-type>TIMESTAMP</jdbc-type>             <sql-type>TIMESTAMP</sql-type>          </mapping>     </type-mapping> 


Note: The default date mapping differs by database. It's better to use java.sql.Date, java.sql.Time, and java.sql.Timestamp rather than java.util.Date to avoid any mapping confusion.

That explains where the type mapping for each column comes from. These mappings make sense as defaults, but it's easy to imagine wanting to use different values for specific fields.

The date mapping looks fine for our needs, since the intention is to provide a date and time value. However, the string values could use some tweaking. The task name and comment lengths of 256 characters are probably OK for now, but the UUID primary key values will always be 32 characters in length. You can change the type when you are updating the table and column names.

To make these changes, you'll need to go back to the jbosscmp-jdbc.xml file. After the defaults section, you can have an enterprise-beans section that contains the CMP configuration for each of your entity beans:

     <jbosscmp-jdbc>         <enterprise-beans>             <entity>                 <ejb-name>Task</ejb-name>                 <!-- configuration for the task bean -->             </entity>             <entity>                 <ejb-name>Comment</ejb-name>                 <!-- configuration for the comment bean -->             </entity>         </enterprise-beans>     </jbosscmp-jdbc> 

The structure of this element resembles that of the enterprise-beans element in an ejb-jar.xml file, with an entity section for each bean. This similarity is intentional. The ejb-name element links the entity to an entity with the same ejb-name in the neighboring ejb-jar.xml file.

The first thing you can configure is the table name that the entity maps to. The table-name element specifies the name of the table to use:


Note: The naming scheme here is completely arbitrary. The point is that you can choose any naming policy that makes sense for your application.
     <entity>         <ejb-name>Task</ejb-name>         <table-name>TODO_TASK</table-name>     </entity> 

We've chosen to add the suffix TODO_ to the name of the bean to make it easier to group the tables related to the ToDo application.

You can add a cmp-field element for each regular CMP field you want to map. The field-name element links this element to a named cmp-field element in the ejb-jar.xml file, and the column-name element specifies the name of the column that the field maps to. Here is a mapping for the id field of TaskBean:

     <cmp-field>         <field-name>id</field-name>         <column-name>TASK_ID</column-name>     </cmp-field> 

You've already seen that JBoss maps this field to VARCHAR(256) in the database because it is a String field. However, the primary keys used by the application are always 32-character UUIDs. So, we'd really rather have this field converted to VARCHAR(32) in the database.

You can provide an override to the jdbc-type and sql-type elements you saw in the default mappings in standardjbosscmp-jdbc.xml. Now the complete configuration looks like this:

     <cmp-field>         <field-name>id</field-name>         <column-name>TASK_ID</column-name>         <jdbc-type>VARCHAR</jdbc-type>         <sql-type>VARCHAR(32)</sql-type>     </cmp-field> 


Note: jdbc-type and sql-type always go together. You can't specify one without the other.

When overriding types in this manner, be aware that you lose database independence. Normally, changing databases would cause a new, and potentially different, type mapping to be loaded from standardjbosscmp-jdbc.xml. However, when overriding types in this manner, the type remains constant regardless of the database in use. It's not much of a limitation, but it is something to keep in mind if you are designing an application that will be deployed on multiple databases.

There's nothing tricky in mapping the rest of the fields. The complete jbosscmp-jdbc.xml file is shown here:

     <!DOCTYPE jbosscmp-jdbc PUBLIC                "-//JBoss//DTD JBOSSCMP-JDBC 4.0//EN"               "http://www.jboss.org/j2ee/dtd/jbosscmp-jdbc_4_0.dtd">     <jbosscmp-jdbc>         <defaults>             <create-table>true</create-table>             <alter-table>true</alter-table>             <remove-table>false</remove-table>         </defaults>         <enterprise-beans>             <entity>                 <ejb-name>Task</ejb-name>                 <table-name>TODO_TASK</table-name>                 <cmp-field>                     <field-name>id</field-name>                     <column-name>TASK_ID</column-name>                     <jdbc-type>VARCHAR</jdbc-type>                     <sql-type>VARCHAR(32)</sql-type>                 </cmp-field>                 <cmp-field>                     <field-name>name</field-name>                     <column-name>TASK_NAME</column-name>                 </cmp-field>                 <cmp-field>                     <field-name>user</field-name>                     <column-name>TASK_USER</column-name>                 </cmp-field>                 <cmp-field>                     <field-name>startedDate</field-name>                     <column-name>TASK_START</column-name>                 </cmp-field>                 <cmp-field>                     <field-name>completedDate</field-name>                     <column-name>TASK_END</column-name>                 </cmp-field>             </entity>             <entity>                 <ejb-name>Comment</ejb-name>                 <table-name>TODO_COMMENT</table-name>                 <cmp-field>                     <field-name>id</field-name>                     <column-name>COMMENT_ID</column-name>                     <jdbc-type>VARCHAR</jdbc-type>                     <sql-type>VARCHAR(32)</sql-type>                 </cmp-field>                 <cmp-field>                     <field-name>commentText</field-name>                     <column-name>COMMENT_TEXT</column-name>                 </cmp-field>                 <cmp-field>                     <field-name>date</field-name>                     <column-name>COMMENT_DATE</column-name>                 </cmp-field>             </entity>         </enterprise-beans>     </jbosscmp-jdbc> 

This is included in the etc/cmp-field directory, and you can deploy it from the build file by setting optional.dd to cmp-field:

     [todo]$ ant -Doptional.dd=cmp-field main deploy 

When you do this, JBoss creates the following schema:

     CREATE TABLE TODO_TASK      (         TASK_ID VARCHAR(32) NOT NULL,          TASK_NAME VARCHAR(256),          TASK_USER VARCHAR(256),          TASK_START TIMESTAMP,          TASK_END TIMESTAMP,          CONSTRAINT PK_TODO_TASK PRIMARY KEY (TASK_ID)     )             CREATE TABLE TODO_COMMENT      (         COMMENT_ID VARCHAR(32) NOT NULL,          COMMENT_TEXT VARCHAR(256),          COMMENT_DATE TIMESTAMP,          task VARCHAR(32),          CONSTRAINT PK_TODO_COMMENT PRIMARY KEY (COMMENT_ID)     ) 


Note: The task column on TODO_ COMMENT is a CMR field, not a CMP field. We'll get to CMR fields shortly.

What just happened

You learned how JBoss maps entity beans. You saw the default naming strategy and saw the default type mappings in standardjbosscmp-jdbc.xml. You customized the basic CMP mapping of the entity beans, overriding both the name and the type of the default mappings in the jbosscmp-jdbc.xml deployment descriptor.

JBoss created the new schema for you when you deployed the application. If you didn't have the remove-table flag set to delete the old tables on undeployment, you'd still have the original TASK and COMMENT tables alongside the new TODO_TASK and TODO_COMMENT. This is true although alter-table was TRue.

JBoss had no way of knowing that the TASK table was actually the old TODO_TASK table when it deployed the application. As far as it's concerned, TASK could be a completely different and unrelated table. JBoss won't drop the old table or attempt to rename it. It's a manual step.

Nothing went wrong here, but something very well could have. Try changing the type of one of the ID fields from VARCHAR(32) back to VARCHAR(256) and redeploy the application. Did JBoss change your schema? It didn't, at least not if you are still working with Hypersonic. Hypersonic can't alter the type of a column. It's just a limitation of the database that JBoss can't work around.

Even if you are working with another database that supports altering types, JBoss will actually attempt to change only the types of CHAR or VARCHAR fields, and then only if the new field is longer in length than the old field. It's certainly limiting, but there are fundamental limitations in what can be done programmatically. At some point human intervention is required.



JBoss. A Developer's Notebook
JBoss: A Developers Notebook
ISBN: 0596100078
EAN: 2147483647
Year: 2003
Pages: 106

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net