Friday, November 5, 2010

Optimistic locking on iBatis

I know that it's little outdated, but I needed this recently on one project
and couldn't find it anywhere in a Ctrl+C / Ctrl+V form.
How to implement optimistic locking under iBatis when there is no standard support for it.

It's quite simple. Implement it by your self.
  • implement custom OptimisticLockException or reuse the one from JPA package: javax.persistence
  • add new db field named 'version' into entity's table. it should be numerical non-null field with default value defined as 1
  • add new field into Entity's class: int version
  • Update DAO interface to throw OptimisticLockException (so anybody using this DAO can change his code accordingly)
public interface EntityDao {
    void createEntity(Entity entity);
    Entity selectEntryById(Long id);
    void updateEntity(Entity entity) throws OptimisticLockException;
    void deleteEntity(Entity entity);
  • Update DAO class to process version fields
public class EntityDaoImpl extends SqlMapClientDaoSupport implements EntityDao {

public void createEntity(final Entity entity) {
    getSqlMapClientTemplate().insert("insertEntity", entity);

public Entity selectEntryById(final Long id) {
    return (Entity) getSqlMapClientTemplate().queryForObject("findEntityById", id);

public void updateEntity(final Entity entity) throws OptimisticLockException {
    final int oldVersion = entity.getVersion();
    final int newVersion = oldVersion + 1;

    final Map<String, Object> params = new HashMap<String, Object>();
    params.put("entity", entity);
    params.put("oldVersion", oldVersion);
    params.put("newVersion", newVersion);

    int updateCount = getSqlMapClientTemplate().update("updateEntity", params);

    if (updateCount == 0) {
        throw new OptimisticLockException("trying to update database with obsolete Entity");


public void deleteEntity(Entity entity) {
    getSqlMapClientTemplate().delete("deleteEntity", entity);
  • Update statements file
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap PUBLIC "-// SQL Map 2.0//EN" "">

 <typeAlias alias="Entity" type="yourPackage.domain.Entity"/>

 <resultMap id="EntityMap" class="Entity">
     <result column="id" property="id"/>
     <result column="value" property="value"/>
     <result column="version" property="version"/>

 <insert id="insertEntity" parameterClass="Entity">
     INSERT INTO entity (id, value, version) VALUES (#id#, #value#, 1)

 <select id="findEntityById" parameterClass="java.lang.Long" resultClass="Entity" resultMap="EntityMap">
         SELECT id, value, version FROM entity WHERE id=#value#

 <update id="updateEntity" parameterClass="java.util.Map">
     UPDATE entity
         AND version=#oldVersion#

 <delete id="deleteEntity" parameterClass="Entity">
     DELETE FROM entity WHERE id=#id#


Monday, May 31, 2010

YES - easy Excel table processing in Java

Not long time ago I was looking for some library that would allow me to easily process data from Excel tables (although I like Apache POI, for my needs it was a little low level API).
But as I was not lucky while searching for a suitable solution I decided to implement a small but effective project (it was a nice facade over POI) that was based on heavy use of annotations.
Thanks to the usage of annotations, the complete code for simple table processing was about 10 to 20 lines long.

You can find some more technical description on this site.

Sunday, May 9, 2010


Not long time ago I needed an implementation of a really fast (constant speed) and small (with as small memory footprint as posible) queue for storing multiple objects (thread safety was not required). For me there were two usable options where each of them fullfilled only one of these two requirements. ArrayList with its size and LinkedList with its speed.

ArrayList was good (from the memory point of view) because it used array as a mean of element storage. Its disadvantage however was that it was not a queue, so the removal of its first element always moves all elements (with the first one excluded) to a lower index. And as the speed of such operation is O(n) this was not acceptable for cases where you had too many elements (my case).

remove firstinsert last
ArrayListO(n)O(1) or O(n) when resizing

The disadvantage of LinkedList (besides its slower insert) was that it wrapped each inserted element into a new wrapper and thus increased the memory usage.

As i needed something better I decided to implement my own queue. And so LinkedArrayQueue was born.

The design was quite simple: to reuse the principle of LinkedList (as this was more closely copying my expectations) and "fix" its memory issues. So instead of creating a wrapper for each new element I was wrapping an array that was suposed to hold the queue elements. When the array was fully written a new wrapper with array was created = O(1). When all elements from an array were polled/removed (O(1)) the array with its wrapper was thrown away = O(1). This way we'll get an insert (O(1)) almost as fast as an insert into an array and also m-times less element wrappers as in the LinkedList (where m means the size of the wrapped array). Also the creation of a new array with its wrapper takes a constant amount of time = O(1).

Here is a graphical representation of this concept:

And here are some interesting results I got on my machine (-Xmx64m, java 1.6.0_16):

inserts before OutOfMemory Errorinsert last speed ns/element (of 1 milion inserts) - aprox. averageremove first speed ns/element (of 500 000 elements) - aprox. average
ArrayList7 634 06860 nanoseconds220 092 nanoseconds
LinkedList2 771 293290 nanoseconds22 nanoseconds
(with array size 128)
15 202 04835 nanoseconds20 nanoseconds

As you can see with the same provided memory I was able to store more elements (in my case I was storing the same Integer n-times) and much faster that it was possible in LinkedList or ArrayList. Also the poll/remove operation was much faster than in ArrayList and only slightly faster than in LinkedList. And that is what I exactly wanted.

So this is the design of my implementation. But if you know of some better (possibly existing) solution just let me know.