Java Ultra-Lite Persistence (JULP)
Features
- Open Source (GPL)
- Running both in container and stand-alone
- Small footprint (less than 50 KB)
- No dependences on any libraries, only JDK (of cource you need JDBC driver)
- Database independent (tested so far with Oracle 7.3, Sybase ASE 12.0, MckoiDB 1.02, hsqdb 1.7.1)
- JDBC 1.x and up
- Inheritance
- Many classes per table
- Many tables per class
- Simple mappings: the only mapping you need is <catalog >.<schema>.table.column=fieldName
CREATE TABLE PRODUCT(ID INTEGER NOT NULL PRIMARY KEY,NAME VARCHAR,PRICE DECIMAL)
...
public class Product{
Integer productId;
String productName;
double price;
...
}
...
ProductFactory factory = new ProductFactory(Product.class);
Map mapping = new HashMap();
mapping.put("PRODUCT.ID", "productId");
mapping.put("PRODUCT.NAME", "productName");
mapping.put("PRODUCT.PRICE", "price");
factory.setMapping(mapping);
...
It is entirely up to you where would you get the values from:
you can get them from .xml, .properties, JNDI, database. You can even hardcoded them (just don't say I recommended this ;-) )
- Instead of sending for updates over the network all the objects, it's possible to send only modified objects.
It's also possible to generate DML statements on the client and send them along with parameters to Application Server or another application for processing:
...
ProductFactory factory = new ProductFactory(Product.class);
factory.setGenerateSQLOnly(true);
...
factory.writeData();
...
List allChanges = factory.getGeneratedSQL();
//Another way...
...
Object[] changes = (Object[]) allChanges.get(0);
String sql = (String) changes[0];
Object arg = changes[1];
PreparedStatement ps = connection.prepareStatement(sql, arg);
...
Or if you'd use JULP for updates:
DBServices dbServices = new DBServices();
...
dbServices.execute(sql, arg);
- Very simple way to populate objects from database:
...
ProductFactory factory = new ProductFactory(Product.class);
ResultSet rs = ...;
factory.load(rs);
...
It is entirely up to you where would you get the ResultSet from:
it could be another framework, hand-written sql, etc. It means the full power of SQL in your hands and not limited by framework's API.
However there are convinient methods available:
...
ProductFactory factory = new ProductFactory(Product.class);
List arg = new ArrayList();
arg.add(new Double(77.50));
arg.add("%CARD%");
String sql = "SELECT * FROM PRODUCT WHERE PRICE > ? AND NAME LIKE ?";
DBServices dbServices = new DBServices();
...
factory.load(dbServices.getResultSet(sql, arg));
dbServices.release(true);
List products = factory.getObjectList();
...
Usually I keep sql in .properties or .xml files and add WHERE clause based on users selection.
There are several objects in JULP which give you some convinient methods to do that.
- Running in disconnected mode: You can populate your objects from database or any other source, modify them, create new ones
and then serialize them. Later you can restore them, connect to database or send the objects to application server and apply the changes.
- Ability to persist POJO (Plain Java Objects): Yes, you need to extend org.julp.AbstractDomainObject, however this is not the only way.
- Generating UPDATE only for the columns which has been changed
- Optimistic concurrency locking: WHERE clause for UPDATE and DELETE is generated using settings
KEY_COLUMNS
KEY_AND_MODIFIED_COLUMNS
KEY_AND_UPDATEBLE_COLUMNS
It means even if a table has no TIMESTAMP or DATETIME or version column it's still possible to use Optimistic concurrency locking.
- Data Modification Sequence: when you modify many objects once, you can specify order of modification,
for example you can specify to do DELETEs first, then UPDATEs, then INSERTs (any order)
...
ProductFactory factory = new ProductFactory(Product.class);
...
char[] dataModificationSequence = new char[3];
dataModificationSequence[0] = ProductFactory.DATA_MODIFICATION_SEQUENCE_DELETE;
dataModificationSequence[1] = ProductFactory.DATA_MODIFICATION_SEQUENCE_UPDATE;
dataModificationSequence[2] = ProductFactory.DATA_MODIFICATION_SEQUENCE_INSERT;
factory.setDataModificationSequence(dataModificationSequence);
- You can append results of SELECT to object list instead of replacing previous result, just convenient method, works like UNION ALL
- Pagination support: you can send to client or display just certain number of records:
...
ProductFactory factory = new ProductFactory(Product.class);
...
factory.load(...
...
factory.setPageSize(20);
PageHolder page = this.getPage(1);
System.out.println("\nTotal records: " + page.getObjectsTotal() + ", Page " + page.getPageNumber() + " of " + page.getPagesTotal() + "\n");
Iterator iter = page.getPage().iterator();
while (iter1.hasNext()){
Product product = (Product) iter.next();
System.out.println(product);
}
...
- JULP is based on DAO pattern, so if some day you will decide to move to another framework it should be relatively simple.
- More...