How to use LiteMap
1.Introduction
1.1Installning
Installing LiteMap is straightforward.
- Download LiteMap from www.sourceforge.net/projects/litemap
- Download a JDBC driver. I use SQLiteJDBC available at http://www.zentus.com/sqlitejdbc/
- Ensure that the Litemap and JDBC jars are in your classpath
1.2Getting started
Let's begin with a simple example.
First, create a Customer class.
//Filename: Customer.java
import net.sourceforge.litemap.*;
public class Customer implements Persistable{
private Integer id = null;
@SkipField private boolean isNew = true;
private String name = null;
private String ssn = null;
public Integer getId(){
return id;
}
public void setId(Integer arg){
id = arg;
}
public boolean isNew(){
return isNew;
}
public void setIsNew(boolean arg){
isNew = arg;
}
public String getName(){
return name;
}
public void setName(String arg){
name = arg;
}
public String getSsn(){
return ssn;
}
public void setSsn(String arg){
ssn = arg;
}
}
Second, create a Test class.
//Filename: Test.java
import net.sourceforge.litemap.*;
public class Test{
Settings.setProperty(”DATABASE”, ”jdbc:sqlite://your/path/filename.db”);
Mapper mapper = Settings.getMapper();
//Create customer table
try{
mapper.createTable(Customer.class);
}
catch(Exception e){
e.printStackTrace();
}
//Create a new customer object and save it to the database
Customer c = new Customer();
c.setName(”Doe John”);
c.setSsn(”010101A0101”);
try{
mapper.save(c, false);
}
catch(Exception e){
e.printStackTrace();
}
}
2.Persistable objects
2.1Minimum requirements
There are some requirements that must be met in order to use LiteMap.
A persistable Java object is by default mapped to a database table with the same name as the name of the Java object in lowercase. The Customer class set out in section 1.2 would, for instance, be mapped to a database table named “customer”. It is, however, possible to specify another table name by using the @TableName() annotation. You can read more about annotations below in section 2.2.
All database tables must have a primary key with the following properties:
•.Name of field must be “id”
•.The field type must be INTEGER
•.Null values are not allowed
•.The field must be AUTOINCREMENT
On the Java side, objects must implement the Persistable interface. The following public methods are required:
•.Integer getId() This method should return null if the object has never been saved to the database. Otherwise it should return the value of the primary key (id).
•.void setId(Integer arg) This method sets the primary key, which you rarely need to do.
•.boolean isNew() The method must return true if the object has never been saved to the database. Otherwise it must return false. The Mapper implementations use this value to decide whether to do a SQL insert or update.
•.setIsNew(boolean arg) The method sets the isNew value, which you rarely have to do manually.
Fields in the Java class are mapped against fields in the database table with the same name. The Java class fields may have any visibility, including private.
2.2Annotations
You may use annotations in the Java code to define mapping properties. The following annotations are supported.
•.@TableName(String value)
•.@TableView(String value)
•.@ReadOnly
•.@SkipField
•.@SqlDef(String value)
By default, LiteMap maps a Java class to a table name with the same name as the class in lowercase. @TableName is used to specify a different table name. If the Customer class in section 1.2 were to be mapped to a database table namned “customers” this could as follows:
@TableName(”customers”)
public class Customers implements Persistable{
...
}
If a @TableView annotation is defined for a class, the mapper uses the specified database view (or table) when loading (reading) the object from the database. The @TableView annotation is normally used in conjunction with fields annotated with @ReadOnly. Such fields are set by the mapper on loading the object, but the mapper skips such fields on saving the object.
@TableName(”customers”)
@TableView(”customers_view”)
public class Customers implements Persistable{
...
@ReadOnly private java.math.BigDecimal accountbalance = null;
}
The @SkipField annotations means that the mapper should ignore the field both on saving and loading the object. In the Customer class set out in section 1.2, the field isNew is annotated with @SkipField, because the field is only used internally by the Java class.
@SqlDef may be used to give information to the mapper's createTable method. The annotation value is simply pasted in the create table query. An example:
public class Customer implements Persistable{
...
@SqlDef(”VARCHAR(20) NOT NULL UNIQUE”) private String ssn = null;
}
2.3 Events
Events are useful for complex data validation and triggers on the Java side. Events are enabled by implementing the WithEvents interface.
The WithEvents interface requires that the following methods are implemented:
•.beforeSave(LiteMapException e)
•.afterSave(LiteMapException e)
•.beforeLoad(LiteMapException e)
•.afterLoad(LiteMapException e)
•.onDelete(LiteMapException e)
The event methods are called by the mapper. The mapper passes a LiteMapException object to the event method. All errors and warnings that occur in the event method should be added to the LiteMapException object. The mapper looks for errors, and will if necessary abort and roll back and the database transaction.
Read more on the LiteMapException object in section 5.
3.Mapper class
3.1Save
The save() method is used to save a persistable object to the database. Example:
Customer c = new Customer();
c.setName(”Doe John”);
Mapper mapper = Settings.getMapper();
mapper.save(c, false);
The first parameter is the persistable object.
The second argument tells the mapper whether warnings should be ignored or not. If set to false, a warning will cause the database transaction to be aborted and rolled back. If set to true, warnings are ignored.
3.2 Load
The load() method populates a persistable object from the database. There are two alternative parameter lists for the method:
•.load(Persistable pobj, Integer id, boolean ignoreWarnings) This method populates pobj with the database record having id as its primary key.
•.load(Persistable pobj, RecordSet rs, boolean ignoreWarnings) This method populates pobj from the current position of the RecordSet rs.
3.3 Delete
The delete() method permanently removes a database record.
import net.sourceforge.litemap.*;
public class Test{
Mapper mapper = Settings.getMapper();
Customer c = new Customer();
mapper.load(c, 1, false);
mapper.delete(c, false);
}
3.4 Create table
The createTable() method creates a database table based on the class passed as argument.
import net.sourceforge.litemap.*;
public class Test{
Mapper mapper = Settings.getMapper();
mapper.createTable(Customer.class);
}
4.Queries
The Query class is a helper for writing custom SQL queries. Example:
import net.sourceforge.litemap.*;
public class Test{
Query q = new Query(”SELECT id, name, ssn FROM customer WHERE name LIKE ?”);
q.ps.setString(1, ”Doe%”);
java.util.Vector<Customer> rv = q.execute(Customer.class, false);
q.close();
}
The result from the execute method is returned as a vector of persistable objects.
4.Errors and warnings
Many methods in the LiteMap API throws a special exception - LiteMapException. The LiteMapException is used to log all exceptions that occur during, for instance, a database transaction.
Exceptions may be logged as errors or warnings. Errors should always mean that the transaction is aborted and rolled back. Warnings, on the other hand, may be ignored by the user. Let's illustrate this with an example:
mapper.save(customer, false)//If a warning is raised, the transaction will be rolled back
mapper.save(customer, true);//All warnings are ignored
Typically a method would first be called with the ignoreWarnings parameter set to false. If a warning is raised, the application may give the user opportunity to ignore it. In many circumstances warnings are needed to raise the quality of data input.
When using LiteMap, errors and warnings are commonly raised in the event methods of the persistable classes. You could for instance implement data validation in the beforeSave() method of the Customer class as follows:
import net.sourceforge.litemap.*;
public class Customer implements Persistable, WithEvents{
...
public void beforeSave(LiteMapException e){
if (name==null){
e.add(LiteMapException.LOGLEVEL_ERROR,
new Exception(”You must give your name”));
}
else if (name.length<3){
e.add(LiteMapException.LOGLEVEL_WARNING,
new Exception(”Is that really your name?”));
}
}
}
5. Settings class
The Settings class is intended as a central repository for settings used by LiteMap.
The following settings are built-in:
•.DATABASE
•.CLIENT_DATE_FORMAT
•.CLIENT_TIME_FORMAT
•.CLIENT_DATETIME_FORMAT
•.DB_DATE_FORMAT
•.DB_TIME_FORMAT
•.DB_DATETIME_FORMAT
•.DECIMAL_FORMAT
The DATABASE property is used by the ConnectionManager class to open a database connection. The property should contain a valid JDBC url.
The other built-in properties are used for formatting purposes. The CLIENT_XX_FORMAT properties are used by the GuiHelper class.
Properties may be set progammatically by the method Settings.setProperty(String key, String value).
Properties may also be loaded from a Java property file using the method Settings.load(InputStream is).
6. ConnectionManager class
The ConnectionManager class is used by LiteMap to open and release database connections.
The ConnectionManager only has two methods: getConnection() and releaseConnection().
You may write your own ConnectionManager class. In order to tell LiteMap to use your own ConnectionManager, you must set it with the Settings.setConnectionManager(ConnectionManager arg) method.
7. GuiHelper class
The GuiHelper class is intended for programming graphical user interfaces.
The load method of the class will try to load a persistable object from the fields of a window class. An example:
Customer c = new Customer();
GuiHelper.load(c, myform, ”txt”);
This example will map a fields in the object myform to the persistable object. A field in myform namned ”txtName” will for instance be mapped to the field in the Customer object named name.
The display method of the GuiHelper class works in the opposite direction, populating the fields of a window class from the persistable object.