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 - 2007 db4objects Inc. http://www.db4o.com */ 02 03package com.db4odoc.staticfields; 04 05public class PilotCategories { 06 private String qualification = null; 07 08 public final static PilotCategories WINNER = new PilotCategories( 09 "WINNER"); 10 11 public final static PilotCategories TALENTED = new PilotCategories( 12 "TALENTED"); 13 14 public final static PilotCategories AVERAGE = new PilotCategories( 15 "AVERAGE"); 16 17 public final static PilotCategories DISQUALIFIED = new PilotCategories( 18 "DISQUALIFIED"); 19 20 private PilotCategories(String qualification) { 21 this.qualification = qualification; 22 } 23 24 public PilotCategories() { 25 26 } 27 28 public void testChange(String qualification) { 29 this.qualification = qualification; 30 } 31 32 public String toString() { 33 return qualification; 34 } 35 36}

Let's use it with

Pilot.java
01/* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com */ 02 03package com.db4odoc.staticfields; 04 05public class Pilot { 06 private String name; 07 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: setPilots
01private static void setPilots() { 02 new File(DB4O_FILE_NAME).delete(); 03 ObjectContainer container = database(); 04 if (container != null) { 05 try { 06 container.set(new Pilot("Michael Schumacher", 07 PilotCategories.WINNER)); 08 container.set(new Pilot("Rubens Barrichello", 09 PilotCategories.TALENTED)); 10 } finally { 11 closeDatabase(); 12 } 13 } 14 }

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

StaticFieldExample.java: checkPilots
01private static void checkPilots() { 02 ObjectContainer container = database(); 03 if (container != null) { 04 try { 05 ObjectSet result = container.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 } else if (pilot.getCategory() == PilotCategories.TALENTED) { 11 System.out.println("Talented pilot: " + pilot); 12 } else { 13 System.out.println("Uncategorized pilot: " + pilot); 14 } 15 } 16 } finally { 17 closeDatabase(); 18 } 19 } 20 }

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

StaticFieldExample.java: configure
1private static void configure(){ 2 System.out.println("Saving static fields can be turned on for individual classes."); 3 4 _configuration = Db4o.newConfiguration(); 5 _configuration.objectClass(PilotCategories.class) 6 .persistStaticFieldValues(); 7 }

Try to save and check pilots again - you should see that with this configuration enumeration values are actually correctly bound to their runtime values.

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
01private static void updatePilots() { 02 System.out 03 .println("Updating PilotCategory in pilot reference:"); 04 ObjectContainer container = database(); 05 if (container != null){ 06 try { 07 ObjectSet result = container.query(Pilot.class); 08 for (int x = 0; x < result.size(); x++) { 09 Pilot pilot = (Pilot) result.get(x); 10 if (pilot.getCategory() == PilotCategories.WINNER) { 11 System.out.println("Winner pilot: " + pilot); 12 PilotCategories pc = pilot.getCategory(); 13 pc.testChange("WINNER2006"); 14 container.set(pilot); 15 } 16 } 17 printCategories(container); 18 } finally { 19 closeDatabase(); 20 } 21 } 22 }

the value just does not change. You can check it with the checkPilots method above.

In order to update static field we will have to do that explicitly:
StaticFieldExample.java: updatePilotCategories
01private static void updatePilotCategories() { 02 System.out.println("Updating PilotCategories explicitly:"); 03 ObjectContainer container = database(); 04 if (container != null){ 05 try { 06 ObjectSet result = container.query(PilotCategories.class); 07 for (int x = 0; x < result.size(); x++) { 08 PilotCategories pc = (PilotCategories) result.get(x); 09 if (pc == PilotCategories.WINNER) { 10 pc.testChange("WINNER2006"); 11 container.set(pc); 12 } 13 } 14 printCategories(container); 15 } finally { 16 closeDatabase(); 17 } 18 } 19 System.out.println("Change the value back:"); 20 container = database(); 21 if (container != null){ 22 try { 23 ObjectSet result = container.query(PilotCategories.class); 24 for (int x = 0; x < result.size(); x++) { 25 PilotCategories pc = (PilotCategories) result.get(x); 26 if (pc == PilotCategories.WINNER) { 27 pc.testChange("WINNER"); 28 container.set(pc); 29 } 30 } 31 printCategories(container); 32 } finally { 33 closeDatabase(); 34 } 35 } 36 }
Please, check the result with the checkPilots method. You will see that the reference has changed correctly.

What about deletion? Similar to update we cannot delete static fields from the referenced object, but we can delete them directly from the database:

StaticFieldExample.java: addDeleteConfiguration
1private static void addDeleteConfiguration(){ 2 if (_configuration != null){ 3 _configuration.objectClass(Pilot.class).cascadeOnDelete(true); 4 } 5 }

StaticFieldExample.java: deleteTest
01private static void deleteTest() { 02 // use delete configuration 03 ObjectContainer container = database(); 04 if (container != null){ 05 try { 06 System.out.println("Deleting Pilots :"); 07 ObjectSet result = container.query(Pilot.class); 08 for (int x = 0; x < result.size(); x++) { 09 Pilot pilot = (Pilot) result.get(x); 10 container.delete(pilot); 11 } 12 printCategories(container); 13 System.out.println("Deleting PilotCategories :"); 14 result = container.query(PilotCategories.class); 15 for (int x = 0; x < result.size(); x++) { 16 container.delete(result.get(x)); 17 } 18 printCategories(container); 19 } finally { 20 closeDatabase(); 21 } 22 } 23 }