Installing and Using the Torque Object Mapper
Larry Wall (father of Perl) is fond of saying that one of the virtues of a good programmer is laziness. By this he means that the best programmers never do work that they can avoid by using someone else's tools.
In Java, there has always been a lot of fairly mindless work that keeps developers from getting to the real job of implementing business logic. One of them, implementing the boilerplate get and set accessors for beans, has been largely eliminated by technologies such as IDEs and now the new DynaBeans framework.
One nettlesome chore still takes up a large amount of development time, however. That is implementing the persistence layer in an application. Anyone who has spent time with a database-enabled project knows the pain that this entails, not so much because it is intellectually difficult, but because it requires a lot of code to handle retrieving, creating, deleting, and updating data.
The Apache Jakarta Torque project is a spin-off of the Turbine application framework; it allows a developer to create one XML file, and have both a persistence layer and database schema automatically generated for them. By using Torque, it is possible to database-enable a simple application in a matter of hours.
To see how Torque works, we'll look at a sample application with a dose of Torque magic. Let's assume that we have a group of database tables we're using to track baseball pitchers, described in conventional SQL (of the MySQL dialect) here:
Here's Table 1:
CREATE TABLE PITCHER ( PITCHER_ID INTEGER NOT NULL AUTO_INCREMENT, LAST_NAME VARCHAR (30) NOT NULL, FIRST_NAME VARCHAR (30) NOT NULL, TEAM_ID INTEGER NOT NULL, PRIMARY KEY(PITCHER_ID), FOREIGN KEY (TEAM_ID) REFERENCES TEAM (TEAM_ID) );
Here's Table 2:
CREATE TABLE TEAM ( TEAM_ID INTEGER NOT NULL, TEAM_NAME VARCHAR (30) NOT NULL, PRIMARY KEY(TEAM_ID) );
And here's Table 3:
CREATE TABLE GAME ( PITCHER_ID INTEGER NOT NULL, PLAYING_FOR INTEGER NOT NULL, AGAINST_TEAM INTEGER NOT NULL, OUTS_RECORDED INTEGER NOT NULL, HITS INTEGER, RUNS INTEGER, WALKS INTEGER, STRIKE_OUTS INTEGER, FOREIGN KEY (PITCHER_ID) REFERENCES PITCHER (PITCHER_ID), FOREIGN KEY (PLAYING_FOR) REFERENCES TEAM (TEAM_ID), FOREIGN KEY (AGAINST_TEAM) REFERENCES TEAM (TEAM_ID) );
You can use this schema to record data about the performance of pitchers as well as teams. Each pitcher belongs to a team, each team has a cadre of pitchers, and each pitcher has a record of how they have performed in each inning pitched.
In a conventional approach, you would need to write methods to read, write, update, and delete each of these tables, as well as creating the objects to model them. By using Torque, all this is taken care of.
To install Torque, you download the Torque binary. As of this writing, the nightly build is the most stable, and its ZIP file can be found at http://jakarta.apache.org/builds/jakarta-turbine/alpha/. When you unpack the zip, you'll find the following files in the newly created torque directory.
Torque.properties build-torque.xml build.properties build.xml database/ docs/ lib/ master/ schema/ src/ templates/ velocity.log
The first step is to configure the build.properties file. Only the top of the file needs to be edited. Here are the critical items, with the values being used for this example:
project = pitchers
The name of the project, used to find the database definitions in the schema directory:
database = mysql
The type of database being used, one of: db2400, hypersonic, mssql, mysql, oracle, postgresql, sapdb, and sybase. You also can write your own database adaptors, a discussion outside the scope of this article.
The package in which the generated classes that define the object mapping will be created. I find it's helpful to use "torque" in the package path to make them stand out and remind me that they're generated by Torque.
createDatabaseUrl = jdbc:mysql://127.0.0.1/ databaseUrl = jdbc:mysql://127.0.0.1/pitchers databaseDriver = org.gjt.mm.mysql.Driver databaseUser = pedro databasePassword = ace databaseHost = 127.0.0.1
The information needed to connect to the database is similar to the information used when setting up a connection pool. Note that you need to provide the databaseDriver and put it in the Torque lib directory for things to work correctly.
Now you're ready to create your database schema. The schema file is in the schema subdirectory, and is called project-schema.xml. As shipped, it has demonstration data in it, which we'll replace with our data.
<?xml version="1.0" encoding="ISO-8859-1" standalone="no" ?> <!DOCTYPE database SYSTEM "http://jakarta.apache.org/turbine/dtd/database.dtd">
This is just a normal XML header.
<database name="PITCHERS" defaultIdMethod="native">
Next, we tell Torque that we're defining a database called "PITCHERS". The defaultIdMethod parameter tells Torque how to handle integer primary key columns. If "native" is selected, Torque will allow the underlying database to use its own native implementation. If "idBroker" is specified, Torque will use its own vendor-neutral implementation which will work even for databases that don't support auto-incrementing primary keys. The downside to using the ID Broker is that it forces Torque to do a lot of acrobatics to keep the ids in sync between multiple threads or processes (or even servers), something that the native database implementations can usually handle better.
<table name="PITCHER"> <column name="PITCHER_ID" required="true" autoIncrement="true" primaryKey="true" type="INTEGER/> <column name="LAST_NAME" required="true" size="30" type="VARCHAR"/> <column name="FIRST_NAME" required="true" size="30" type="VARCHAR"/> <column name="TEAM_ID" required="true" type="INTEGER"/> <foreign-key foreignTable="TEAM"> <reference local="TEAM_ID" foreign="TEAM_ID"/> </foreign-key> </table>
Page 1 of 3