ExoLab     OpenEJB     OpenJMS     OpenORB     Castor     Tyrex     
 

Main
  Home
  About
  Features
  Download
  API
  Schema
  Castor Forums
  Mailing Lists
  CVS / Bugzilla
  Support
  CastorWiki

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
  LOBs

More
  Presentations
  The Examples
  3rd Party Tools
  JDO Tests
  XML Tests
  Configuration
  Tips & Tricks
  Full JavaDoc
  CastorWiki
  
  

About
  License
  Contributors
  Status, Todo
  Changelog
  Library
  Contact
  Project Name

  



Castor's relation to other specifications
    Does Castor JDO comply with the SUN JSR-000012 specification?
    Is Castor JDO better than EJB CMP?
XML related questions
    Is it possible to make XML marshalling transactionally using Castor?
    Is it possible to do queries on a XML file using Castor?
Technical questions
    Where can I find some examples to start with?
    I have encountered problems using Sun JDBC-ODBC bridge with Castor...
    My get-method for the Collection of dependent objects returns null. Why?
    Should my JDO classes implement some special interface?
    Can Castor automatically create/remove related objects?
    Is Castor JDO using any connection pooling mechanism to improve the overall performance?
    I am getting ClassNotFoundException for my JDO class, but it is in the class path. Why?
    I am getting exception 'the class ... is not persistence capable...'. Why?
    I call db.remove() on the dependent object and commit, but this doesn't work...
    How should I represent string/date/boolean literals in OQL query?
    I get 'java.lang.AbstractMethodError: getBigDecimal' for numeric fields. Why?
    Does Castor support both one-way and two-way relationships?
    I have an object that holds a relation to itself. Does Castor support this?
    Why do I get an ObjectModifiedException when trying to commit a transaction?
    I'm receiving a java.sql.SQLException: ORA-01461
Castor and performance caches
    Sometimes long transaction fails: on update() it is thrown ObjectModifiedException. Why?
    Can I use the cache-type='none' with long transactions?
    What is causing a PersistenceException with long transactions and how do I fix it?
OQL
    Is there any document available for Castor OQL?
    The OQL document describes several phases of development. Which is the current phase?
    Does Castor OQL support sub-queries?
    I cannot get Castor OQL to join two objects for me. Is it supported?
    Can I write a pass-thru OQL?
    Does Castor OQL support struct?
    How do I structure a query using the 'LIKE' expression?
    Does Castor support the SQL 'IN' expression?
Features requests
    Can a foreign key be part of multiple primary keys?
    Is polymorphic collection supported?
Data model issues
    Is it possible to map an object to more than one tables?
    Can an object with the same identity be re-created after being removed in the same transaction?
    What is a dependent object?
    Can a data object involved in many-to-many relationship be dependent?
Castor JDO design
    How does Castor JDO work anyway?
    Does Castor support two-phase commits? How is this implemented?
    Does Castor support nested transaction?
Working with open source databases
    Does Castor support PosgreSQL?
    Does Castor support MySQL?
    Which Open Source database is supported better?
Integrating Castor's logging with Log4J
    How can I integrate Castor's logging with a logging infrastructure using Log4J?
Lazy Loading related questions
    How do I configure the JDO mapping to use the lazy loading feature?
    I have modified my mapping to use lazy loading. Now I get the error 'no method to set value for field: com.xyz.ClassB in class: ClassMolder com.xyz.ClassA' or 'org.exolab.castor.jdo.DataObjectAccessException: no method to set value for field: com.xyz.ClassB in class: ClassMolder com.xyz.ClassA'. What am I doing wrong?
Tuning for LOBs
Database-specific issues
    HSQL and identity key generators

Castor's relation to other specifications

Does Castor JDO comply with the SUN JSR-000012 specification?

No, Castor JDO doesn't comply with the SUN's JDO specification.

Although Castor JDO carries very similar goals as SUN's JDO, it has been developed independently from the JSR.

Although it is not impossible to shape (perhaps "hammer" is a more descriptive verb) Castor JDO into the SUN's JDO specification, there are several major technical differences which make it unfavorable to do so. Castor is RDBMS centric. Each persistence object loaded by Castor is locked. Locks in Castor are observable, meaning that locks may not be granted because of timeout or deadlock. On the other hand, the SUN's JDO hides details about locks.

Internally, Castor JDO maintains a single copy of lock (and cache) for each active persistence object for all transaction. SUN's JDO specification implicitly requires a copy of cache per object per transaction. SUN's JDO also implicitly requires a bytecode modifier which Castor doesn't require.

Castor also provides other features, such as key generators, long transaction support and OQL query which cannot be found in SUN's JSR.

Is Castor JDO better than EJB CMP?

The relation between JDO and EJB Container-Managed Persistence is more complicated than simply saying, "one is better than the other".

An Entity Bean may manage persistence itself - the EJB specification calls this Bean Managed Persistence (BMP). Alternatively, the Entity Bean may rely on an EJB container to manage all peersistence automatically - the EJB specification calls this Container Managed Persistence (CMP). When implementing BMP, an Entity Bean may use Castor JDO as its persistence mechanism, or it may use others methods, such as dealing with JDBC directly. During CMP, an EJB Container vendor may implement their CMP on top of Castor JDO. In such an implementation, Castor JDO will be used to persist the Entity Bean.

If a developer would like to take advantage of an EJB's life-cycle management, security, the "write once deploy anywhere" promise and other distributed business application facilities, then EJB will be the right choice. Otherwise, the fact that Castor is simple, is Open Source (you can always include Castor in your application or product), has much less overhead, provides more design freedom, and is integrated with Castor XML may be enough of a reason to choose Castor JDO.

XML related questions

Is it possible to make XML marshalling transactionally using Castor?

No. The decision of putting XML and JDO together is NOT intended to make XML marshalling transactional. Instead, the integration is done to help developers of a typical client-server situation whereby an application server receives incoming XML messages, process the messages and replies to the client.

With Castor, incoming XML messages can be unmarshaled into data objects. Required information can be obtained from a database using JDO in form of data objects. With this approach, all data manipulation can be done in an object-oriented way. Changes to JDO data objects can be committed transactionally, and result data objects can be marshaled into XML and returned to the client.

Is it possible to do queries on a XML file using Castor?

No, Castor does not provide an OQL query facility on a XML file. If querying is important for you, you should consider using a DBMS to store your data instead of using XML files, especially if querying performance is a concern.

Another alternative is parse an XML Document directly and use XPath to retrieve Nodes and/or NodeSets from an XML Document. Other open source tools which provide this functionality are:

- SAXPath
- Jakarta Commons JXPath

Technical questions

Where can I find some examples to start with?

Download the full CVS snapshot and look into the src/tests/jdo directory.

I have encountered problems using Sun JDBC-ODBC bridge with Castor...

It cannot be used with Castor, because it doesn't allow more than one open ResultSet at the same time. Either use JDBC driver of type > 1, or use some other JDBC-ODBC bridge without such a restriction (for example, from Easysoft).

My get-method for the Collection of dependent objects returns null. Why?

You should initialize the Collection yourself:

private Collection _children = new ArrayList();

public Collection getChildren() {
    return _children;
}
            

Should my JDO classes implement some special interface?

In general, no. If you need some behavior that is not directly supported by Castor, you can implement interface org.exolab.castor.jdo.Persistent. In order to use dirty checking for long transaction you should implement interface org.exolab.castor.jdo.TimeStampable. If you need an example of use of these interfaces, see Persistent.java and TestPersistent.java among Castor JDO tests.

Can Castor automatically create/remove related objects?

First of all, let's agree upon terminology. We distinguish dependent and independent objects:

-dependent objects are bounded to the parent object's lifecycle
-independent objects have independent lifecycle
Thus, dependent objects are created/removed automatically, when their parent object is created/removed, while all operations on independent objects should be performed explicitly.

However, with Castor 0.8.x you cannot describe explicitly the kind of object. Instead, the following rule applies: if you have one-to-many relation, and each side of the relation refers to another (Collection attribute on "one" side, simple attribute on "many" side), then "many" side is a dependent object. All other objects are independent. In particular, related objects via one-to-one relation are not created/removed automatically.

With Castor 0.9 dependent objects should be described via "depends" attribute of "class" element in mapping configuration file.

If you wish some independent object was created and/or removed automatically on operations on other independent object, you may use interface Persistent to code the desired behavior.

Is Castor JDO using any connection pooling mechanism to improve the overall performance?

No, Castor JDO doesn't have any built-in JDBC resource pooling. However the framework can transparently use any resource pooling facilities provided through DataSource implementation or -even better- through JDNI. In fact we even recommend people to use some Connection and PreparedStatement pool with Castor as this can increase Castor's performance 3-5 fold.

For example the following set of statements:

db.begin();
db.execute(...)
db.commit()
            
will be executed in much less time with the resource pooling because it will avoid creating a new physical JDBC connection at every execution.

With Oracle, instead of specifying the usual JDBC driver you can use a DataSource that specifically provides some Connection caching/pooling.

Thus if your jdo config file looks like :

        <database name="..." engine="oracle" >
            <driver class-name="oracle.jdbc.driver.OracleDriver"
                    url="jdbc:oracle:thin:@localhost:1521:TEST" >
                <param name="user" value="SYSTEM"/>
                <param name="password" value="manager"/>
            </driver>
            ...
        </database>
        
then it can be changed into (for example):
        <database name="..." engine="oracle" >
            <driver URL="jdbc:oracle:thin:@localhost:1521:TEST" 
                    class-name="oracle.jdbc.pool.OracleConnectionCacheImpl">
                <param name="user" value="SYSTEM" />
                <param name="password" value="manager"/>
            </driver>
            ...
        </database>
        

When Castor is used inside a Container such as an EJB container (within BMP or Session Bean), then the Container usually provides the JDBC resource through the JNDI ENC, which implicitely includes pooling facilities.

I am getting ClassNotFoundException for my JDO class, but it is in the class path. Why?

Probably castor.jar file is in jre/lib/ext directory. In this case you should call:

      jdo.setClassLoader(getClass().getClassLoader());
             
before jdo.getDatabase().

I am getting exception 'the class ... is not persistence capable...'. Why?

In this case as well as in many others you can get more information with the help of logging. Call:

  jdo.setLogWriter(Logger.getSystemLogger());
        

and seek in the output for warnings and errors.

I call db.remove() on the dependent object and commit, but this doesn't work...

You should not add/remove dependent objects directly. In order to add/remove the dependent object you should just add/remove it from the collection in the master object and call db.commit()

Dependent objects cannot be created/removed explicitly. It's created automatically when it is added to a master object, and removed automatically when it de-linked/dereferenced from a master object.

Otherwise, we will be encounter into problem where a dependent object created explicitly but removed implicitly (delinked from a master object), or vice versa. It can also lead to other problems that are harder to detect.

How should I represent string/date/boolean literals in OQL query?

It is recommended to replace literals with parameters and to set them via OQLQuery.bind(), for example:

OQLQuery query = db.getOQLQuery("SELECT p FROM Person p "
      +"WHERE name LIKE $1 AND dob>$2 AND married=$3");
query.bind("John %");
query.bind((new SimpleDateFormat("yyyy-MM-dd"))
       .parse("1960-01-01"));
query.bind(false);
         

I get 'java.lang.AbstractMethodError: getBigDecimal' for numeric fields. Why?

Your JDBC driver is not JDBC 2.0 compliant, upgrade it or find another one.

Does Castor support both one-way and two-way relationships?

Typcially a relationship between two objects is either one-way (aka uni-directional) or two-way (aka bi-directional). Officially, Castor currently only supports bi-directional relationships. For example, if an Order object contains a reference to a LineItem object, the LineItem object must contain a reference to the Order object. However, this requirement is not enforced in all situations.

This is a very complex problem to solve. So until Castor is expanded the support uni-directional relationships, the best policy is to implement the bi-directionalality for all relationships. This will ensure proper functionality.

I have an object that holds a relation to itself. Does Castor support this?

This is a very common occurrence in an object model and is known as a self-referenential relationship. Unfortunately, Castor does not currently support self-referential relationships. An example of such a relationship occurs when a Folder object contains a reference to another Folder object. Castor does not currently support this. However, there are ways around this limitation.

One way is to manage this type of relationship manually. For example, let's say that a parent object FolderA needs to hold references to child objects FolderB, FolderC and FolderD. The Folder object contains not only a property to hold its own id, but also a property to hold its parent id (we'll call this parentId). The parentId property is used to determine if there is a relationship to another Folder object. If parentId is null, there is no relationship. If parentId is populated, there is a relationship and the object tree can be walked by comparing the object id to the parentId. When the two properties are equal, you're at the top of the tree.

Another say to solve this problem is to make use of an intermediary object. For example, a Folder object contains a Reference object in lieu of the actual Folder object. The Reference object is somewhat of a proxy object whereby it only contains enough information to identify the object to which the Reference object refers. Then the Folder object can be easily instantiated via the information contained in the Reference object.

Why do I get an ObjectModifiedException when trying to commit a transaction?

The dirty checking engine will throw an ObjectModifiedException when the values in the cache and in the database are different. This can happen when someone else changed the database content, but also when type mapping is not reversible.

For example, if a java timestamp (java.util.Date) is stored as a DATE, the time part is lost and the dirty checking will fail. Oracle cannot tell the difference between an empty String and a null value: if an attribute value is an empty String, dirty checking will also fail. Some precision loss sometimes occur with floating point numbers.

To avoid this, always use reversible mapping conversions. If this is not possible, mark the fields with dirty="ignore" in the mapping file.

I'm receiving a java.sql.SQLException: ORA-01461

When using Weblogic Portal 4.0 with Oracle I am receiving the following error:

java.sql.SQLException: ORA-01461: can bind a LONG value only for insert into a LONG column
            
According to Weblogic Release Notes, this error can remedied by setting a Weblogic environment variable.

Castor and performance caches

Sometimes long transaction fails: on update() it is thrown ObjectModifiedException. Why?

Most probably the object that is being updated has more than 100 related objects of one class and the cache size for this class is not enough. You should either increase the size of the cache or change the cache type to time-limited (the default cache type is count-limited, the default size is 100), for example:

<class ...>
  <cache-type type="count-limited" capacity="1000"/>
  ...
</class>
        

Can I use the cache-type='none' with long transactions?

As of release 0.9.5.3, you cannot. When using a cache of type 'none' with your 'Timestampable' objects, a MappingException is thrown when performing long transactions. Currently, Castor requires a (performance) cache of type other than 'none' to be used with classes that implement the 'TimeStampable' interface. In other words, if you want to use long transactions, please make sure that you use one of these cache types: 'unlimited', 'count-limited' or 'time-limited'.

The next entry has some more information about a potential cause of confusion in the context of long transactions and a cache type other than 'unlimited'.

What is causing a PersistenceException with long transactions and how do I fix it?

With long transactions, sometimes update() throws a PersistenceException. As of release 0.9.5.3, Castor requires a (performance) cache (of type other than 'none') to be used with classes that implement the 'TimeStampable' interface.

Please note that if you are using a cache type other than 'unlimited', it is possible that objects expire from the cache. This case will be highlighted to you by a PersistenceException being thrown.

In this cases, please consider switching to cache type 'unlimited' (if possible) or increase the size of the cache according to your needs when using 'count-limited' (which has a default capacity of 100).

OQL

Is there any document available for Castor OQL?

Yes. It is available from the Castor website: Advanced JDO --> OQL

The OQL document describes several phases of development. Which is the current phase?

We are currently working on Phase 3.

Does Castor OQL support sub-queries?

Not yet

I cannot get Castor OQL to join two objects for me. Is it supported?

Yes or no. Castor OQL supports implicit joins. And, in most case, you simply don't need explicit join.

Consider the following example,

SELECT o FROM Order o, LineItem i WHERE o.id = i.id AND i.price > 100
            

It is simply equivalent to the following OQL

SELECT o FROM Order o WHERE o.lineItem.price > 100
            

Can I write a pass-thru OQL?

Yes. Just put "CALL SQL" keywords in front of your SQL statement. For example,

OQLQuery oql = castorDb.getOQLQuery(
    "CALL SQL SELECT id, name, date "+
    "FROM user WHERE upper(name) like $1 AS myapp.Product");
            

But remember that the order of the fields listed must match what is defined in the mapping file.

Does Castor OQL support struct?

No, Castor OQL doesn't support struct. For example, the following query CANNOT be done:

select c.name, c.age from Client c
            

How do I structure a query using the 'LIKE' expression?

A query using the 'LIKE' expression includes the use of the SQL wildcard '%'. The wildcard must be included in the

bind()
statement:
        OQLQuery oql = castorDb.getOQLQuery( "SELECT p FROM Product p WHERE p.name LIKE $1" );
        oql.bind( "%widget%" );
            

Does Castor support the SQL 'IN' expression?

Yes. However, the full expression is a bit different using the LIST keyword. The following example provides a demonstration:

SELECT p FROM Product p WHERE p.id IN LIST ( 123, 456, 789 )
            

If identifiers other than numbers are used, those identifiers must be quoted:

SELECT p FROM Product p WHERE p.id IN LIST ( "abc", "jkl", "xyz" )
            

Features requests

Can a foreign key be part of multiple primary keys?

Unfortunately, the answer is no. We're aware that many users need this feature so it is a very high priority in our todo list.

If foreign key is the primary key, as a workaround you may consider using the 'extends' relationship.

Is polymorphic collection supported?

Unfortunately, the answer is no.

In version 0.8.11, we tried to enable polymorphic collection by introducing the notation of Object Reloading. Object Reloading delegates the determination of the class to a data object. However, it is proved that reloading can only be done before any instance of the target object is returned to user, and we have no way to determine that. As a result, we removed the support in version 0.9.x.

In the near future, we are going to use a new mechanism to provide extends. The new mechanism loads a table with an SQL statement that outer-joins all of the extending tables with the base. The existence of an extended table row can be used to determine the class of a data object. Notice that all extended table rows of the same entity should always be stored in the same data-store.

In the further future, we also want to let users to define a discriminator column (or determinance field). Basing on the value of discriminator columns in the base table, the bridge layer fetches the additional information and returns the combined entity with the appropriate list of entity classes.

Data model issues

Is it possible to map an object to more than one tables?

Yes, if the two tables share the same identity, you can specify one data object to "extends" the other. When the extended data object is loaded, its table (specified in <map-to/> will be joined with all the tables of its super classes'.

Another solution (in my opinion more flexible) is having two set of methods in the main object. One for Castor JDO and another for application.

Consider the following example:

class Employee {
   private int _employeeNumber;
   private Address _address;
   private Collection _workGroup;

   public int getEmployeeNumber() {
        return _employeeNumber;
   }
   public void setEmployeeNumber( int id ) {
        _employeeNumber = id;
   }

   // methods for Castor JDO
   public Address getAddress() {
       return _address;
   }
   public void setAddress( Address address ) {
        _address = address;
   }
   public Collection getWorkGroup() {
        return _workGroup;
   }
   public Collection setWorkGroup( Collection workGroup ) {
        _workGroup = workGroup;
   }

   // methods for application
   public String getAddressCity() {
       return _address.getCity();
   }
   public String getAddressZip() {
       return _address.getZip();
   }
   // ...
}
            

Can an object with the same identity be re-created after being removed in the same transaction?

Yes, as long as the deleted object is the same instance as the one being recreated.

What is a dependent object?

Dependent object is actually a concept from the object-oriented database world. A dependent object's lifetime depends on its master object. So, create/delete/update of the master object will trigger the proper actions, newly linked dependent object will be automatically created and de-referenced dependent object will be removed.

The concept was also used in the earlier CMP 2.0 draft, although it is later removed.

Can a data object involved in many-to-many relationship be dependent?

No

Castor JDO design

How does Castor JDO work anyway?

Let's use object loading as an example.

When an application invoke db.load, the underneath TransactionContext is invoked. If the object with the requested identity exists in the TransactionContext, previously loaded object in the TransactionContext is returned. Otherwise, TransactionContext creates a new instance of the interested type and invokes LockEngine to "fill" the object.

LockEngine acquires a lock of the object, and it makes sure ClassMolder has a thread-safe environment when it invokes ClassMolder. In ClassMolder, if the interested set of fields representing the object is not existed in the cache yet, SQLEngine will be invoked and the set of fields from the underneath data store will be returned. ClassMolder binds the loaded or cached fields into the new instance. ClassMolder requests the TransactionContext to load the related and the dependent objects. Eventually, the object is returned after all of the relationships are resolved.

The process of commit has several states. The first state is preStore. In preStore state, objects existing in the TransactionContext are checked for modification one by one, including dependent and related objects. De-referenced dependent objects are marked as delete-able, and reachable dependent objects are added into TransactionContext. An object is marked "dirty" if it is modified. Also, if any modification should cause any related or dependent to be dirty, the related or dependent object is marked as dirty as well.

After the preStore state, all dirty object is properly stored. And, all marked delete object will be removed. Then, the connection is committed. If succeed, all cache with be updated. Finally, all lock is released.

Does Castor support two-phase commits? How is this implemented?

Yes, via javax.transaction.Synchronization interface.

For Castor to work with global transactions, Castor must be configured to use global transaction demarcation in its main configuration file:

<jdo-conf>
   ...
   <transaction-demarcation mode="global" >
      <transaction-manager name="jndi" />
   </transaction-demarcation>
</jdo-conf>
            

When retrieving a Database instance via

...
JDO jdo = new JDO();
jdo.setDatabaseName("...");
jdo.setConfiguration (..);
...
Database db = jdo.getDatabase();
            

the Database implementation will authomatically be registered with the transaction manager, as it implements javax.jta.Synchronization interface. Subsequently, the transaction manager communicates with Castor via the beforeCompletion() and afterCompletion() calls.

Does Castor support nested transaction?

No

Working with open source databases

Does Castor support PosgreSQL?

Yes, starting from PostgreSQL 7.1, where outer joins support has been added.

Does Castor support MySQL?

Yes, starting from MySQL version 3.23, where transaction support has been added. Note: if you use Mark Matthews MySQL JDBC driver, then you need version 2.0.3 or higher.

Which Open Source database is supported better?

For now only with PostgreSQL 7.1 and SAP DB you get a full set of Castor features. Other Open Source databases don't support select with write lock, so db-locked locking mode doesn't work properly (it works in the same way as exclusive locking mode).

All other Castor features are supported with MySQL, Interbase, InstantDB and Hypersonic SQL.

Integrating Castor's logging with Log4J

How can I integrate Castor's logging with a logging infrastructure using Log4J?

Please see this message from the mailing list. It includes an adapter class that will provide this functionality. (Thanks John!)

Lazy Loading related questions

How do I configure the JDO mapping to use the lazy loading feature?

Let us convert one of the classes from the JDO examples to use lazy-loading.

In the example model, one Product can contain many ProductDetails. This is reflected in the conventional mapping as below. First, the mapping for Product:

<!--  Mapping for Product  -->
<class name="myapp.Product"
       identity="id">
   <description>Product definition</description>
   <map-to table="prod" xml="product" />
   <field name="id" type="integer">
       <sql name="id" type="integer" />
       <xml name="id" node="attribute"/>
   </field>
 
   <!-- more fields ... -->

   <!-- Product has reference to ProductDetail
            many details per product  -->
   <field name="details" type="myapp.ProductDetail" required="true"
           collection="vector">
       <sql many-key="prod_id"/>
       <xml name="detail" node="element" />
   </field>
</class>
            

Now let us examine ProductDetail. Note, the relationship is mapped bi-directionally as must be all relationships when using Castor JDO.

<!--  Mapping for Product Detail -->
<class name="myapp.ProductDetail" identity="id" depends="myapp.Product" >
   <description>Product detail</description>
    <map-to table="prod_detail" xml="detail" />
   <field name="id" type="integer">
       <sql name="id" type="integer"/>
       <xml node="attribute"/>
    </field>
    <field name="product" type="myapp.Product">
       <sql name="prod_id" />
       <xml name="product" node="element" />
    </field>
   
       <!-- more fields ... -->
   
</class>
           
           

Let us now make the relationship between Product and ProductDetail use lazy loading. We need only change the way that the relationship to ProductDetail is specified in the mapping of Product. The relevant field in Product can be re-written like so:

<field name="details" type="myapp.ProductDetail" required="true" lazy="true"
            collection="collection">
   <sql many-key="prod_id"/>
   <xml name="detail" node="element" />
</field>
           
           

There have been two changes.

-We have placed the attribute lazy="true" in the field element
-We have changed the type of the underlying collection type to be a java.util.Collection by changing the field element attribute to collection="collection".

Note that no change is required in the ProductDetail mapping.

I have modified my mapping to use lazy loading. Now I get the error 'no method to set value for field: com.xyz.ClassB in class: ClassMolder com.xyz.ClassA' or 'org.exolab.castor.jdo.DataObjectAccessException: no method to set value for field: com.xyz.ClassB in class: ClassMolder com.xyz.ClassA'. What am I doing wrong?

To use lazy loading you must also change the persistent class that will hold the related objects. At the very highest level, you need to provide a set method that accepts a java.util.Collection for the field in question. This is demonstrated by changing the JDO examples below.

In the original Product class we have the following code:

import java.util.Vector;
...
private Vector       _details = new Vector();
...
public Vector getDetails()
{
   return _details;
}


public void addDetail( ProductDetail detail )
{
   _details.add( detail );
   detail.setProduct( this );
}
           

Let us now make the necessary changes to set up lazy loading. As stated above we now require a special set method for the related ProductDetails (stored originally as a java.util.Vector) that accepts a java.util.Collection as an argument. This mandates that we must also use a java.util.Collection to hold our ProductDetails. If this is not added, you will receive the errors above.

import java.util.Collection;
...
private Collection       _details;
...
public Collection getDetails()
{
   return _details;
}


public void setDetails( Collection details )
{
   _details = details;
}

           

Tuning for LOBs

Castor JDO provides a property in castor.properties for adjusting the size of the JDBC driver's buffer for reading LOBs (BLOBs and CLOBs) from the database. The propery is named org.exolab.castor.jdo.lobBufferSize and its default is 5120 bytes (5k). The size of this buffer can be tuned for larger LOBs, but is dependent upon the JDBC driver implementation being used and what it supports.

Database-specific issues

HSQL and identity key generators

Due to a product limitation, AUTO_INCREMENT sequences in HSQL begin with 0 rather 1, as is the case with most other RDBMS. As a result of this, long transactions will not work for the object with the identity 0, and a ObjectModifiedException will be thrown.

To avoid this issue, we recommend inserting a temp object into the database in question, and removing thereafter so that no object with identity 0 is stored.

 
   
  
   
 


Copyright © 1999-2004 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.