ExoLab     OpenEJB     OpenJMS     OpenORB     Castor     Tyrex     
 

Main
  Home
  Download
  API
  Schema
  Mailing Lists
  CVS / Bugzilla
  Support

XML
  Using XML
  Source Generator
  Schema Support
  XML Mapping
  XML FAQ

JDO
  Using JDO
  JDO Config
  Types
  JDO Mapping
  JDO FAQ
  Other Features

Advanced JDO
  OQL
  Trans. & Locks
  Design
  KeyGen
  Long Trans.
  Nested Attrs.
  Pooling Examples
  Blobs and PostgreSQL

More
  Presentations
  The Examples
  Extras and 3rd Party Tools
  Test Framework -- JDO
  Test Framework -- XML
  Configuration
  Tips & Tricks
  Full JavaDoc

About
  License
  Contributors
  Status, Todo
  Changelog
  Library
  Contact

  



Types
Castor XML
Castor JDO
Castor DAX
The Field Mapping
SQL Type Conversion
Parameterized Type Convertors
BLOB and CLOB Types

Types

The Castor type mechanism assures proper conversion between Java types and external types.

Castor XML

Castor XML converts all Java fields into XML element and attribute values.

Castor JDO

Castor JDO converts Java fields into SQL columns which are persisted through the JDBC driver. Due to implementation details, the field type expected by the JDBC driver is not always the field type defined for the mapped object.

The most common occurrences of mistyping is when using fields of type FLOAT, DOUBLE, NUMERIC and DECIMAL. SQL type FLOAT actually maps to Java type Double. SQL type NUMERIC and DECIMAL map to Java type BigDecimal.

When such an inconsistency occurs, Castor JDO will throw an IllegalArgumentException during object persistence with a message indicating the two conflicting type.

In order to avoid runtime exceptions we recommend explicitly specifying types in the mapping file using the SQL typing convention, see SQL Type Conversion

Castor DAX

Castor DAX converts all Java fields into LDAP attribute values. LDAP attribute values are always textual and represented as the string value of the field, e.g. "5" or "true".

LDAP attributes may also contain binary values. When storing byte arrays or serialized Java objects, DAX will store them as byte arrays.

The Field Mapping

The field element includes an optional attribute called type which can be used to specify the Java type of the field. This attribute is optional since Castor can always derive the exact Java type from the class definition.

We highly recommend that developers use the type field in their mapping file as a means to provide static type checking. When loading a mapping file Castor will compare the actual Java type with the type specified in the mapping and complain about inconsistencies.

The field type can be specified either given the full class name (e.g. java.lang.Integer) or using a short name. The following table lists all the acceptable short names and the Java types they represent:

short namePrimitive type?Java Class
big-decimalNjava.math.BigDecimal
booleanYjava.lang.Boolean.TYPE
byteYjava.lang.Byte.TYPE
bytesNbyte[]
charYjava.lang.Character.TYPE
charsNchar[]
clobNjava.sql.Clob
dateNjava.util.Date
doubleYjava.lang.Double.TYPE
floatYjava.lang.Float.TYPE
integerYjava.lang.Integer.TYPE
localeNjava.util.Locale
longYjava.lang.Long.TYPE
otherNjava.lang.Object
shortYjava.lang.Short.TYPE
stringNjava.lang.String
stringsNString[]
streamNjava.io.InputStream

SQL Type Conversion

Castor JDO uses the JDBC getObject/setObject methods in order to retrieve and set fields. These methods do not perform automatic type conversion, often resulting in unexpected behavior. For example, when using a NUMERIC field with direct JDBC access, application developers tend to call getInteger() or getFloat(), but the Java object returned from a call to getObject is often a java.math.BigDecimal.

Castor JDO implements automatic type conversion between Java and SQL. For this mechanism to work, the mapping file must specify the SQL type being used for Castor to employ the proper convertor. If no SQL type is specified, no conversion will occur, possibly resulting in an IllegalArgumentException being thrown.

SQL types are specified with the sql-type attribute using either the default Java type returned by the JDBC driver (e.g. java.lang.Integer or the proper SQL type name (without precision). The following table lists the supported SQL type names and the corresponding Java types:

SQL TypeJava Type
bigintjava.lang.Long
binarybyte[]
bitjava.lang.Boolean
blobjava.io.InputStream
charjava.lang.String
clobjava.sql.Clob
datejava.sql.Date
decimaljava.math.BigDecimal
doublejava.lang.Double
floatjava.lang.Double
integerjava.lang.Integer
longvarbinarybyte[]
longvarcharjava.lang.String
numericjava.math.BigDecimal
realjava.lang.Float
smallintjava.lang.Short
timejava.sql.Time
timestampjava.sql.Timestamp
tinyintjava.lang.Byte
varbinarybyte[]
varcharjava.lang.String

The following example illustrates how to specify SQL type in field mapping:

  <field name="prodId" type"integer">
    <sql name="prod_id" type="numeric"/>
  </field>

Parameterized Type Convertors

Some of the type convertors may have a string parameter, which changes the conversion algorithm. The parameter is specified in square brackets after the SQL type, for example:

  <field name="active" type="boolean">
    <sql name="acc_active" type="char[01]"/>
  </field>
where "0" is the character value for false and "1" is the character value for true

In the above example the first of four parameterized type convertors is used, "boolean->char" convertor. The parameter must have length 2, the first character is the value for false, the second character is the value for true. The default value is "FT". The actual SQL type should be char(1).

The second convertor is "date->char". Its parameter must be a correct pattern for SimpleDateFormat. For example:

  <field name="dateOfBirth" type="date">
    <sql name="pers_dob" type="char[MMM d, yyyy]"/>
  </field>

If the parameter is not specified, the conversion is performed using toString() method of the Date class.

The third and the fourth convertors are "date->integer" and "date->numeric". Their parameters are also patterns having syntax based on the SimpleDateFormat syntax, but repeated characters are eliminated. The following table shows the substitution rules that are used to obtain the SimpleDateFormat pattern from the parameter.

Y,yyyyyyear
MMMmonth in year
D,dddday in month
h,HHHhour in day (0~23)
mmmminute in hour
ssssecond in minute
SSSSmillisecond
For example, "YMD" parameter is expanded to "yyyyMMdd" SimpleDateFormat pattern, "YMDhmsS" parameter is expanded to "yyyyMMddHHmmssSSS" SimpleDateFormat pattern. The length of the expanded parameter gives the minimal number of decimal digits that the actual SQL type must support. The default value of the parameter is "YMD".

BLOB and CLOB Types

BLOB and CLOB stand for binary and character large objects (in Sybase IMAGE and TEXT types, respectively), which means that most likely you don't want to load the whole objects into memory, but to read/write them as streams. Usually these types are not comparable via WHERE clause of SQL statement, that is why you should disable dirty checking for such fields, e.g.

  <field name="text" type="string">
    <sql name="text" type="clob" dirty="ignore" />
  </field>
In this example CLOB field will be read as String. This may cause OutOfMemoryError, if the text is really large, but in many cases mapping CLOB to String is acceptable. The advantage of this way is that we obtain Serializable value that can be passed via RMI. Similarly you can map BLOB and CLOB to byte[] and char[] types, respectively:
  <field name="photo" type="bytes">
    <sql name="photo" type="blob" dirty="ignore" />
  </field>
  <field name="resume" type="chars">
    <sql name="resume" type="clob" dirty="ignore" />
  </field>

Now assume that this way is not acceptable. The natual mapping for BLOB type is java.io.InputStream, and it is supported by Castor:

  <field name="cdImage" type="stream">
    <sql name="cd_image" type="blob" dirty="ignore" />
  </field>
The natual mapping for CLOB type is java.io.Reader, but it is not supported by Castor, because java.io.Reader doesn't provide information about the length of the stream, which is necessary for JDBC driver (at least for Oracle driver) to write the value to the database. This is why CLOB type is mapped to java.sql.Clob:
  <field name="novel" type="clob">
    <sql name="novel" type="clob" dirty="ignore" />
  </field>
When you read data from the database, you can use getCharacterStream() method to obtain java.io.Reader from java.sql.Clob. When you write data to the database, you can either use the helper class org.exolab.castor.jdo.engine.ClobImpl to construct java.sql.Clob from java.io.Reader and the length:
  object.setClob(new ClobImpl(new FileReader(file), file.length());
or implement java.sql.Clob interface yourself.

But we aware of the followng restriction: if you map BLOB to java.io.InputStream or CLOB to java.sql.Clob, you should set turn caching off for the Java class containing those values, e.g.:

  <class ...>
    <cache-type type="none"/>
      ...
      <field name="novel" type="clob">
        <sql name="novel" type="clob" dirty="ignore" />
      </field>
  </class>
Blob and Clob values cannot be cached, because they are alive only while ResultSet that produced them is open. In particular this means that you cannot use dirty checking for long transactions with such classes.

 
   
  
   
 


Copyright ) 1999-2003 ExoLab Group. All rights reserved.
 
Java, EJB, JDBC, JNDI, JTA, Sun, Sun Microsystems are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and in other countries. XML, XML Schema, XSLT and related standards are trademarks or registered trademarks of MIT, INRIA, Keio or others, and a product of the World Wide Web Consortium. All other product names mentioned herein are trademarks of their respective owners.