Turbine

Essentials

Models

Get Involved

Documentation

Database

Working With Peers

Peers are an Object Relation mapping tool, built on top of Village that gives you access to a relational database via Java objects. Peers act on a somewhat lower level than other O-R mapping tools like Castor or Osage. This means that you have to do some coding by hand, but it allows for the most flexible solution.

Peers use Turbine's Database adaptor classes that make uniform connection to a wide range of databases possible. If your database is not supported you can read the Database Adapter docs on how to create a new adaptor for your database.

NOTE: If you would like to use Peers outside of the Turbine Servlet (this is very common), then you need to use the TurbineConfig object to initialize Turbine's code with the right TurbineResources.properties file before you execute your Peer code. Please see the javadoc for the TurbineConfig object for more details.

Database Maps

Peers make use of a DatabaseMap class that holds internal data about the relational schema. You will seldom, if ever, need to work with the DatabaseMap class. It is used internally by Peers to discover information about the database at runtime.

There is exactly one DatabaseMap for each relational database that you connect to. You may wish to connect to more that one database in your application. You should then have one DatabaseMap for each of the databases.

DatabaseMaps are constructed by classes called MapBuilders. Turbine has a default MapBuilder, called TurbineMapBuilder, that creates a DatabaseMap for Turbine's internal database structure. Again you should seldom work with MapBuilder classes. They are used internally by Peers. Usually there is a MapBuilder for each table in your database. MapBuilder classes for new schemas can be generated for you automatically.

Peer Classes

Everything in Peers resolve around Peer classes. A Peer class have a one-to-one mapping to a Database table. You use each table's associated Peer class to do operations on that table. Peer classes can be generated for you automatically.

Peer classes have static methods only, so you would never create objects of Peer classes. It is not necessary to have objects on this level because of the one-to-one mapping with a table. Peer methods are thread-save.

Data Objects

A Data Object holds information about a single row of a specific table. Data Objects can be generated automatically for you. It takes the form of Bean properties for each field of the table.

Data Objects are used almost exclusively with their related Peer classes. Where peer classes "wraps around" around a database table, a Data Object "wraps around" individual rows of the table. The two always go together.

You normally use Data Objects in one of two ways. The most common way is to extract data after you called a doSelect on a Peer class. The doSelect method returns a vector of Data Objects that holds the data of the resultset. Secondly you can create Data Objects and pass it to the overloaded doInsert and doUpdate methods of the relevant Peer class.

Criteria Objects

Criteria is an abstraction of the criteria of an sql query. We use criteria objects to specify the criteria of a sql statement. The database adaptor classes contains information on how this Criteria object will be translated to different flavours of sql.

Criteria is in effect a map of field names and values that forms the criteria of a query. By default the comparison is equals (=) but you can define any comparison operator (<,>,<=,>=,IN,etc.).

Criteria can also be used to do some other sql function like ORDER BY or DISTINCT. If Criteria is too limited for your purposes (which should not happen often) you are still free to use raw sql queries.

ID Broker

One of the cool features of Peers is the ID Broker. ID Broker is used to automatically create unique primary keys for tables. The ID Broker has support for auto-increment fields like in MySQL; sequence generators like in Oracle or if neither is supported it creates id's from a database table called id_table.

You use the MapBuilder to specify which of the techniques you want to use with your system. By default the id_table is used, because it is the only common denominator.

The ID Broker is used in the underlying Peer code. After you have set it up you need not worry about it anymore.

Typical Peer Usage

All the examples on this section will be based on the following schema:

        create table category (
            category_id     int not null,
            name            varchar (100) not null,
        primary key (category_id));

        create table item (
            item_id         int not null,
            name            varchar (100) not null,
            price           int not null,
            category_id     int,
        primary key (item_id),
        foreign key (category_id) references category (category_id)
                on delete set null
                on update cascade);
Selects

Probably the most common use of Peers is to select data from a database. If we want to extract all the Categories from the database we can use the following code. Because we want all the objects we don't need to add anything special to the Criteria.

Criteria crit = new Criteria();
Vector v = CategoryPeer.doSelect (crit);

If you want to select all the items of a certain Category you need to add it to the Criteria object. For example we need all the items from the Category with id 2.

Criteria crit = new Criteria();
crit.add (ItemPeer.CATEGORY_ID,2);
Vector v = ItemPeer.doSelect (crit);

After you obtained the Vector of Data Objects you can add it to the Context if you're using WebMacro or Velocity. This will allow you to use #foreach in the template to display all the selected items.

Inserts

To do an insert we need to add all the fields to the criteria objects. Note that the id field is not added to the Criteria. It is taken care of by the ID BROKER. The object that is returned by doInsert is the id of the newly added row.

Criteria crit = new Criteria();
crit.add (CategoryPeer.NAME,"New Category");
Object o = CategoryPeer.doInsert (crit);

We can also use the overloaded method to add a new Data Object. Note that once again we don't set the id - the ID BROKER does this for us.

Item itm = new Item();
itm.setName ("New Item");
itm.setPrice (100);
itm.setCategoryId (1);
Object o = ItemPeer.doInsert (itm);

I saved the best for last. Say that you want to create a new database entry from an html form. You can use the ParameterParser object (see the getParameters method of RunData in the api docs) to automatically fill in your fields. All that you need to do is to give your html form fields the same name as the corresponding property in the generated Data Object. For example a database field ITEM_ID will cause the generated Data Object to have getItemId and setItemId methods. Here the property name is ItemId, so that should be the form field name. Then you can have code like this:

Item itm =  new Item()
data.getParameters().setProperties(itm);
Object o = ItemPeer.doInsert (itm);

Updates works pretty much the same as inserts. You just need to call the doUpdate method from your Peer class. Just keep in mind that you must add and id column if you wish to do Updates.

Deletes

Deletes work much in the same way than a select. If you for example want to delete the item with id = 3 then you simply add it to the Criteria and call doDelete.

Criteria crit = new Criteria();
crit.add (ItemPeer.ITEM_ID,3);
ItemPeer.doDelete (crit);

Copyright © 1999-2001, Apache Software Foundation