You are here: Implementation Strategies > Refactoring And Schema Evolution > Refactoring API

Refactoring API

Db4o provides special API which can help you to move classes between packages (Java)/namespaces(.NET), rename classes or fields:

Java:
Db4o.configure()
.objectClass("package.class").rename("newPackage.newClass");
Db4o.configure().objectClass("package.class").
objectField("oldField").rename("newField");

The safe order of actions for rename calls is:

  1. Backup you database and application
  2. Close all open objectContainers if any
  3. Rename classes or fields or copy classes to the new package/namespace in your application. (Do not remove old classes yet).
  4. Issue ObjectClass#rename and objectField#rename calls without having an ObjectContainer open.
  5. Open database file and close it again without actually working with it.
  6. Remove old classes (if applicable).

After that you will only see the new classes/fields in ObjectManager, the old ones will be gone.

Let's look how it works on an example. We will use initial class Pilot:

Pilot.java
/**//* Copyright (C) 2004 - 2007 Versant Inc. http://www.db4o.com */

package com.db4odoc.refactoring;

public class Pilot  {
  private String name;

  public Pilot(String name)  {
    this.name = name;
  }

  public String getName()  {
    return name;
  }

  public String toString()  {
    return name;
  }
}

and change it to the new class PilotNew renaming field and changing package/namespace at the same time:

PilotNew.java
/**//* Copyright (C) 2004 - 2007 Versant Inc. http://www.db4o.com */

package com.db4odoc.refactoring;

public class PilotNew  {
  private String identity;

  private int points;

  public PilotNew(String name, int points)  {
    this.identity = name;
    this.points = points;
  }

  public String getIdentity()  {
    return identity;
  }

  public String toString()  {
    return identity + "/" + points;
  }
}

First let's create a database and fill it with some values:

RefactoringExample.java: setObjects
private static void setObjects() {
    new File(DB4O_FILE_NAME).delete();
    ObjectContainer container = Db4o.openFile(DB4O_FILE_NAME);
    try  {
      Pilot pilot = new Pilot("Rubens Barrichello");
      container.store(pilot);
      pilot = new Pilot("Michael Schumacher");
      container.store(pilot);
    } finally  {
      container.close();
    }
  }

RefactoringExample.java: checkDB
private static void checkDB() {
    ObjectContainer container = Db4o.openFile(DB4O_FILE_NAME);
    try  {
      ObjectSet result=container.queryByExample(new Object());
          listResult(result);
    } finally  {
      container.close();
    }
  }

We already have PilotNew class so we can go on with renaming:

RefactoringExample.java: changeClass
private static void changeClass() {
    Configuration configuration = Db4o.newConfiguration();
    configuration.objectClass(Pilot.class).rename("com.db4odoc.f1.refactoring.PilotNew");
    configuration.objectClass(PilotNew.class).objectField("name").rename("identity");
    ObjectContainer container = Db4o.openFile(configuration, DB4O_FILE_NAME);
    container.close();
  }

Now the data for the old Pilot class should be transferred to the new PilotNew class, and "name" field data should be stored in "identity" field.

To make our check more complicated let's add some data for our new class:

RefactoringExample.java: setNewObjects
private static void setNewObjects() {
    ObjectContainer container = Db4o.openFile(DB4O_FILE_NAME);
    try  {
      PilotNew pilot = new PilotNew("Rubens Barrichello",99);
      container.store(pilot);
      pilot = new PilotNew("Michael Schumacher",100);
      container.store(pilot);
    } finally  {
      container.close();
    }
  }

We can check what is stored in the database now:

RefactoringExample.java: retrievePilotNew
private static void retrievePilotNew() {
    ObjectContainer container = Db4o.openFile(DB4O_FILE_NAME);
    try  {
      ObjectSet result = container.query(PilotNew.class);
      listResult(result);
    } finally  {
      container.close();
    }
  }

There is one thing to remember. The rename feature is intended to rename a class from one name to the other. Internally this will rename the meta-information. If you will try to rename class to the name that is already stored in the database, the renaming will fail, because the name is reserved. In our example it will happen if setNewObjects method will be called before changeClass.

Download example code:

Java