DescendIntoTranslator

Translator API provides a special way of storing and retrieving objects. In fact the actual class is not stored in the database. Instead the information from that class is stored in a primitive object (object array) and the class is recreated during instantiation or activation.

Let's look how queries handle translated classes. Diagnostics system will help us to see, what is going on.

In our example class Car is configured to be saved and retrieved with CarTranslator class. CarTranslator saves only car model information appending it with the production date.

CarTranslator.java
01/* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com */ 02package com.db4odoc.diagnostics; 03 04import com.db4o.*; 05import com.db4o.config.*; 06 07public class CarTranslator 08 implements ObjectConstructor { 09 public Object onStore(ObjectContainer container, 10 Object applicationObject) { 11 Car car =(Car)applicationObject; 12 13 String fullModel; 14 if (hasYear(car.getModel())){ 15 fullModel = car.getModel(); 16 } else { 17 fullModel = car.getModel() + getYear(car.getModel()); 18 } 19 return new Object[]{fullModel}; 20 } 21 22 private String getYear(String carModel){ 23 if (carModel.equals("BMW")){ 24 return " 2002"; 25 } else { 26 return " 1999"; 27 } 28 29 } 30 31 private boolean hasYear(String carModel){ 32 return false; 33 } 34 35 public Object onInstantiate(ObjectContainer container, Object storedObject) { 36 Object[] raw=(Object[])storedObject; 37 String model=(String)raw[0]; 38 return new Car(model); 39 } 40 41 public void onActivate(ObjectContainer container, 42 Object applicationObject, Object storedObject) { 43 } 44 45 public Class storedClass() { 46 return Object[].class; 47 } 48}

TranslatorDiagListener is implemented to help us filter only those diagnostic messages, that concern translated classes (filtering diagnostics messages is explained in Diagnostic Messages Filter chapter).

We did not get any diagnostic messages here and the result shows the stored cars with extended model values.

To test Native Queries we will use the predicate, which retrieves only cars, produced in year 2002:

NewCarModel.java
01/* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com */ 02package com.db4odoc.diagnostics; 03 04import com.db4o.query.Predicate; 05 06public class NewCarModel extends Predicate<Car> { 07 public boolean match(Car car) { 08 return ((Car)car).getModel().endsWith("2002"); 09 } 10}
DiagnosticExample.java: retrieveTranslatedCarsNQ
01private static void retrieveTranslatedCarsNQ() { 02 Configuration configuration = Db4o.newConfiguration(); 03 configuration.diagnostic().addListener(new TranslatorDiagListener()); 04 configuration.exceptionsOnNotStorable(true); 05 configuration.objectClass(Car.class).translate(new CarTranslator()); 06 configuration.objectClass(Car.class).callConstructor(true); 07 ObjectContainer container = Db4o.openFile(configuration, DB4O_FILE_NAME); 08 try { 09 ObjectSet result = container.query(new NewCarModel()); 10 listResult(result); 11 } finally { 12 container.close(); 13 } 14 }

A diagnostic message should appear pointing out, that the query is not correct in our case. Let's try  to correct it using unoptimized NQ and evaluations.

DiagnosticExample.java: retrieveTranslatedCarsNQUnopt
01private static void retrieveTranslatedCarsNQUnopt() { 02 Configuration configuration = Db4o.newConfiguration(); 03 configuration.optimizeNativeQueries(false); 04 configuration.diagnostic().addListener(new TranslatorDiagListener()); 05 configuration.exceptionsOnNotStorable(true); 06 configuration.objectClass(Car.class).translate(new CarTranslator()); 07 configuration.objectClass(Car.class).callConstructor(true); 08 ObjectContainer container = Db4o.openFile(configuration, DB4O_FILE_NAME); 09 try { 10 ObjectSet result = container.query(new NewCarModel()); 11 listResult(result); 12 } finally { 13 container.close(); 14 } 15 }

In both cases we the results are correct. Native Query optimization cannot be used with the translated classes, because the actual values of the translated fields are only known after instantiation and activation. That also means that translated classes can have a considerable impact on database performance and should be used with care.