Does anyone have a good solution or workaround for this?
Shallow updates do not update foreign keys in the root object's associated database
table. By shallow, I mean that I have called setAutoStore(false) before the
transaction. Given our very complex object hierarchy, we are unable to use
setAutoStore(true), which does a deep update. This leads to a host of other issues
such as reduced performance and optimistic lock collisions on objects which have not
been modified. We query for object sets and hang onto them long term, associating
them with new and modified objects to be persisted.
I've been using two classes in my testing, Monster and Victim. A Monster has a
collection of Victims and a Victim knows his one Monster. Test pseudocode follows:
1. Set auto store to false.
2. Create a new Monster in transaction A.
3. Create a new Victim in transaction B.
4. Set the victim's monster to the monster created in step 2.
5. Call update on the victim in transaction C.
Attributes on the victim are written out to the database except for the monsterId.
We're running the latest version of Castor, v0.9.4.1.
Following is the database schema, the code for the Monster, Victim, and Test, and
Castor mappings
Thanks for any suggestions!
--- database schema ---
create table monster
(id varchar(30),
name varchar(30));
create table victim
(id varchar(30),
name varchar(30),
monsterId varchar(30));
--- Monster ---
import java.util.Vector;
import org.exolab.castor.jdo.TimeStampable;
public class Monster implements TimeStampable {
protected String id;
protected String name;
protected long timeStamp;
protected Vector victims = new Vector();
public String getId() {
return id;
}
public void setId(String anId) {
id = anId;
}
public String getName() {
return name;
}
public void setName(String aName) {
name = aName;
}
public Victim createVictim() {
return new Victim();
}
public Vector getVictims() {
return victims;
}
public void addVictim(Victim aVictim) {
victims.add(aVictim);
aVictim.setMonster(this);
}
public void jdoSetTimeStamp( long aTimeStamp )
{
timeStamp = aTimeStamp;
}
public long jdoGetTimeStamp()
{
return timeStamp;
}
}
--- Victim ---
import org.exolab.castor.jdo.TimeStampable;
public class Victim implements TimeStampable {
private String id;
private String name;
private Monster monster;
private long timeStamp;
public String getId() {
return id;
}
public void setId(String anId) {
id = anId;
}
public String getName() {
return name;
}
public void setName(String aName) {
name = aName;
}
public Monster getMonster() {
return monster;
}
public void setMonster(Monster aMonster) {
monster = aMonster;
}
public void jdoSetTimeStamp( long aTimeStamp )
{
timeStamp = aTimeStamp;
}
public long jdoGetTimeStamp()
{
return timeStamp;
}
}
--- Monster mapping ---
<mapping>
<class name="Monster" identity="id" key-generator="UUID">
<description>The Monster</description>
<cache-type type="count-limited" capacity="100"/>
<map-to table="Monster" xml="Monster" />
<field name="id" type="string" >
<sql name="id" type="char"/>
<xml name="id" node="attribute"/>
</field>
<field name="name" type="string" >
<sql name="name" type="char"/>
<xml name="name" node="attribute"/>
</field>
<field name="victims" type="Victim" required="true" collection="vector">
<sql many-key="monsterId"/>
</field>
</class>
</mapping>
--- Victim mapping ---
<mapping>
<class name="Victim" identity="id" key-generator="UUID">
<description>A Victim</description>
<cache-type type="count-limited" capacity="100"/>
<map-to table="Victim" xml="Victim" />
<field name="id" type="string" >
<sql name="id" type="char"/>
<xml name="id" node="attribute"/>
</field>
<field name="name" type="string" >
<sql name="name" type="char"/>
<xml name="name" node="attribute"/>
</field>
<field name="monster" type="Monster">
<sql name="monsterId"/>
<xml name="monsterId" node="attribute"/>
</field>
</class>
</mapping>
--- Test Code ---
import java.util.Collection;
import java.util.Iterator;
import java.util.Vector;
import org.arch4j.persistence.ObjectQuery;
import org.arch4j.persistence.PersistenceManager;
import org.arch4j.persistence.PersistenceProvider;
import org.exolab.castor.jdo.ClassNotPersistenceCapableException;
import org.exolab.castor.jdo.Database;
import org.exolab.castor.jdo.DatabaseNotFoundException;
import org.exolab.castor.jdo.DuplicateIdentityException;
import org.exolab.castor.jdo.JDO;
import org.exolab.castor.jdo.OQLQuery;
import org.exolab.castor.jdo.PersistenceException;
import org.exolab.castor.jdo.QueryResults;
import org.exolab.castor.jdo.TransactionAbortedException;
import org.exolab.castor.jdo.TransactionNotInProgressException;
public class CastorTest {
private Database db;
public CastorTest() {
try {
JDO jdo = new JDO();
jdo.setDatabaseName("project6");
jdo.setConfiguration("./metadata/database.xml");
jdo.setClassLoader(getClass().getClassLoader());
db = jdo.getDatabase();
}
catch (DatabaseNotFoundException e) {
System.out.println("* Database not found.");
e.printStackTrace();
}
catch (PersistenceException e) {
System.out.println("* Persistence exception while opening the database.");
e.printStackTrace();
}
}
public static void main(String[] args) {
CastorTest instance = new CastorTest();
instance.testForeignKeyInShallowUpdate();
}
/**
* Tests resolving foreign key references on shallow updates.
*/
private void testForeignKeyInShallowUpdate() {
System.out.println("--- testForeignKeyInShallowUpdate() ---");
try {
db.setAutoStore(false); // alert Castor to go shallow
// create a monster
Monster monster = new Monster();
monster.setName("Tiamat");
db.begin();
db.create(monster);
db.commit();
// create a victim through Castor
Victim victim = new Victim();
victim.setName("Victor");
db.begin();
db.create(victim);
db.commit();
victim.setMonster(monster);
db.begin();
db.update(victim); // does NOT write the monsterId to the Victim table
db.commit();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
____________________________________________________________________
Please look below this disclaimer for attachments.
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. This communication may contain material protected by
attorney-client privilege. If you are not the intended recipient or
the person responsible for delivering the email to the intended
recipient, be advised that you have received this email in error and
that any use, dissemination, forwarding, printing, or copying of this
email is strictly prohibited. If you have received this email in error
please notify the Information Systems Manager by telephone at (715)845-3111
[EMAIL PROTECTED]
http://www.wipfli.com
-----------------------------------------------------------
If you wish to unsubscribe from this mailing, send mail to
[EMAIL PROTECTED] with a subject of:
unsubscribe castor-dev