I've now tried changing the List in A to a Vector and adding the B instances to a1 in the same transaction as I create a1, both before and after the tx2.lock(a1... call.

In all cases, the only writes to table A_B are to delete all rows that reference the new A.

I've had a look through the OJB test cases, and so far the only places I see n:m associations being exercised, they are set up as part of the construction of the instance; I don't see any test which alter the content of a collection that's part of an n:m mapping. Are there any?

If anybody is successfully using non-decomposed n:m mappings in OJB can you give me sample code demonstrating how to do it?

L.

Laurie Harper wrote:

Doing some further digging, I found a bug in the test case: it was
missing 'tx3.lock(a1, Transaction.WRITE);' in the collection update
transaction block. However, adding this had no effect on behaviour.
Here's what's in the log for that block of code:

22981 DEBUG [main] odmg.ObjectEnvelopeTable - call beginTransaction() on
PB instance
22981 DEBUG [main] accesslayer.ConnectionManager - Try to change
autoCommit state to 'false'
22983 DEBUG [main] ta.PersistenceBrokerFactoryDefaultImpl -
createPersistenceBroker(key) called
22983 DEBUG [main] singlevm.PersistenceBrokerImpl - PB.close was called:
org.apache.ojb.broker.singlevm.PersistenceBrokerImpl@2c2cfd
22984 DEBUG [main] odmg.ObjectEnvelopeTable - commit:
A{272}(org.apache.ojb.odmg.states.StateOldClean)
22985 DEBUG [main] ta.PersistenceBrokerFactoryDefaultImpl -
createPersistenceBroker(key) called
22985 DEBUG [main] singlevm.PersistenceBrokerImpl - PB.close was called:
org.apache.ojb.broker.singlevm.PersistenceBrokerImpl@2c2cfd
22986 DEBUG [main] odmg.TransactionImpl - Commit transaction
org.apache.ojb.odmg.TransactionImpl@74ba2a, commit on broker
org.apache.ojb.broker.singlevm.PersistenceBrokerImpl@30fecf
22988 DEBUG [main] ta.PersistenceBrokerFactoryDefaultImpl -
createPersistenceBroker(key) called
22989 DEBUG [main] singlevm.PersistenceBrokerImpl - PB.close was called:
org.apache.ojb.broker.singlevm.PersistenceBrokerImpl@2c2cfd
22990 DEBUG [main] locking.LockManagerDefaultImpl -
LM.releaseLock(tx-192.168.1.100:14224e:f22ecbeafa:-7ffe, A{272})
22990 DEBUG [main] ta.PersistenceBrokerFactoryDefaultImpl -
createPersistenceBroker(key) called
22990 DEBUG [main] singlevm.PersistenceBrokerImpl - PB.close was called:
org.apache.ojb.broker.singlevm.PersistenceBrokerImpl@2c2cfd
22992 DEBUG [main] odmg.TransactionImpl - Close Transaction and release
current PB org.apache.ojb.broker.singlevm.PersistenceBrokerImpl@30fecf
on tx org.apache.ojb.odmg.TransactionImpl@74b
a2a

The changes to a1's collection of Bs never results in an update on table
A (which it shouldn't in this case, of course) or an insert on table A_B
(which it should).

I tried calling tx3.lock(bs, Transaction.WRITE) before modifying bs, but
that resulted in a 'not persistence capable' exception.

I'm sure I must be missing something really simple... Help!

L.

Laurie Harper wrote:

> This is driving me slightly nuts :-) I ran into a strange error tring to
>  add a collection property modelled by an indirection table in the
> database. If I do this (much abreviated):
>
> tx = odmg.newTransaction();
> tx.begin();
> tx.lock(project, WRITE);
> project.getList().add(foo);
> tx.commit();
>
> where the getList() method initialises the collection property to 'new
> LinkedList()' if it's not already set, I get an error about there being
> no transaction in progress. That's the problem I want to solve.
>
>
> In trying to understand what's going on, I tried to boil it down to a
> really simple test case. The test case consists of two classes and three
> tables modelling an n:m relationship. The problem is, it breaks in a
> different way than the above: when I add items to the collection
> property and commit, the indirection table isn't updated (so the
> collection property doesn't get persisted).
>
> The test case involves two simple classes, A and B. A has a collection
> of B. The database contains tables A and B and an indirection table A_B.
> I can load an instance of A from the database and OJB uses rows from A_B
> to populate A's collection property. But if I try and modify the
> collection property on A, nothing is written to the A_B table. Here's
> the various files that constitute my test case. Any suggestions what I'm
> doing wrong may help shed light on real problem, described above.
>
> One oddity is that the query to load the AB instances only works if I
> use the SQL table/column names in the OQL query! (see lines marked XXX
> in the test case below). I'm unclear about why that should be...
>
> Schema:
>
> CREATE SEQUENCE A_SEQ;
> CREATE SEQUENCE B_SEQ;
> CREATE SEQUENCE A_B_SEQ;
>
> CREATE TABLE A
> (
>     ID INTEGER DEFAULT nextval('A_SEQ') NOT NULL,
>     PRIMARY KEY (ID)
> );
>
> CREATE TABLE B
> (
>     ID INTEGER DEFAULT nextval('B_SEQ') NOT NULL,
>     PRIMARY KEY (ID)
> );
>
>
> CREATE TABLE A_B
> (
>     A_ID INTEGER DEFAULT nextval('A_B_SEQ') NOT NULL,
>     B_ID INTEGER DEFAULT nextval('A_B_SEQ') NOT NULL,
>     PRIMARY KEY (A_ID,B_ID)
> );
>
> ALTER TABLE A_B
>     ADD CONSTRAINT A_FK_1 FOREIGN KEY (A_ID) REFERENCES A (ID)
> ;
> ALTER TABLE A_B
>     ADD CONSTRAINT A_FK_2 FOREIGN KEY (B_ID) REFERENCES B (ID)
> ;
>
> Repository_user.xml entries:
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> Object model:
>
> import java.util.List;
> import java.util.LinkedList;
>
> /**
>  * A has n:m relationship with B
>  */
> public class  A {
>     private int id;
>     public int getID() {
>         return id;
>     }
>
>     private List listOfB;
>     public List getListOfB() {
>         return (null == listOfB) ? new LinkedList() : listOfB;
>     }
> }
>
> /* --- */
>
> import java.util.List;
>
> /**
>  * B has m:n relationship with A
>  */
> public class B {
>     private int id;
>     public int getID() {
>         return id;
>     }
> }
>
> /* --- */
>
> import java.util.List;
> import java.util.LinkedList;
>
> /**
>  * Expose the A_B table so we can query it in the test cases.
>  */
> public class  AB {
>     private int aID, bID;
>     public int getAID() {
>         return aID;
>     }
>     public int getBID() {
>         return bID;
>     }
> }
>
> Test case:
>
> import java.util.List;
>
> import org.odmg.*;
> import org.apache.ojb.odmg.OJB;
> import junit.framework.TestCase;
> import junit.framework.TestSuite;
> import junit.framework.Test;
> import junit.textui.TestRunner;
>
> /**
>  * Creates instances of A and B that reference each other and persists
> them.
>  */
> public class RelationshipTest extends TestCase {
>     private Implementation odmg;
>     private Database db;
>
>     public static void main(String[] args) {
>         TestRunner.run(RelationshipTest.class);
>     }
>     public static Test suite() {
>         return new TestSuite(RelationshipTest.class);
>     }
>     public RelationshipTest(String name) {
>         super(name);
>     }
>
>     public void setUp() throws ODMGException {
>         System.out.println("setup");
>         odmg = OJB.getInstance();
>         db = odmg.newDatabase();
>         db.open("repository.xml", Database.OPEN_READ_WRITE);
>     }
>
>     public void testCreate() throws Exception {
>         A a1;
>         B b1, b2;
>
>         // Create instances of B to be associated with an A
>         {
>         Transaction tx1 = odmg.newTransaction();
>         tx1.begin();
>         b1 = new B();
>         b2 = new B();
>         tx1.lock(b1, Transaction.WRITE);
>         tx1.lock(b2, Transaction.WRITE);
>         tx1.commit();
>         }
>
>         // Create an instance of A
>         {
>         Transaction tx2 = odmg.newTransaction();
>         tx2.begin();
>         a1 = new A();
>         tx2.lock(a1, Transaction.WRITE);
>         tx2.commit();
>         }
>
>         // Modify A's collection of Bs
>         {
>         Transaction tx3 = odmg.newTransaction();
>         tx3.begin();
>         List bs = a1.getListOfB(); // creates new list in a1
>         bs.add(b1);
>         bs.add(b2);
>         tx3.commit();
>         }
>
>         // Check that the A_B table was populated
>         {
>         OQLQuery q = odmg.newOQLQuery();
>         //q.create("select AB from AB where AB.aID = "+a1.getID());//XXX
>         q.create("select AB from AB where A_B.A_ID = "+a1.getID());//XXX
>         List abs = (DList) q.execute();
>         assertNotNull("abs", abs);
>         assertEquals("abs.size", 2, abs.size());
>         }
>     }
>
>     public void testLoad() throws Exception {
>         OQLQuery q = odmg.newOQLQuery();
>         q.create("select A from A where A.ID = 1");
>         A a = (A) ((DList) q.execute()).get(0);
>         List listOfB = a.getListOfB();
>
>         assertEquals("a.id", 1, a.getID());
>         assertNotNull("a.listOfB", listOfB);
>         assertEquals("a.bs.size", 2, listOfB.size());
>         assertEquals("a.bs[0].id", 1, ((B) listOfB.get(0)).getID());
>         assertEquals("a.bs[1].id", 2, ((B) listOfB.get(1)).getID());
>     }
> }
>
>
> --
> To unsubscribe, e-mail:
> For additional commands, e-mail:




--
To unsubscribe, e-mail:
For additional commands, e-mail:


--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to