10.4. Using OJB
The APIs to OJB are quite straightforward, and it is very easy to use them to create, update, and retrieve data. Everything goes through a PersistenceBroker, which is responsible for transparently managing all the mapping details. Obtaining a PersistenceBroker is done through a factory:
It is possible to define several PersistenceBrokers, perhaps each pointing at a different database. Recall that the default database was defined in repository_database.xml; this is the database that will be used by the default broker.Once a broker has been obtained, storing a new instance of any defined object is pleasantly simple:
import org.apache.ojb.broker.PersistenceBroker;
import org.apache.ojb.broker.PersistenceBrokerFactory;
...
PersistenceBroker broker = null;
try {
broker =
PersistenceBrokerFactory.defaultPersistenceBroker();
} catch (Throwable t) {
t.printStackTrace();
}
The object is created and values are set, just as with any bean. To save the object to the database a transaction is started, and the store() method is used to write the object data to the database according to the mapping. The transaction is then committed. If anything goes wrong, the transaction can be rolled back.Deleting an object is just as easy: Simply call broker.delete() instead of store().Note that the albumId was not set before being stored. Because OJB knows that albumId is the primary key and auto increment has been set to "true" in the mapping file, OJB will automatically allocate a new primary key when it detects that albumId is null. This is done by the sequence-manager defined in OJB.properties. The default implementation stores the next available primary keys in a table called OJB_HL_SEQ, which is one of the internal tables mapped in repository-internal.xml.Many databases provide their own mechanism for automatically allocating primary keys, but these often vary widely between different databases. Putting all the primary key logic in the application, as with OJB, makes it very easy to move from one database to another. With OJB developers can use hsqldb, and the application can be deployed on Oracle without having to change a single line of application code or configuration data. However, this means that if any other application that will be writing to the databaseincluding commands entered by hand through an interpretermust also update the OJB_HL_SEQ table. Failure to do so may lead to conflicts as OJB tries to allocate a new primary key that has already been assigned.If OJB detects that all the object's primary keys are present when it is saved, then it will perform an update instead of an insert. This is valid because the only ways in which an object can have a primary key are by already having one in the database or by being assigned one by OJB prior to initially being saved. In either case, it means that the object must already exist, so any save operation must be updating data. This makes it very easy for a band to change its namefor example, the artist in the previous example:
Artist newArtist = new Artist();
newArtist.setName("Imagica");
try {
broker.beginTransaction();
broker.store(newArtist);
broker.commitTransaction();
} catch (PersistenceBrokerException e) {
broker.abortTransaction();
System.out.println("Unable to save: " + e);
}
It is reasonable to expect that when storing or updating an object all the primitive fields would be saved, and this is indeed the case. It is less clear what OJB will do with collections. This behavior is controlled by the auto-update attribute of the collection-descriptor noted in passing in the section on "repository-user." When this attribute is set to true, OJB will traverse the collection and automatically save any objects. This means the following code will work as expected:
artist.setName("The Birthday Massacre");
...
broker.store(artist);
...
OJB will save artist, which will entail allocating a new artistId. After the record has been written to the database, OJB will examine all the collections and then attempt to save each album. When doing so it will notice that each needs a primary key and so will allocate new albumIds. It will also know that artistId in Albumis a foreign key and will assign it with the artistId that was handed out as the new primary key to artist. OJB will then save the albums, having ensured that all the database constraints have been satisfied.The auto-delete attribute works similarly. When this is set to true, deleting an object will cause objects in that objects collections to be deleted first. Typically this makes sense: If an artist is being removed from the database, all that artist's albums should be removed as well. In fact, by declaring a foreign-key relationship in the database definition, this constraint will be enforced; any attempt to delete an artist who still has albums will fail with an error. Setting auto-delete and auto-update to true thus ensures that the semantics of the object is identical to the semantics of the database as defined in the schema, in addition to mapping the hierarchical structures.
Artist artist = new Artist();
artist.setName(");
Album first = new Album();
first.setName(");
first.setYearReleased();
Album second = new Album(");
second.setName(");
second.setYearReleased();
...save the artist ...