One of the problems involved with storing Java objects in relational databases is that the objects and their relationships don't usually map directly to relational structures. JdbcStore is a Java framework designed to help you overcome this mismatch and allow you to easily store objects in any JDBC-compatible database. Using the JdbcStore workbench, you can model your persistent objects, their relationships and how their attributes map to database tables and columns. Based on this model, JdbcStore generates Java classes for creating, storing, retrieving and manipulating your objects. An additional collection of classes for handling database connections, transaction processing, SQL queries and object caching round out the product.
How It Works
At the heart of JdbcStore is the concept of a model describing your persistent objects. Models are created and manipulated with the JdbcStore workbench and can be saved to disk. Persistent objects are called types within the model and their properties define how the objects are persisted along with other characteristics.
Using the workbench types can be defined from scratch, loaded from existing .class files or created from table definitions obtained directly from the database. Associated with each type are persistent attributes, attribute to database mappings, inheritance information, key attributes, object relationship definitions and cataloged SQL. Once you define the persistent object types you generate source code that implements persistence for those types. JdbcStore also generates SQL statements to create a database to store the types if needed.
JdbcStore generates a user class, a persistent extension class, a factory class and even BeanInfo classes for each type. The user class defines the persistent object and is normally only generated for types that are defined from scratch in the workbench. The persistent extension subclasses the type to implement persistence with methods such as Store(), IsDeleted() and MarkDeleted(). The factory class is used to generate object instances and includes methods such as NewInstance(), FetchAll(), FetchForKey() and FetchUsingSQL().
Within your application you use these and other JdbcStore classes to load a model, connect to the data source and work with persistent objects. The database connection is handled through a supplied ORB layer for flexibility and objects can be retrieved by using object relations or SQL queries. Related objects can be instantiated immediately or upon being referenced (lazy instantiation). Object caching and concurrency control are supported also.
I bought JdbcStore online (both Windows and Macintosh versions are available) and downloaded a self extracting archive containing the program. Running the archive starts an unpacking wizard which lets you select a location for the JdbcStore installation files. Extracting the installation files requires a product serial number and digital key, which were quickly e-mailed to me after my purchase.
You must have a Java VM installed on your computer before installing JdbcStore. Executing the JdbcStore.class file starts a simple InstallShield installation process. The only choice you have to make is the installation directory (the default is C:\LPC.) Installing JdbcStore took less than five minutes and consumed under 6 MB of disk space.
To run JdbcStore you need to add c:\lpc and c:\lpc\symantec\symbeans.jar to your CLASSPATH (assuming the default installation location.) If you have a recent version of symbeans.jar (say from Visual Café) you can use that instead. According to LPC Consulting, the JdbcStore workbench makes limited use of Symantec Beans and will be converted to JFC in the future.
I tested JdbcStore on a Pentium 133 running Windows 95, with Visual Café 2.5 and JDK 1.1.6. The database was Access 97 and Sun's JDBC-ODBC bridge was the JDBC driver. For this test I created a small Access database with two tables called FRIENDS and ADDRESSES. Using the Windows Control Panel - 32-bit ODBC Drivers - I set up this database as an ODBC data source named "testdb" using Microsoft's Access driver.
I then created a simple Person class in Java with a few public attributes that I wanted to persist in the FRIENDS table. Get and set methods were defined for each attribute destined to be persistent along with a method to print the person's name. The get and set methods are required for JdbcStore to access the persistent fields. My goal was to write an application that would do some updates on the FRIENDS database and print out each person's name and addresses.
Building a Model
The JdbcStore workbench is started by executing"javacom.lpc.jdbcstore.workbench.LPCMainFrame" from the
JdbcStore directory. The first steps once the workbench is started are to load a JDBC driver and connect to your data source. I easily connected to my test database by specifying sun.jdbc.odbc.JdbcOdbcDriver as the driver and a database URL of jdbc:odbc:testdb. Once I was connected, I quickly loaded the database definition into the workbench by retrieving the SQL catalog. Figure 1 shows the definition of the FRIENDS table that was loaded from Access.
Next I automatically generated a persistent type definition for the Addresses table. I didn't do this for the FRIENDS table since I wanted to use the Person class I'd created earlier to access that data. Using JdbcStore's class loader I added my Person class to the model and created a Person type. The public fields and methods from Person.class were visible and I added them to my new Person type.
Next, I edited my new Person and Address types to set up the database mappings. Since I had generated the Address type from the table definition, it already had attributes for each database column with JDBC mappings, as shown in Figure 2. For the Person type I had to set up the mappings to the FRIENDS table, which took me a few tries before I got the Java variable and column database types to match up properly. Once my model was complete I saved it to disk.
Generating Source Code
Once the model was complete I was ready to generate source code, which is done with the workbench. For the Addresses type I generated a user class (since this type was defined from scratch) along with factory and persistent extension classes. For the Person type I simply generated the factory and persistent extension classes because wanted to keep the Person.class file.
When generating source code you can choose the names and locations for the resulting Java classes. I used the default names of Address.java for the user class, lpcAddress.java for the persistent extension, and AddressFactory.java for the factory. All source code is generated from token based templates that are provided and can be modified if necessary.
Creating an Application
Writing an application (or applet) using JdbcStore is straightforward. The first things your application must do are load the JDBC driver, connect to the database and load the model. JdbcStore comes with various classes to handle these tasks. Once these steps are completed the JdbcStore classes can create, fetch, manipulate, and store objects.
A wealth of sample code and an adequate programming guide help get you started. By following the examples, I quickly created a Java application that loaded all Persons from the FRIENDS table, printed out their names, and then swapped their first name and alias values. Then I quickly extended the application to print each person's addresses under their name. To do this I sub-classed the lpcAddress class and added a PrintAddress() method instead of modifying lpcAddress directly, thus avoiding the need to reapply changes if the lpcAddress class is regenerated.
The JdbcStore run-time classes contain other useful features. The database connection is handled by an included ORB which facilitates plugging in RMI or CORBA later. The factory classes have an assortment of fetch statements for filtering and sorting objects. Classes to access the JdbcStore model at run-time are included, along with classes for managing run-time object caching and concurrency control.
To deploy an application you need to include a copy of the model, a set of JdbcStore run-time classes and any classes required by the application. To deploy an applet you need a link to your model (which can be opened using a URL) instead of a copy. The size of my model file was 6KB and the JdbcStore run-time classes took about 200 KB as .class files and 92 KB as a .jar file.
JdbcStore has a few rough edges, which is expected with a product's first release. The most notable shortcomings are in the workbench's user interface. Some standard niceties such as browsing for folders in dialogs are missing. Some functions don't provide as much feedback as I would like, although details are often available in the Java console. In one instance, I created a Java compilation error in one of the generated persistent extension classes because I didn't define a key attribute for the type. This type of invalid entry should be detected by the workbench. These problems don't detract too much from the product since it is used by developers who are (usually!) adaptable to these kinds of limitations.
My other warnings have more to do with frameworks in general than JdbcStore itself. One potential problem with frameworks is that you have to adapt to their architecture and syntax. JdbcStore is simple and intuitive enough that this should not pose a problem. Another thing to keep in mind is that your applications will be tightly coupled to the framework so you should make sure it includes everything you need before you rely on it. JdbcStore seems full-featured enough to be suitable for a variety of applications. You must also be careful about modifying generated code, lest you find yourself having to laboriously reapply changes. JdbcStore is modular enough that you should be able to eliminate this problem with good design.
With JdbcStore you can very quickly create persistent objects and use them in applications. Some of its more powerful features include source code generation, both object oriented and SQL based data access, transaction processing, and object caching. JdbcStore's classes are intuitive, easy to use and provide enough slots and tabs to meet many needs. JDBC, an ORB layer, and customizable source code templates provide flexibility.
JdbcStore still has a few rough edges but they don't affect the product's usefulness. As with any framework you should make sure that you can use it to accomplish your specific goals. The documentation is decent and lots of sample code is included. At only $99, JdbcStore is worth checking out if you want to easily persist your objects or access existing databases with Java.
About the Author
Tim is a software developer and consultant living in Oakland, California. You can reach him through his company's Web site at www.palocolorado.com or at