Static fields API

By default db4o does not persist static fields. Normally this is not necessary as static values are set for a class, not for an object. However you can set up db4o to store static fields if you need to implement constant or enumeration:

Java: Db4o.configure().objectClass(Foo.class).persistStaticFieldValues()

Do not use this option unnecessarily, as it will slow down the process of opening database files and the stored objects will occupy space in the database file.

This option does not have any eaffect on primitive types (int, boolean, etc). Use their object alternatives instead (Integer, Boolean, etc).

When this setting is on for a specific class, all non-primitive-typed static field values of this class are stored the first time an object of the class is stored, and restored, every time a database file is opened afterwards, after class meta information is loaded for this class (when the class objects are retrieved with a query, for example).

A good example of non-primitive constant type is type-safe enumeration implementation:

PilotCategories.java
01/* Copyright (C) 2004 - 2006 db4objects Inc. http://www.db4o.com */ 02 03package com.db4odoc.staticfields; 04 05 06public class PilotCategories { 07 private String qualification = null; 08 public final static PilotCategories WINNER=new PilotCategories("WINNER"); 09 public final static PilotCategories TALENTED=new PilotCategories("TALENTED"); 10 public final static PilotCategories AVERAGE=new PilotCategories("AVERAGE"); 11 public final static PilotCategories DISQUALIFIED=new PilotCategories("DISQUALIFIED"); 12 13 private PilotCategories(String qualification){ 14 this.qualification = qualification; 15 } 16 17 public PilotCategories(){ 18 19 } 20 21 public void testChange(String qualification){ 22 this.qualification = qualification; 23 } 24 public String toString() { 25 return qualification; 26 } 27 28}

Let's use it with

Pilot.java
01/* Copyright (C) 2004 - 2006 db4objects Inc. http://www.db4o.com */ 02 03package com.db4odoc.staticfields; 04 05 06public class Pilot { 07 private String name; 08 private PilotCategories category; 09 10 public Pilot(String name,PilotCategories category) { 11 this.name=name; 12 this.category=category; 13 } 14 15 public PilotCategories getCategory() { 16 return category; 17 } 18 19 public String getName() { 20 return name; 21 } 22 23 public String toString() { 24 return name+"/"+category; 25 } 26}

StaticFieldExample.java: setPilotsSimple
01public static void setPilotsSimple() { 02 System.out 03 .println("In the default setting, static constants are not continously stored and updated."); 04 new File(YAPFILENAME).delete(); 05 ObjectContainer db = Db4o.openFile(YAPFILENAME); 06 try { 07 db.set(new Pilot("Michael Schumacher", PilotCategories.WINNER)); 08 db.set(new Pilot("Rubens Barrichello", PilotCategories.TALENTED)); 09 } finally { 10 db.close(); 11 } 12 }

We can try to save pilots with the default db4o settings:

StaticFieldExample.java: checkPilots
01public static void checkPilots() { 02 ObjectContainer db = Db4o.openFile(YAPFILENAME); 03 try { 04 ObjectSet result = db.query(Pilot.class); 05 for (int x = 0; x < result.size(); x++) { 06 Pilot pilot = (Pilot) result.get(x); 07 if (pilot.getCategory() == PilotCategories.WINNER) { 08 System.out.println("Winner pilot: " + pilot); 09 } else if (pilot.getCategory() == PilotCategories.TALENTED) { 10 System.out.println("Talented pilot: " + pilot); 11 } else { 12 System.out.println("Uncategorized pilot: " + pilot); 13 } 14 } 15 } finally { 16 db.close(); 17 } 18 }

That does not work however. We will have to explicitly point out, which class's static fields we want to save:

StaticFieldExample.java: setPilotsStatic
01public static void setPilotsStatic() { 02 System.out 03 .println("The feature can be turned on for individual classes."); 04 Db4o.configure().objectClass( 05 "com.db4odoc.f1.staticfields.PilotCategories") 06 .persistStaticFieldValues(); 07 new File(YAPFILENAME).delete(); 08 ObjectContainer db = Db4o.openFile(YAPFILENAME); 09 try { 10 db.set(new Pilot("Michael Schumacher", PilotCategories.WINNER)); 11 db.set(new Pilot("Rubens Barrichello", PilotCategories.TALENTED)); 12 } finally { 13 db.close(); 14 } 15 }

StaticFieldExample.java: checkPilots
01public static void checkPilots() { 02 ObjectContainer db = Db4o.openFile(YAPFILENAME); 03 try { 04 ObjectSet result = db.query(Pilot.class); 05 for (int x = 0; x < result.size(); x++) { 06 Pilot pilot = (Pilot) result.get(x); 07 if (pilot.getCategory() == PilotCategories.WINNER) { 08 System.out.println("Winner pilot: " + pilot); 09 } else if (pilot.getCategory() == PilotCategories.TALENTED) { 10 System.out.println("Talented pilot: " + pilot); 11 } else { 12 System.out.println("Uncategorized pilot: " + pilot); 13 } 14 } 15 } finally { 16 db.close(); 17 } 18 }

As it was mentioned before, it is important to keep static values in one place and do not allow different objects to modify them. If we try to change static value from the referencing object:

StaticFieldExample.java: updatePilots
01public static void updatePilots() { 02 System.out.println("Updating PilotCategory in pilot reference:"); 03 ObjectContainer db = Db4o.openFile(YAPFILENAME); 04 try { 05 ObjectSet result = db.query(Pilot.class); 06 for (int x = 0; x < result.size(); x++) { 07 Pilot pilot = (Pilot) result.get(x); 08 if (pilot.getCategory() == PilotCategories.WINNER) { 09 System.out.println("Winner pilot: " + pilot); 10 PilotCategories pc = pilot.getCategory(); 11 pc.testChange("WINNER2006"); 12 db.set(pilot); 13 } 14 } 15 printCategories(db); 16 } finally { 17 db.close(); 18 } 19 }

the value just does not change.

In order to update static field we will have to do that explicitly:

StaticFieldExample.java: updatePilotCategories
01public static void updatePilotCategories() { 02 System.out.println("Updating PilotCategories explicitly:"); 03 ObjectContainer db = Db4o.openFile(YAPFILENAME); 04 try { 05 ObjectSet result = db.query(PilotCategories.class); 06 for (int x = 0; x < result.size(); x++) { 07 PilotCategories pc = (PilotCategories) result.get(x); 08 if (pc == PilotCategories.WINNER) { 09 pc.testChange("WINNER2006"); 10 db.set(pc); 11 } 12 } 13 printCategories(db); 14 } finally { 15 db.close(); 16 } 17 System.out.println("Change the value back:"); 18 db = Db4o.openFile(YAPFILENAME); 19 try { 20 ObjectSet result = db.query(PilotCategories.class); 21 for (int x = 0; x < result.size(); x++) { 22 PilotCategories pc = (PilotCategories) result.get(x); 23 if (pc == PilotCategories.WINNER) { 24 pc.testChange("WINNER"); 25 db.set(pc); 26 } 27 } 28 printCategories(db); 29 } finally { 30 db.close(); 31 } 32 }

StaticFieldExample.java: checkPilots
01public static void checkPilots() { 02 ObjectContainer db = Db4o.openFile(YAPFILENAME); 03 try { 04 ObjectSet result = db.query(Pilot.class); 05 for (int x = 0; x < result.size(); x++) { 06 Pilot pilot = (Pilot) result.get(x); 07 if (pilot.getCategory() == PilotCategories.WINNER) { 08 System.out.println("Winner pilot: " + pilot); 09 } else if (pilot.getCategory() == PilotCategories.TALENTED) { 10 System.out.println("Talented pilot: " + pilot); 11 } else { 12 System.out.println("Uncategorized pilot: " + pilot); 13 } 14 } 15 } finally { 16 db.close(); 17 } 18 }

We can see that the reference has changed correctly.

What about deletion? Nothing is new here. We can delete static fields from the referenced object, or directly from the database:

StaticFieldExample.java: deleteTest
01public static void deleteTest() { 02 ObjectContainer db = Db4o.openFile(YAPFILENAME); 03 db.ext().configure().objectClass(Pilot.class).cascadeOnDelete(true); 04 try { 05 System.out.println("Deleting Pilots :"); 06 ObjectSet result = db.query(Pilot.class); 07 for (int x = 0; x < result.size(); x++) { 08 Pilot pilot = (Pilot) result.get(x); 09 db.delete(pilot); 10 } 11 printCategories(db); 12 System.out.println("Deleting PilotCategories :"); 13 result = db.query(PilotCategories.class); 14 for (int x = 0; x < result.size(); x++) { 15 db.delete(result.get(x)); 16 } 17 printCategories(db); 18 } finally { 19 db.close(); 20 } 21 }