This short tutorial gives an introduction into the general working principles of PriDE, based on a simple example. It takes less than half an hour to set up a simple PriDE application which allows to perform basic operations on a single database table. The package quickstart of the PriDE manual example code repository on GitHub contains the complete source code for the tutorial example.
Setting up an application includes the following steps:
I.e. there’s only a few minutes time for each step now, so let’s hurry up ;-)
Working with PriDE requires to add the library pride-x-y-z.jar into the CLASSPATH of the working environment, as well as the JDBC driver of the database to access. E.g. in case of a MySQL 6 database this is the library mysql-connector-java-6.y.z.jar, for Oracle 11 the library ojdbc8.jar, for HSQL 2.x the library hsqldb-2.y.z.jar, and for SQLite 3 the library sqlite-jdbc-3.y.z.jar. The ultra light database SQLite in server-less mode is the best choice for first experiments. You may set up a playground project by cloning PriDE’s manual examples source code repository on GitHub and compile its sources with Maven, using the included pom.xml. However, as PriDE and SQLite do not depend on any other libraries, you can easily download the PriDE and SQLite JAR files from Maven central and create a project with any technique you like.
Driver class, database URL, database user, and password are supposed to be provided as system properties in this tutorial examples. For SQLite and a local example database, user and password can be omitted and the properties look like this:
pride.dbtype=sqlite
pride.driver=org.sqlite.JDBC
pride.db=jdbc:sqlite:pride.examples.db
pride.logfile=sql.log
Providing the DB type is recommended, to keep PriDE from making a wrong guess, and logging all SQL operations is usually a good idea - especially for beginners.
PriDE follows a database-first approach, so in the next step, the required database table must be designed. PriDE does not provide its own tool for that but assumes one being included in your database installation. If nothing appropriate is around, their are lots of tools available for that, e.g. the free DB Designer online tool which supports various common databases. The tutorial examples uses a database table according to the following definition:
create table CUSTOMER (
id integer not null primary key,
name varchar(20),
first_name varchar(30)
);
Add this table now to your SQLite database, using SQLite’s command shell or by running class CreateCustomerTable included in the PriDE manual example code:
java
-Dpride.dbtype=sqlite
-Dpride.driver=org.sqlite.JDBC
-Dpride.db=jdbc:sqlite:pride.examples.db
-Dpride.logfile=sql.log
util.CreateCustomerTable
Accessing a table via PriDE requires a corresponding entity class (usually a simple Java Bean) and a mapping descriptor object. 1:1 mappings of a database table to a Java class can be generated with a code generator provided with PriDE. For the table CUSTOMER above, the source code for a corresponding entity class Customer and an incorporated descriptor can be generated by the following call:
java
-Dpride.dbtype=sqlite
-Dpride.driver=org.sqlite.JDBC
-Dpride.db=jdbc:sqlite:pride.examples.db
-Dpride.logfile=sql.log
pm.pride.util.generator.EntityGenerator CUSTOMER quickstart.Customer > Customer.java
The generator writes its output to the console, so you can either redirect the output to file as you see above or create the class in the IDE of your choice and copy the output from the console to your class editor. Note that you may also generate the descriptive parts in a separate class to keep the entity bean class free from database aspects. For the tutorial example we generate a hybrid class which looks like this:
public class Customer extends MappedObject {
public static final String TABLE = "CUSTOMER";
public static final String COL_ID = "id";
public static final String COL_NAME = "name";
public static final String COL_FIRST_NAME = "first_name";
protected static final RecordDescriptor red =
new RecordDescriptor(Customer.class, TABLE, null)
.row(COL_ID, "getId", "setId")
.row(COL_NAME, "getName", "setName")
.row(COL_FIRST_NAME, "getFirstName", "setFirstName")
.key(COL_ID);
public RecordDescriptor getDescriptor() { return red; }
private long id;
private String name;
private String firstName;
// Read access functions
public long getId() { return id; }
public String getName() { return name; }
public String getFirstName() { return firstName; }
// Write access functions
public void setId(long id) { this.id = id; }
public void setName(String name) { this.name = name; }
public void setFirstName(String firstName) { this.firstName = firstName; }
// Reconstructor
public Customer(long id) throws SQLException {
setId(id);
findXE();
}
public Customer() {}
}
Without going into details now, you can see an important design principle of PriDE: the mapping descriptor is code. You won’t find any descriptive languages included in PriDE - neither XML nor property nor JSON files. Everything in PriDE is Java code and can be examined with a debugger if necessary.
Based on the entity classes, you can design the actual application. First of all the PriDE runtime library must be initialized by a so-called “resource accessor”. A JSE application requires only a single line of code for an initialization based on system properties:
ResourceAccessorJSE.fromSystemProperties();
The database operations are performed by invoking corresponding member functions of the entity classes, e.g.
public void create(int id, String name, String firstName)
throws SQLException {
Customer c = new Customer(id, name, firstName);
c.create();
}
public void update(int id, String name, String firstName)
throws SQLException {
Customer c = new Customer(id, name, firstName);
c.update();
}
public void queryByName( String name )
throws SQLException {
Customer c = new Customer(0, name, null);
ResultIterator ri = c.query(COL_NAME);
if (ri != null) {
do {
System.out.println(
c.getId() + ": " +
c.getName() + "," +
c.getFirstName());
} while(ri.next());
}
}
The tutorial example on GitHub includes the class CustomerClient, providing an interactive test client. Calling the client with its system property based initialization looks like this:
java
-Dpride.dbtype=sqlite
-Dpride.driver=org.sqlite.JDBC
-Dpride.db=jdbc:sqlite:pride.examples.db
-Dpride.logfile=sql.log
quickstart.CustomerClient
Play around with the client and then check the working directory. You will find a file sql.log created by PriDE which logs all the SQL statements that resulted from your persistence operation calls. The log file is plain SQL, so if you encounter any unexpected persistence behavior in you application, you can copy the commands from the log and run them from you database’s SQL shell. This is a big advantage over the command logging of most other persistence frameworks.
Actually PriDE is working with plain SQL by default rather than with so-called “bind variables”. So what you see in the log file is exactly what PriDE executes against the database resp. its JDBC driver. If you like to change to bind variables as default, you can add the configuration property -Dpride.bindvars=on
. Restart the CustomerClient with this system property set, run some commands and check the log file again. You still see plain SQL but the values of insert and select statements are now preceded by a ? indicating that the value was passed to the database via a bind variable. You can still copy every command from the log to an SQL shell - you only have to remove its question marks before running it interactively. You won’t find many persistence managers with a comfortable SQL logging like that.
A meaningful usage of bind variables becomes a relevant issue for heavily accessed databases and will be discussed in the prepared operations chapter.
The tutorial example already introduces the most important basic elements of PriDE. To understand what’s going on behind the scenes of the 5 steps above, you will find all aspects explained in detail in the manual.
Before you go on you should simplify the configuration in a way that you don’t have to provide system properties every time you call a client. Although PriDE does not require any descriptive languages, they are sometimes quite helpful. To simplify the playing-around with examples, all client programs included in the PriDE manual examples use the class util.ResourceAccessorExampleConfig for initialization. It allows to assemble the configuration from two sources: system properties as it was introduced so far and a property file config/pride.examples.config.properties. As the configuration properties probably stay unchanged through all your experiments, you should transfer all your command line system properties to file (without the leading “-D” of course) and start your client programs without passing any system properties at all. To run the entity generator with the file-based configuration call the wrapper class util.EntityGeneratorWithExampleConfig which is also included in the examples.