You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-user@db.apache.org by "Bates, Alex" <AB...@teradata-ncr.com> on 2003/07/11 02:22:56 UTC

1:N association - truncating list to 1 when query

I have a 1:N association - but in my case, the 1 doesn't store a collection
of the N.  Instead, each of the N stores a reference the parent 1.  I didn't
see any examples of how to do this in the JUnits or docs. 

To make things more concrete, I have a QueryVO class (not to be confused
with OJB's query classes), which has a 1:N relationship with ResultSetVO
class.  Each ResultSetVO has a single parent QueryVO (QueryVO is a member of
ResultSetVO).  

---------------  Class definitions ------------------------

public class ResultSetVO implements VOInterface {
    protected Object id = null;
    protected String label = null;
    protected QueryVO query = null;	..
}

public class QueryVO implements VOInterface {
    protected Object id;
    protected String label;
    protected String sql;
}

So, what I want to be able to do is: navigate from the CHILD (one of the N)
to the PARENT (the 1).  Notice that ResultSetVO stores a reference to the
parent QueryVO, but QueryVO does NOT store a collection of child
ResultSetVOs.

All the examples I see in the docs and Junit that use inverse-foreignkey use
it for the opposite: the parent has a collection of children (in my case,
QueryVO would have a collection of ResultSetVOs).  But my case is different:
I need to define how ResultSetVO can reference QueryVO.

Using the mapping file below, I am able to create ResultSetVOs that are
mapped to QueryVOs, and persist them (without errors).  However, when I try
to retrieve the list of ResultSetVOs, it always truncates the list at 1.  I
found this to be true using both the low-level PB API, and using an ODMG OQL
query.

Details: I'm running the Jboss/J2EE version of OJB; using the ODMG API; at
the bottom is the log output where the truncation occurs.


---------------  Mapping File ------------------------

<!-- Definitions for com.teradata.tap.component.system.query.QueryVO -->
   <class-descriptor
   	  class="com.teradata.tap.component.system.query.QueryVO"
   	  table="TapQuery"
   >
      <field-descriptor
         name="id"
         column="ID"
         jdbc-type="INTEGER"
         primarykey="true"
         autoincrement="true"
      />
      <field-descriptor
         name="label"
         column="Label"
         jdbc-type="VARCHAR"
      />
      <field-descriptor
         name="sql"
         column="SqlString"
         jdbc-type="VARCHAR"
      />
   </class-descriptor> 

<!-- Definitions for com.teradata.tap.component.system.resultset.ResultSetVO
-->
   <class-descriptor
   	  class="com.teradata.tap.component.system.resultset.ResultSetVO"
   	  table="TapResultset"
   >
      <field-descriptor
         name="id"
         column="ID"
         jdbc-type="INTEGER"
         primarykey="true"
         autoincrement="true"
      />
      <field-descriptor
         name="label"
         column="Label"
         jdbc-type="VARCHAR"
      />
      <field-descriptor
         name="maxRows"
         column="MaxRows"
         jdbc-type="INTEGER"
      />
      <field-descriptor
         name="queryTimeoutSecs"
         column="QueryTimeoutSecs"
         jdbc-type="INTEGER"
      />
	<reference-descriptor name="query"
		class-ref="com.teradata.tap.component.system.query.QueryVO"
		auto-retrieve="true"
	        auto-update="true">		
			<foreignkey field-ref="id" />
	</reference-descriptor>
   </class-descriptor> 


-------------------- Detailed logging output --------------------------

2003-07-10 17:18:15,864 DEBUG
[org.apache.ojb.broker.accesslayer.JdbcAccessImpl] executeQuery : Query from
class com.teradata.tap.component.system.resultset.ResultSetVO where
org.apache.ojb.broker.query.Criteria@34cdfc
2003-07-10 17:18:15,879 DEBUG
[org.apache.ojb.broker.accesslayer.sql.SqlGeneratorDefaultImpl] SQL: SELECT
A0.MaxRows,A0.QueryTimeoutSecs,A0.Label,A0.ID FROM TapResultset A0
2003-07-10 17:18:16,192 DEBUG [org.apache.ojb.broker.accesslayer.RsIterator]
hasNext() -> true
2003-07-10 17:18:16,223 DEBUG
[org.apache.ojb.broker.singlevm.PersistenceBrokerImpl] getObjectByIdentity
com.teradata.tap.component.system.query.QueryVO{22}
2003-07-10 17:18:16,223 DEBUG
[org.apache.ojb.broker.accesslayer.sql.SqlGeneratorDefaultImpl] SQL: SELECT
SqlString,Label,ID FROM TapQuery WHERE ID = ? 
2003-07-10 17:18:16,333 DEBUG
[org.apache.ojb.broker.accesslayer.StatementManager] closeResources was
called
2003-07-10 17:18:16,333 WARN
[org.jboss.resource.adapter.jdbc.WrappedConnection] Closing a statement you
left open, please do your own housekeeping
2003-07-10 17:18:16,333 DEBUG
[org.apache.ojb.broker.accesslayer.ConnectionFactoryAbstractImpl] do
datasource lookup, name: java:TeradataDS, user: tapuser
2003-07-10 17:18:16,333 DEBUG
[org.apache.ojb.broker.accesslayer.ConnectionManagerImpl] Request new
connection from ConnectionFactory:
org.apache.ojb.broker.util.pooling.ByPassConnection@1be3d02
2003-07-10 17:18:16,379 DEBUG
[org.apache.ojb.broker.accesslayer.StatementManager] closeResources was
called
2003-07-10 17:18:16,379 DEBUG [org.apache.ojb.broker.accesslayer.RsIterator]
hasNext() -> false
2003-07-10 17:18:16,379 DEBUG [org.apache.ojb.odmg.JTATxManager]
getTransaction called
2003-07-10 17:18:16,379 DEBUG [org.apache.ojb.odmg.JTATxManager]
getTransactionManager called
2003-07-10 17:18:16,379 DEBUG [org.apache.ojb.odmg.JTATxManager]
getTransactionManager called
2003-07-10 17:18:16,379 DEBUG [org.apache.ojb.odmg.ObjectEnvelopeTable] PB
is in internal tx: false  broker was:
org.apache.ojb.broker.singlevm.PoolablePersistenceBroker@1de530a
2003-07-10 17:18:16,379 DEBUG [org.apache.ojb.odmg.ObjectEnvelopeTable] call
beginTransaction() on PB instance
2003-07-10 17:18:16,379 DEBUG
[org.apache.ojb.broker.accesslayer.ConnectionFactoryAbstractImpl] do
datasource lookup, name: java:TeradataDS, user: tapuser
2003-07-10 17:18:16,379 DEBUG
[org.apache.ojb.broker.accesslayer.ConnectionManagerImpl] Request new
connection from ConnectionFactory:
org.apache.ojb.broker.util.pooling.ByPassConnection@17366cb
2003-07-10 17:18:16,379 DEBUG [org.apache.ojb.odmg.J2EETransactionImpl]
Commit transaction org.apache.ojb.odmg.J2EETransactionImpl@f6af3b, commit on
broker org.apache.ojb.broker.singlevm.PoolablePersistenceBroker@1de530a
2003-07-10 17:18:16,379 DEBUG
[org.apache.ojb.broker.util.pooling.ByPassConnection] ** we ignore commit
2003-07-10 17:18:16,379 DEBUG [org.apache.ojb.odmg.TransactionImpl] Close
Transaction and release current PB
org.apache.ojb.broker.singlevm.PoolablePersistenceBroker@1de530a on tx
org.apache.ojb.odmg.J2EETransactionImpl@f6af3b
2003-07-10 17:18:16,379 DEBUG
[org.apache.ojb.broker.singlevm.PersistenceBrokerImpl] PB.close was called:
org.apache.ojb.broker.singlevm.PersistenceBrokerImpl@1d16ecf
2003-07-10 17:18:16,379 INFO  [STDOUT] vector of resultsets:1

---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-user-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-user-help@db.apache.org


Re: 1:N association - truncating list to 1 when query

Posted by Thomas Mahler <th...@web.de>.
Hi Alex,

Bates, Alex wrote:
> I have a 1:N association - but in my case, the 1 doesn't store a collection
> of the N.  Instead, each of the N stores a reference the parent 1.  I didn't
> see any examples of how to do this in the JUnits or docs. 

Have a look at the Productgroup - Article examples in the testcases.
Productgroup has a collection of Atricles. Ok, you don't have this, so 
just omitt the collection-descriptor.
And each Article has a reference to its productgroup using 
areferencedescriptor.

So what you describe is not that special and OJB will handle it without 
any problems.

please see my comments below:

> To make things more concrete, I have a QueryVO class (not to be confused
> with OJB's query classes), which has a 1:N relationship with ResultSetVO
> class.  Each ResultSetVO has a single parent QueryVO (QueryVO is a member of
> ResultSetVO).  
> 
> ---------------  Class definitions ------------------------
> 
> public class ResultSetVO implements VOInterface {
>     protected Object id = null;
>     protected String label = null;
>     protected QueryVO query = null;	..
> }

There is no foreign attribute referencing the associated QueryVO !

> 
> public class QueryVO implements VOInterface {
>     protected Object id;
>     protected String label;
>     protected String sql;
> }
> 
> So, what I want to be able to do is: navigate from the CHILD (one of the N)
> to the PARENT (the 1).  Notice that ResultSetVO stores a reference to the
> parent QueryVO, but QueryVO does NOT store a collection of child
> ResultSetVOs.
> 
> All the examples I see in the docs and Junit that use inverse-foreignkey use
> it for the opposite: the parent has a collection of children (in my case,
> QueryVO would have a collection of ResultSetVOs).  But my case is different:
> I need to define how ResultSetVO can reference QueryVO.
> 
> Using the mapping file below, I am able to create ResultSetVOs that are
> mapped to QueryVOs, and persist them (without errors).  However, when I try
> to retrieve the list of ResultSetVOs, it always truncates the list at 1.  I
> found this to be true using both the low-level PB API, and using an ODMG OQL
> query.
> 
> Details: I'm running the Jboss/J2EE version of OJB; using the ODMG API; at
> the bottom is the log output where the truncation occurs.
> 
> 
> ---------------  Mapping File ------------------------
> 
> <!-- Definitions for com.teradata.tap.component.system.query.QueryVO -->
>    <class-descriptor
>    	  class="com.teradata.tap.component.system.query.QueryVO"
>    	  table="TapQuery"
>    >
>       <field-descriptor
>          name="id"
>          column="ID"
>          jdbc-type="INTEGER"
>          primarykey="true"
>          autoincrement="true"
>       />
>       <field-descriptor
>          name="label"
>          column="Label"
>          jdbc-type="VARCHAR"
>       />
>       <field-descriptor
>          name="sql"
>          column="SqlString"
>          jdbc-type="VARCHAR"
>       />
>    </class-descriptor> 
> 
> <!-- Definitions for com.teradata.tap.component.system.resultset.ResultSetVO
> -->
>    <class-descriptor
>    	  class="com.teradata.tap.component.system.resultset.ResultSetVO"
>    	  table="TapResultset"
>    >
>       <field-descriptor
>          name="id"
>          column="ID"
>          jdbc-type="INTEGER"
>          primarykey="true"
>          autoincrement="true"
>       />
>       <field-descriptor
>          name="label"
>          column="Label"
>          jdbc-type="VARCHAR"
>       />
>       <field-descriptor
>          name="maxRows"
>          column="MaxRows"
>          jdbc-type="INTEGER"
>       />
>       <field-descriptor
>          name="queryTimeoutSecs"
>          column="QueryTimeoutSecs"
>          jdbc-type="INTEGER"
>       />
> 	<reference-descriptor name="query"
> 		class-ref="com.teradata.tap.component.system.query.QueryVO"
> 		auto-retrieve="true"
> 	        auto-update="true">		
> 			<foreignkey field-ref="id" />
> 	</reference-descriptor>

!!!
You are using ResultSetVO.id as primary key *and* as foreign key 
referencing the QueryVO.
As id is unique you will end up with seeing only 1 ResultSetVO for each 
QueryVO.
This is exactly the behaviour you see!

You must define and additional foreign-key attribute 
ResultSetVO.queryVOId and use this field as foreignkey field-ref !

(If you do not want to have extra foreign key attributes intruding you 
persistent classes you can use the anonymous fields feature.
But I recommend to start with the more easy solution mentioned above first.)

cheers,
Thomas


>    </class-descriptor> 
> 
> 
> -------------------- Detailed logging output --------------------------
> 
> 2003-07-10 17:18:15,864 DEBUG
> [org.apache.ojb.broker.accesslayer.JdbcAccessImpl] executeQuery : Query from
> class com.teradata.tap.component.system.resultset.ResultSetVO where
> org.apache.ojb.broker.query.Criteria@34cdfc
> 2003-07-10 17:18:15,879 DEBUG
> [org.apache.ojb.broker.accesslayer.sql.SqlGeneratorDefaultImpl] SQL: SELECT
> A0.MaxRows,A0.QueryTimeoutSecs,A0.Label,A0.ID FROM TapResultset A0
> 2003-07-10 17:18:16,192 DEBUG [org.apache.ojb.broker.accesslayer.RsIterator]
> hasNext() -> true
> 2003-07-10 17:18:16,223 DEBUG
> [org.apache.ojb.broker.singlevm.PersistenceBrokerImpl] getObjectByIdentity
> com.teradata.tap.component.system.query.QueryVO{22}
> 2003-07-10 17:18:16,223 DEBUG
> [org.apache.ojb.broker.accesslayer.sql.SqlGeneratorDefaultImpl] SQL: SELECT
> SqlString,Label,ID FROM TapQuery WHERE ID = ? 
> 2003-07-10 17:18:16,333 DEBUG
> [org.apache.ojb.broker.accesslayer.StatementManager] closeResources was
> called
> 2003-07-10 17:18:16,333 WARN
> [org.jboss.resource.adapter.jdbc.WrappedConnection] Closing a statement you
> left open, please do your own housekeeping
> 2003-07-10 17:18:16,333 DEBUG
> [org.apache.ojb.broker.accesslayer.ConnectionFactoryAbstractImpl] do
> datasource lookup, name: java:TeradataDS, user: tapuser
> 2003-07-10 17:18:16,333 DEBUG
> [org.apache.ojb.broker.accesslayer.ConnectionManagerImpl] Request new
> connection from ConnectionFactory:
> org.apache.ojb.broker.util.pooling.ByPassConnection@1be3d02
> 2003-07-10 17:18:16,379 DEBUG
> [org.apache.ojb.broker.accesslayer.StatementManager] closeResources was
> called
> 2003-07-10 17:18:16,379 DEBUG [org.apache.ojb.broker.accesslayer.RsIterator]
> hasNext() -> false
> 2003-07-10 17:18:16,379 DEBUG [org.apache.ojb.odmg.JTATxManager]
> getTransaction called
> 2003-07-10 17:18:16,379 DEBUG [org.apache.ojb.odmg.JTATxManager]
> getTransactionManager called
> 2003-07-10 17:18:16,379 DEBUG [org.apache.ojb.odmg.JTATxManager]
> getTransactionManager called
> 2003-07-10 17:18:16,379 DEBUG [org.apache.ojb.odmg.ObjectEnvelopeTable] PB
> is in internal tx: false  broker was:
> org.apache.ojb.broker.singlevm.PoolablePersistenceBroker@1de530a
> 2003-07-10 17:18:16,379 DEBUG [org.apache.ojb.odmg.ObjectEnvelopeTable] call
> beginTransaction() on PB instance
> 2003-07-10 17:18:16,379 DEBUG
> [org.apache.ojb.broker.accesslayer.ConnectionFactoryAbstractImpl] do
> datasource lookup, name: java:TeradataDS, user: tapuser
> 2003-07-10 17:18:16,379 DEBUG
> [org.apache.ojb.broker.accesslayer.ConnectionManagerImpl] Request new
> connection from ConnectionFactory:
> org.apache.ojb.broker.util.pooling.ByPassConnection@17366cb
> 2003-07-10 17:18:16,379 DEBUG [org.apache.ojb.odmg.J2EETransactionImpl]
> Commit transaction org.apache.ojb.odmg.J2EETransactionImpl@f6af3b, commit on
> broker org.apache.ojb.broker.singlevm.PoolablePersistenceBroker@1de530a
> 2003-07-10 17:18:16,379 DEBUG
> [org.apache.ojb.broker.util.pooling.ByPassConnection] ** we ignore commit
> 2003-07-10 17:18:16,379 DEBUG [org.apache.ojb.odmg.TransactionImpl] Close
> Transaction and release current PB
> org.apache.ojb.broker.singlevm.PoolablePersistenceBroker@1de530a on tx
> org.apache.ojb.odmg.J2EETransactionImpl@f6af3b
> 2003-07-10 17:18:16,379 DEBUG
> [org.apache.ojb.broker.singlevm.PersistenceBrokerImpl] PB.close was called:
> org.apache.ojb.broker.singlevm.PersistenceBrokerImpl@1d16ecf
> 2003-07-10 17:18:16,379 INFO  [STDOUT] vector of resultsets:1
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: ojb-user-unsubscribe@db.apache.org
> For additional commands, e-mail: ojb-user-help@db.apache.org
> 
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-user-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-user-help@db.apache.org