You are here: Advanced Features > Callbacks > Possible Usecases > Autoincrement

Autoincrement

db4o does not deliver a field auto increment feature, which is common in RDBMS. Normally you don't need any additional ids, since db4o manages objects by object-identity. However cases where you have disconnected objects, you need additional ids. One of then possibilities it to use auto incremented ids.

If your application logic requires this feature you can implement it using external callbacks. One of the possible solutions is presented below. Note that this example only works in embedded-mode.

This example assumes that all object which need an auto incremented id are subclasses of the IDHolder class. This class contains the auto-incremented id.

private  int id;
public  int getId() {
    return id;
}

public  void setId(int id) {
    this.id = id;
}
IDHolder.java: id holder

First create a class which keeps the state of the auto-increment numbers. For example a map which keeps the latest auto incremented id for each class.

private  static  class PersistedAutoIncrements {
 private  final Map<Class, Integer> currentHighestIds = new HashMap<Class, Integer>();

    public  int nextNumber(Class forClass) {
        Integer number = currentHighestIds.get(forClass);
        if (null == number) {
            number = 0;
        }
        number += 1;
        currentHighestIds.put(forClass,number);
        return number;
    }
}
AutoIncrement.java: persistent auto increment

Then create two methods, which are called later. One which returns the next auto-incremented id for a certain class. Another which stores the current state of the auto-increments.

public  synchronized  int getNextID(Class forClass) {
       PersistedAutoIncrements incrementState = ensureLoadedIncrements();
       return incrementState.nextNumber(forClass);
}

   public  synchronized  void storeState(){
       if(null!=state){
           container.ext().store(state,2);            
       }
   }
AutoIncrement.java: getting the next id and storing state

The last part is to ensure that the existing auto-increments are loaded from the database. Or if not existing a new instance is created.

private PersistedAutoIncrements ensureLoadedIncrements() {
    if(null==state){
        state = loadOrCreateState();
    }
    return state;

}

private PersistedAutoIncrements loadOrCreateState() {
    ObjectSet<PersistedAutoIncrements> existingState = container.query(PersistedAutoIncrements.class);
    if(0==existingState.size()){
        return  new PersistedAutoIncrements(); 
    } else  if(1==existingState.size()){
        return existingState.get(0);
    } else{
        throw  new IllegalStateException("Cannot have more than one state stored in database");
    }
}
AutoIncrement.java: load the state from the database

Now it's time to use the callbacks. Every time when a new object is created, assign a new id. For this the creating-event is perfect. When commiting also make the auto increment-state persistent, to ensure that no id is used twice.

final AutoIncrement increment = new AutoIncrement(container);
EventRegistry eventRegistry = EventRegistryFactory.forObjectContainer(container);
eventRegistry.creating().addListener(new EventListener4<CancellableObjectEventArgs>() {
    public  void onEvent(Event4<CancellableObjectEventArgs> event4,
                        CancellableObjectEventArgs objectArgs) {
        if(objectArgs.object() instanceof IDHolder){
            IDHolder idHolder = (IDHolder) objectArgs.object();
            idHolder.setId(increment.getNextID(idHolder.getClass()));
        }
    }
});
eventRegistry.committing().addListener(new EventListener4<CommitEventArgs>() {
    public  void onEvent(Event4<CommitEventArgs> commitEventArgsEvent4,
                        CommitEventArgs commitEventArgs) {
        increment.storeState();
    }
});
AutoIncrementExample.java: use events to assign the ids

Last, don't forget to index the id-field. Otherwise looks-ups will be slow.

configuration.common().objectClass(IDHolder.class).objectField("id").indexed(true);
AutoIncrementExample.java: index the id-field