ObJectRelationalBridge
BRIDGING JAVA OBJECTS AND RELATIONAL DATABASES


defining type- and value conversions

introduction

A typical problem with O/R tools are mismatching datatypes: a class of the domain model has a attribute of type boolean but the corresponding database table stores this attribute in a column of type bit or int.

This example explains how OJB allows you to define ConversionStrategies that do the proper translation of types and values.

The source code of this example is included in the OJB source distribution and resides in the package test.ojb.broker.

the problem

The class test.ojb.broker.Article contains an attribute isSelloutArticle of type boolean:

public class Article implements InterfaceArticle
{
    protected int articleId;
    protected String articleName;
    
    /** maps to db-column Auslaufartikel of type int */
    protected boolean isSelloutArticle;

    ...
}

The coresponding table uses an int column (Auslaufartikel) to store this attribute:

CREATE TABLE Artikel (
    Artikel_Nr         INT PRIMARY KEY,
    Artikelname        CHAR(60),
    Lieferanten_Nr     INT,
    Kategorie_Nr       INT,
    Liefereinheit      CHAR(30),
    Einzelpreis        DECIMAL,
    Lagerbestand       INT,
    BestellteEinheiten INT,
    MindestBestand     INT,
    Auslaufartikel     INT
  )

the solution

OJB allows to provide user defined ConversionStrategies that do the appropiate mapping. For the above mentioned problem I defined the following class ArticleConversionStrategy. It implements the interface ojb.broker.ConversionStrategy which provides to methods: javaToSql and sqlToJava.

The method sqlToJava is a callback that is within the OJB broker when Object attributes are read in from JDBC resultsets. The ConversionStrategy is defined per class. Thus we have to implement behaviour for all persistent attributes of the class. In this case I just implement special behaviour for the attribute isSelloutArticle, for all other attributes the input value is returned unmodified.

But if this method is called for the attribute isSelloutArticle it maps the incoming (from the JDBC resultset) Integer values to the corresponding Boolean values. The mapping from Boolean values to the attributes primitive type boolean is done by the OJB broker internally by means of Java reflection.

The method javaToSql is used to decribe the reverse conversion for inserts and updates of new or modified objects.

public class ArticleConversionStrategy implements ojb.broker.ConversionStrategy
{

    private Integer i_true  = new Integer(1);
    private Integer i_false = new Integer(0);

    private Boolean b_true = new Boolean(true);
    private Boolean b_false = new Boolean(false);



    public Object javaToSql(Object source, FieldDescriptor fld)
    {
        if (fld.getPersistentField().getName().equals("isSelloutArticle"))
        {
            if (source.equals(b_true)) return i_true;
            else return i_false;
        }
        else return source;
    }

    public Object sqlToJava(Object source, FieldDescriptor fld)
    {
        if (fld.getPersistentField().getName().equals("isSelloutArticle"))
        {
            if (source.equals(i_true)) return b_true;
            else return b_false;
        }
        else return source;
    }
}

There is only one thing left to do: we must tell OJB to use this ConversionStrategy for the Article class. This is done in the XML Repository. The ClassDescriptor allows to define a <conversionStrategy> element declaring the fully qualified Strategy class.

<!-- Definitions for test.ojb.broker.Article -->
   <ClassDescriptor id="1">
      <class.name>test.ojb.broker.Article</class.name>
      <class.proxy>test.ojb.broker.ArticleProxy</class.proxy>
      <class.extent>test.ojb.broker.BookArticle</class.extent>
      <class.extent>test.ojb.broker.CdArticle</class.extent>
      <table.name>Artikel</table.name>
      <conversionStrategy>test.ojb.broker.ArticleConversionStrategy</conversionStrategy>
      ...

      <FieldDescriptor id="10">
         <field.name>isSelloutArticle</field.name>
         <column.name>Auslaufartikel</column.name>
         <jdbc_type>INT</jdbc_type>
      </FieldDescriptor>
      ...

   </ClassDescriptor>

$FOOTER$