Autoincrement

Db4o does not deliver a field autoincrement feature, which is common in RDBMS. If your application logic requires this feature you can implement it using External Callbacks. One of the possible solutions is presented below.

We will need an object to store the last generated ID and to return a new ID on request:

IncrementedId.java
01/* Copyright (C) 2004 - 2006 db4objects Inc. http://www.db4o.com */ 02/* 03 * Singleton class used to keep auotincrement information 04 * and give the next available ID on request 05 */ 06package com.db4odoc.callbacks; 07 08import com.db4o.ObjectContainer; 09import com.db4o.ObjectSet; 10 11public class IncrementedId { 12 private int no; 13 private static IncrementedId ref; 14 15 private IncrementedId() { 16 this.no = 0; 17 } 18 19 // end IncrementedId 20 21 public int getNextID(ObjectContainer db) { 22 no++; 23 db.set(this); 24 return no; 25 } 26 27 // end increment 28 29 public static IncrementedId getIdObject(ObjectContainer db) { 30 // if ref is not assigned yet: 31 if (ref == null) { 32 // check if there is a stored instance from the previous 33 // session in the database 34 ObjectSet os = db.get(IncrementedId.class); 35 if (os.size() > 0) 36 ref = (IncrementedId) os.next(); 37 } 38 39 if (ref == null) { 40 // create new instance and store it 41 System.out.println("Id object is created"); 42 ref = new IncrementedId(); 43 db.set(ref); 44 } 45 return ref; 46 } 47 // end getIdObject 48}

This object generates the simplest ID, which is an autoincremented integer value. You can add your own algorithm to generate more sophisticated ID sequences, like ABC0001DEF.

When you use external callbacks you are not limited to a single object: a callback can apply to any group of objects Thus you can create a sequence of classes sharing the same autoincrement. To distinguish the objects, which will have an autoincremented field, we will use an abstract (MustInherit in VB) class:

CountedObject.java
01/* Copyright (C) 2004 - 2006 db4objects Inc. http://www.db4o.com */ 02/* 03 * This class is used to mark classes that need to get an autoincremented ID 04 */ 05package com.db4odoc.callbacks; 06 07 08public abstract class CountedObject { 09 int id; 10 11 public void setId(int id){ 12 this.id = id; 13 } 14 15 public int getId(){ 16 return id; 17 } 18}

Each object extending CountedObject will get an autoincremented ID. For example:

TestObject.java
01/* Copyright (C) 2004 - 2006 db4objects Inc. http://www.db4o.com */ 02package com.db4odoc.callbacks; 03 04public class TestObject extends CountedObject{ 05 String name; 06 07 public TestObject(String name) { 08 this.name = name; 09 } 10 11 public String toString() { 12 return name+"/"+id; 13 } 14 15}

It is only left to register the callback with the creating() event:

AutoIncExample.java: registerCallback
01public static void registerCallback(final ObjectContainer db){ 02 EventRegistry registry = EventRegistryFactory.forObjectContainer(db); 03 // register an event handler, which will assign autoincremented IDs to any 04 // object extending CountedObject, when the object is created 05 registry.creating().addListener(new EventListener4() { 06 public void onEvent(Event4 e, EventArgs args) { 07 ObjectEventArgs queryArgs = ((ObjectEventArgs) args); 08 Object obj = queryArgs.object(); 09 // only for the objects extending the CountedObject 10 if (obj instanceof CountedObject){ 11 ((CountedObject)obj).setId(getNextId(db)); 12 } 13 } 14 }); 15 }
AutoIncExample.java: getNextId
1private static int getNextId(ObjectContainer db) { 2 // this function retrieves the next available ID from 3 // the IncrementedId object 4 IncrementedId r = IncrementedId.getIdObject(db); 5 int nRoll; 6 nRoll = r.getNextID(db); 7 8 return nRoll; 9 }

You can test the results with the following code:

AutoIncExample.java: storeObjects
1public static void storeObjects(ObjectContainer db){ 2 TestObject test; 3 test = new TestObject("FirstObject"); 4 db.set(test); 5 test = new TestObject("SecondObject"); 6 db.set(test); 7 test = new TestObject("ThirdObject"); 8 db.set(test); 9 }
AutoIncExample.java: retrieveObjects
1public static void retrieveObjects(ObjectContainer db){ 2 ObjectSet result = db.get(new TestObject(null)); 3 listResult(result); 4 }

Please, note that the suggested implementation cannot be used in a multithreaded environment. In such environment you will have to make sure that the IncrementedId class can only be saved to the database once, and that 2 threads cannot independently and simultaneously increment IncrementedId counter.