Kodo 3.3.3, InverseManager, 1:1 Relation
Hi,
I am evaluating Kodo at the moment and have a problem with the inverse
manager. I have a class 'BaseClassPC' which has a reference to a class
'ReferencedClassPC'. It is a simple 1:1 bidirectional relation, so in
the table for class 'BaseclassPC' I have a column
'REFERENCEDCLASS_JDOID' which points to the JDOID of the referenced
class. I have no foreign key back from REFERENCEDCLASS to BASECLASS.
Now, when I want to set the association between the two objects in my
code this only works when I call baseclass.setReferencedClass(...). When
I try to do it the other way round (referencedclass.setBaseclass(..)) I
get an exception on commit, even though I set kodo.InverseManager=true
in my kodo.properties. The error only occurs when I create both objects
and set the reference within one transaction. Excerpt from the stacktrace:
NestedThrowablesStackTrace:
kodo.util.FatalUserException: Attempt to set column
"BASECLASSPC.REFERENCEDCLASS_JDOID" to two different values:
(null)"null", (class java.lang.Long)"251" This can occur when you fail
to set both sides of a two-sided relation between objects, or when you
map different fields to the same column, but you do not keep the values
of these fields in synch.
at kodo.jdbc.sql.PrimaryRow.setObject(PrimaryRow.java:215)
at kodo.jdbc.sql.RowImpl.flushJoinValues(RowImpl.java:267)
at kodo.jdbc.sql.RowImpl.flushForeignKey(RowImpl.java:189)
at kodo.jdbc.sql.RowImpl.setForeignKey(RowImpl.java:158)
at kodo.jdbc.sql.PrimaryRow.setForeignKey(PrimaryRow.java:128)
The doku for the inverse manager says 'Under this setting, Kodo detects
changes to either side of a bidirectional relation, and automatically
sets the other side appropriately on flush.' So I was expecting that it
does not matter on which side I set the relation, nor that I have to set
the relation in two separate transactions, am I wrong?
Here is the sample code, executed in a single transaction:
BaseclassPC base = new BaseclassPC();
ReferencedClassPC ref = new ReferencedClassPC();
//base.setRefClass(ref); <-- works
ref.setSubclass(base); <-- fails
getPersistenceManager().makePersistent(base);
getPersistenceManager().makePersistent(ref);
BTW: It does not matter in which order I make the calls to
makePersistent(...).
Thanks very much,
Jochen
Hi Stephen,
shame on me, I really forgot the put this attribute, sorry that I
bothered you. Another question about the inverse manager: Are there any
limitations that I have to take into account when mapping my classes?
E.g. I read somewhere in this forum that the IM does not work for
horizontal mappings. Background is that I want to switch from another
JDO vendor to Kodo, because the other vendor's implementation of inverse
management was damn buggy, and I want to make sure to have reliable
inverse management this time ;)
Thanks,
Jochen
Stephen Kim wrote:
Did you set the inverse-owner attribute? Kodo will only manasge
inverses which are marked as inverse relations.
Jochen Kressin wrote:
Hi,
I am evaluating Kodo at the moment and have a problem with the inverse
manager. I have a class 'BaseClassPC' which has a reference to a class
'ReferencedClassPC'. It is a simple 1:1 bidirectional relation, so in
the table for class 'BaseclassPC' I have a column
'REFERENCEDCLASS_JDOID' which points to the JDOID of the referenced
class. I have no foreign key back from REFERENCEDCLASS to BASECLASS.
Now, when I want to set the association between the two objects in my
code this only works when I call baseclass.setReferencedClass(...).
When I try to do it the other way round
(referencedclass.setBaseclass(..)) I get an exception on commit, even
though I set kodo.InverseManager=true in my kodo.properties. The error
only occurs when I create both objects and set the reference within
one transaction. Excerpt from the stacktrace:
NestedThrowablesStackTrace:
kodo.util.FatalUserException: Attempt to set column
"BASECLASSPC.REFERENCEDCLASS_JDOID" to two different values:
(null)"null", (class java.lang.Long)"251" This can occur when you fail
to set both sides of a two-sided relation between objects, or when you
map different fields to the same column, but you do not keep the
values of these fields in synch.
at kodo.jdbc.sql.PrimaryRow.setObject(PrimaryRow.java:215)
at kodo.jdbc.sql.RowImpl.flushJoinValues(RowImpl.java:267)
at kodo.jdbc.sql.RowImpl.flushForeignKey(RowImpl.java:189)
at kodo.jdbc.sql.RowImpl.setForeignKey(RowImpl.java:158)
at kodo.jdbc.sql.PrimaryRow.setForeignKey(PrimaryRow.java:128)
The doku for the inverse manager says 'Under this setting, Kodo
detects changes to either side of a bidirectional relation, and
automatically sets the other side appropriately on flush.' So I was
expecting that it does not matter on which side I set the relation,
nor that I have to set the relation in two separate transactions, am I
wrong?
Here is the sample code, executed in a single transaction:
BaseclassPC base = new BaseclassPC();
ReferencedClassPC ref = new ReferencedClassPC();
//base.setRefClass(ref); <-- works
ref.setSubclass(base); <-- fails
getPersistenceManager().makePersistent(base);
getPersistenceManager().makePersistent(ref);
BTW: It does not matter in which order I make the calls to
makePersistent(...).
Thanks very much,
Jochen
Similar Messages
-
Does KODO support additional persistent columns in a relation table?
Examples would be a timestamp or an additional flag. Currently the
relation table is updated automatically by the objects in the
relationship, but there is no object representing the relation table
itself.<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
Hi,
<br>we faced the same need and have gone ahead with a slew of relation
classes/subclasses with rules in them to manage their rightness. the default
relation table is not amenable to model complex associations.
<br>shridhar
<br>
<hr WIDTH="100%">
<br>
<p>Patrick Linskey wrote:
<blockquote TYPE=CITE>Currently, the only way to implement this is to write
your own relation
<br>class. We plan on implementing something along these lines down the
road,
<br>but it's not high on our new feature list at this point.
<p>-Patrick
<p>On 6/11/02 5:44 PM, "Todd Bowker" <[email protected]> wrote:
<p>> Does KODO support additional persistent columns in a relation table?
<br>> Examples would be a timestamp or an additional flag. Currently the
<br>> relation table is updated automatically by the objects in the
<br>> relationship, but there is no object representing the relation table
<br>> itself.
<p>--
<br>Patrick Linskey [email protected]
<br>SolarMetric Inc. http://www.solarmetric.com</blockquote>
</html> -
When primary table is also join table and you have NOT NULL constraints
Hi,
Me again. This is similar to the message titled "Problem with an
optional 1 to 1 relationship modelled using a link table". Whats
different about this case is we are dealing with a one to many relationship.
Given this SQL:
create table person (
pid INTEGER(10) NOT NULL,
language_code VARCHAR(3) NOT NULL
create table language_person (
pid INTEGER(10) NOT NULL REFERENCES person(pid),
language_code VARCHAR(3) NOT NULL,
first_name VARCHAR(20) NOT NULL
I wrote these classes (abbreviated)
Person:
* @jdo:persist
* @jdo:identity-type application
* @jdo:objectid-class PersonId
* @jdo:requires-extent false
* @jdo:extension vendor-name="kodo" key="table"
* value="PERSON"
* @jdo:extension vendor-name="kodo" key="lock-column"
* value="none"
* @jdo:extension vendor-name="kodo" key="class-column"
* value="none"
public class Person {
* @jdo:primary-key true
* @jdo:extension vendor-name="kodo" key="data-column"
* value="PID"
private int pid;
* @jdo:extension vendor-name="kodo" key="data-column"
* value="LANGUAGE_CODE"
private String languageCode;
* @jdo:collection element-type="LanguagePerson"
* @jdo:extension vendor-name="kodo" key="pid-data-column"
* value="PID"
* @jdo:extension vendor-name="kodo" key="table"
* value="LANGUAGE_PERSON"
* @jdo:extension vendor-name="kodo" key="pid-ref-column"
* value="PID"
* @jdo:extension vendor-name="kodo"
key="languageCode-data-column"
* value="LANGUAGE_CODE"
* @jdo:extension vendor-name="kodo"
key="languageCode-ref-column"
* value="LANGUAGE_CODE"
private Set languagePersons = new HashSet();
public Person(int pid, String languageCode) {
this.pid = pid;
this.languageCode = languageCode;
public void addLanguagePerson(LanguagePerson languagePerson) {
languagePersons.add(languagePerson);
public Set getLanguagePersons() {
return languagePersons;
LANGUAGE_PERSON
* @jdo:persist
* @jdo:identity-type application
* @jdo:objectid-class LanguagePersonId
* @jdo:requires-extent false
* @jdo:extension vendor-name="kodo" key="table"
* value="LANGUAGE_PERSON"
* @jdo:extension vendor-name="kodo" key="lock-column"
* value="none"
* @jdo:extension vendor-name="kodo" key="class-column"
* value="none"
public class LanguagePerson {
* @jdo:primary-key true
* @jdo:extension vendor-name="kodo" key="data-column"
* value="PID"
private int pid;
* @jdo:primary-key true
* @jdo:extension vendor-name="kodo" key="data-column"
* value="LANGUAGE_CODE"
private String languageCode;
* @jdo:extension vendor-name="kodo" key="data-column"
* value="FIRST_NAME"
private String firstName;
public LanguagePerson(int pid, String languageCode, String firstName) {
this.pid = pid;
this.languageCode = languageCode;
this.firstName = firstName;
And then I do this:
PersistenceManager pm = JDOFactory.getPersistenceManager();
pm.currentTransaction().begin();
final Person person = new Person(1,"EN");
final LanguagePerson languagePerson = new
LanguagePerson(1,"EN","Mike");
person.addLanguagePerson(languagePerson);
pm.makePersistent(person);
pm.currentTransaction().commit();
The SQL that issues forth is this:
1125 [main] INFO jdbc.SQL - [ C:6588476; T:6166426; D:2891371 ]
preparing statement <17089909>: INSERT INTO PERSON(LANGUAGE_CODE, PID)
VALUES (?, ?)
1125 [main] INFO jdbc.SQL - [ C:6588476; T:6166426; D:2891371 ]
executing statement <17089909>: [reused=1;params={(String)EN,(int)1}]
1125 [main] INFO jdbc.SQL - [ C:6588476; T:6166426; D:2891371 ]
preparing statement <9818046>: INSERT INTO
LANGUAGE_PERSON(LANGUAGE_CODE, PID) VALUES (?, ?)
1125 [main] INFO jdbc.SQL - [ C:6588476; T:6166426; D:2891371 ]
executing statement <9818046>: [reused=1;params={(String)EN,(int)1}]
1140 [main] INFO jdbc.SQL - [ C:6588476; T:6166426; D:2891371 ]
preparing statement <24763620>: INSERT INTO LANGUAGE_PERSON(FIRST_NAME,
LANGUAGE_CODE, PID) VALUES (?, ?, ?)
1140 [main] INFO jdbc.SQL - [ C:6588476; T:6166426; D:2891371 ]
executing statement <24763620>:
[reused=1;params={(String)Mike,(String)EN,(int)1}]
And the second INSERT fails on Oracle because FIRST_NAME is null, and
the table definition requires it to be NOT NULL.
Is there anyway I can get Kodo to figure out its dealing with the same
table for inserting the link columns and the full row, and optimize
accordingly i.e do one INSERT for LANGUAGE_PERSON?
I guess my only other options are a) introduce an explicit link table or
b) define a custom mapping?
Thanks,
Mike.There are examples of 1-Many mappings in the documentation:
http://www.solarmetric.com/Software/Documentation/latest/docs/
ref_guide_meta_examples.html
The important point I think you've missed is that right now, 1-many
mappings always require an inverse 1-1 mapping. Again, see the docs
above.
So your LanguagePerson needs a field of type Person, and whenever you add
a LanguagePerson to a Person, make sure to set that LanguagePerson's
Person too. LanguagePerson.person will use the same PID column as
LanguagePeson.pid. Kodo has no problem with having 2 mappings
mapped to the same column.
Kodo 3.0 will allow 1-Many relations without an inverse 1-1. -
URGENT help !! 1-n relationship
Hi ,
i'm evaluation kodo (first impression : extremely powerful!)
I'm trying to test a 1:n relationship with a join query between two tables
(mysql database) , but i can't generate (by kodo) a single sql join
statement. When i run the following code i have a query for
TCatalogorisorse (obtaining a collection) and then automatically N query
(for each element in the collection) on the TTiporisorsa table.....The
results are correct...but i want a single join statement!!! help me, please
This is the relationship followed by the columns:
TCatalogorisorse (N) -------- (1) TTiporisorsa
TCatalogorisorse [car_Code, car_Descrizione, car_Unitamisura ]
TTiporisorsa[tpr_code,tpr_descrizione]
Java code:
public class TCatalogorisorse
private int carCode;
private String carDescrizione;
private int carUnitamisura;
private TTiporisorsa risorsa;
public class TTiporisorsa
private int tprCode;
private String tprDescrizione;
private Collection risorse ;
Query:
PersistenceManagerFactory pmf = new JDBCPersistenceManagerFactory ();
PersistenceManager pm = pmf.getPersistenceManager ();
Query query = pm.newQuery (provajdo.business.TCatalogorisorse.class);
Collection results = (Collection) query.execute ();
Metadata:
<class name="TCatalogorisorse" objectid-class="TCatalogorisorseId">
<extension key="class-column" value="none" vendor-name="kodo"/>
<extension key="lock-column" value="none" vendor-name="kodo"/>
<extension key="table" value="t_catalogorisorse"
vendor-name="kodo"/>
<field name="carCode" primary-key="true">
<extension key="data-column" value="CAR_CODE"
vendor-name="kodo"/>
</field>
<field name="carDescrizione">
<extension key="data-column" value="CAR_DESCRIZIONE"
vendor-name="kodo"/>
</field>
<field name="carUnitamisura">
<extension key="data-column" value="CAR_UNITAMISURA"
vendor-name="kodo"/>
</field>
<field name="risorsa">
<extension key="tprCode-data-column" value="TPR_CODE"
vendor-name="kodo"/>
</field>
</class>
<class name="TTiporisorsa" objectid-class="TTiporisorsaId">
<extension key="class-column" value="none" vendor-name="kodo"/>
<extension key="lock-column" value="none" vendor-name="kodo"/>
<extension key="table" value="t_tiporisorsa"
vendor-name="kodo"/>
<field name="tprCode" primary-key="true">
<extension key="data-column" value="TPR_CODE"
vendor-name="kodo"/>
</field>
<field name="tprDescrizione">
<extension key="data-column" value="TPR_DESCRIZIONE"
vendor-name="kodo"/>
</field>
<field name="risorse">
<collection element-type="TCatalogorisorse"/>
<extension vendor-name="kodo" key="element-inverse"
value="risorsa"/>
</field>
</class>Thanks Abe,
so are you saying me that kodo doesnt't currently generate dynamic sql
with outer joins?
can't i have
select a.X,b.Y
from a,b
where
a.Z=b.K
please confirm my (last)
conclusion!!
thanks
for the support... yes i would like an unique sql statement like this :
select *
from t_catalogorisorse cr , t_tiporisorsa tr
where cr.tpr_code=tr.tpr_code;
....are you saying me that actually is not possible and so i must wait for
kodo 3? (when it will be available?)...
i am testing kodo to change the way to access databases (manually
constructing queries :-( ) and this could be a big limitation, for big
tables/databases this could be non good (i think).
please reply with the definitive affermation.
thanks
Abe White wrote:
Currently Kodo does not perform eager loading of relations. Kodo 3.0
will support eager loading via outer joins (for 1-1) and batched selects
(for 1-M/M-M). It lseems you're looking for a way to prevent extra
queries for each TTiporisorsa when you read the set of all
TCatalogorisorses. One way to accomplish this is to do a query for all
the TTiporisorsas that will be loaded before you do your query for the
related TCatalogorisorses. When you traverse the collection of
TTiporisorsas, they will become cached. Then when each TCatalogorisorse
loads its related TTiporisorsa, it will find it in the cache, and won't
have to make a data store trip. So you end up with 2 queries instaed of
(1 + #TCatalogorisorses). -
Problem creating non-persistent Child Objects
I have the need to create a non persistable child object in the
jdoPreStore of a parent object. I then perform some tests on the parent
to determine if the child object needs to be persisted or not. If I leave
the child non persistent it still writes to the database.
I was performing the follwoing piece of code
Class Parent {
// The relationship is a 0 to many
public Child createChild() {
Child child = .....//create non persistent object
child.setParent(this);
getChild().add(child);
It appears that if I remove the getChild().add(child). It does not
persist (as desired).
Is this correct behaviour?? I dont think that it should be, but if it is
then I have a further problem.
If that child object inherits from another object and you remove the
getChild().add(child) kodo outputs an invalid object to the database. It
doesnt insert a row to the child table. But it inserts a row to the
childs inherited object table. This is now an invalid object and will
fail upon loading.
Any help on this would be appreciated.
Thanks
Luke.JDO has something called persistence by reachability. This means that
objects do not have to explicitly be marked as to be persistent as JDO
will traverse the object graph to ensure that all nodes are persistent.
I think you are seeing this behavior combined with another side
behavior: Kodo requires that both sides of a relation be set.
Basically, keep your objects in synch (set both sides of the relation).
And if you want to hold onto a reference to non-persistent object
before you decide what to do with it, add a transient field or a field
marked "persistence-modifier="none"" in your metadata and then process
those transient fields in jdoPreStore ().
i.e.
if (//businessLogic is true)
persistentField = transientField;
Luke wrote:
I have the need to create a non persistable child object in the
jdoPreStore of a parent object. I then perform some tests on the parent
to determine if the child object needs to be persisted or not. If I leave
the child non persistent it still writes to the database.
I was performing the follwoing piece of code
Class Parent {
// The relationship is a 0 to many
public Child createChild() {
Child child = .....//create non persistent object
child.setParent(this);
getChild().add(child);
It appears that if I remove the getChild().add(child). It does not
persist (as desired).
Is this correct behaviour?? I dont think that it should be, but if it is
then I have a further problem.
If that child object inherits from another object and you remove the
getChild().add(child) kodo outputs an invalid object to the database. It
doesnt insert a row to the child table. But it inserts a row to the
childs inherited object table. This is now an invalid object and will
fail upon loading.
Any help on this would be appreciated.
Thanks
Luke.
Steve Kim
[email protected]
SolarMetric Inc.
http://www.solarmetric.com -
Support for "Interface Based Design"
I would like two PC classes that implement a common interface, but the two
PC classes are not related by inheritance, and would not be stored in the
same table. For example,
public interface VersionNumber {
int getNumber();
boolean isComparableTo( VersionNumber vn );
/** PC class **/
public class BasicVersionNumber implements VersionNumber {
/** PC class **/
public class CustomVersionNumber implements VersionNumber {
/** PC class **/
public class Paper {
VersionNumber vn;
Since "BasicVersionNumber" and "CustomVersionNumber" are not related via
inheritance, they would not generally reside in the same database table.
It would mean that the table containing "Paper" would need both the target
table for this instance of "vn", and the primary key for "vn". It appears
that KODO assumes the target table is available in the Meta-Data file, but
with interface-based design, that is not known until run time and could be
different for different instances of class "Paper".
Is it possible to do this with KODO? Where can I go to understand how.
Keith L. Musser
Integrated Dynamics, Inc.
812-371-7777
email: [email protected]
Disclaimer - This email, and any files transmitted with it, are confidential
and may contain privileged or copyright information. If you are not the
intended recipient you must not copy, distribute or use this email, or the
information contained herein, for any purpose other than to notify us. If
you received this email in error, please notify the sender immediately, and
delete this email from your system.Kodo supports interfaces as fields (in Kodo 3, we support interfaces for
more relation types). Kodo will store the toString () of the JDO
identity for the actual concrete instance in the column as there is no
formal O/R relation between the table and the interface field type.
Keith Musser wrote:
I would like two PC classes that implement a common interface, but the two
PC classes are not related by inheritance, and would not be stored in the
same table. For example,
public interface VersionNumber {
int getNumber();
boolean isComparableTo( VersionNumber vn );
/** PC class **/
public class BasicVersionNumber implements VersionNumber {
/** PC class **/
public class CustomVersionNumber implements VersionNumber {
/** PC class **/
public class Paper {
VersionNumber vn;
Since "BasicVersionNumber" and "CustomVersionNumber" are not related via
inheritance, they would not generally reside in the same database table.
It would mean that the table containing "Paper" would need both the target
table for this instance of "vn", and the primary key for "vn". It appears
that KODO assumes the target table is available in the Meta-Data file, but
with interface-based design, that is not known until run time and could be
different for different instances of class "Paper".
Is it possible to do this with KODO? Where can I go to understand how.
Steve Kim
[email protected]
SolarMetric Inc.
http://www.solarmetric.com -
Relational queries through JDBC with the help of Kodo's metadata for O/R mapping
Due to JDOQL's limitations (inability to express joins, when relationships
are not modeled as object references), I find myself needing to drop down to
expressing some queries in SQL through JDBC. However, I still want my Java
code to remain independent of the O/R mapping. I would like to be able to
formulate the SQL without hardcoding any knowledge of the relational table
and column names, by using Kodo's metadata. After poking around the Kodo
Javadocs, it appears as though the relevant calls are as follows:
ClassMetaData cmd = ClassMetaData.getInstance(MyPCObject.class, pm);
FieldMetaData fmd = cmd.getDeclaredField( "myField" );
PersistenceManagerFactory pmf = pm.getPersistenceManagerFactory();
JDBCConfiguration conf = (JDBCConfiguration)
((EEPersistenceManagerFactory)pmf).getConfiguration();
ClassResolver resolver = pm.getClassResolver(MyPCObject.class);
Connector connector = new PersistenceManagerConnector(
(PersistenceManagerImpl) pm );
DBDictionary dict = conf.getDictionary( connector );
FieldMapping fm = ClassMapping.getFieldMapping(fmd, conf, resolver, dict);
Column[] cols = fm.getDataColumns();
Does that look about right?
Here's what I'm trying to do:
class Foo
String name; // application identity
String bar; // foreign key to Bar
class Bar
String name; // application identity
int weight;
Let's say I want to query for all Foo instances for which its bar.weight >
100. Clearly this is trivial to do in JDOQL, if Foo.bar is an object
reference to Bar. But there are frequently good reasons for modeling
relationships as above, for example when Foo and Bar are DTOs exposed by the
remote interface of an EJB. (Yeah, yeah, I'm lazy, using my
PersistenceCapable classes as both the DAOs and the DTOs.) But I still want
to do queries that navigate the relationship; it would be nice to do it in
JDOQL directly. I will also want to do other weird-ass queries that would
definitely only be expressible in SQL. Hence, I'll need Kodo's O/R mapping
metadata.
Is there anything terribly flawed with this logic?
BenI have a one point before I get to this:
There is nothing wrong with using PC instances as both DAO and DTO
objects. In fact, I strongly recommend this for most J2EE/JDO design.
However, there should be no need to expose the foreign key values... use
application identity to quickly reconstitute an object id (which can in
turn find the persistent version), or like the j2ee tutorial, store the
object id in some form (Object or String) and use that to re-find the
matching persistent instance at the EJB tier.
Otherwise, there is a much easier way of finding ClassMapping instances
and in turn FieldMapping instances (see ClassMapping.getInstance () in
the JavaDocs).
Ben Eng wrote:
Due to JDOQL's limitations (inability to express joins, when relationships
are not modeled as object references), I find myself needing to drop down to
expressing some queries in SQL through JDBC. However, I still want my Java
code to remain independent of the O/R mapping. I would like to be able to
formulate the SQL without hardcoding any knowledge of the relational table
and column names, by using Kodo's metadata. After poking around the Kodo
Javadocs, it appears as though the relevant calls are as follows:
ClassMetaData cmd = ClassMetaData.getInstance(MyPCObject.class, pm);
FieldMetaData fmd = cmd.getDeclaredField( "myField" );
PersistenceManagerFactory pmf = pm.getPersistenceManagerFactory();
JDBCConfiguration conf = (JDBCConfiguration)
((EEPersistenceManagerFactory)pmf).getConfiguration();
ClassResolver resolver = pm.getClassResolver(MyPCObject.class);
Connector connector = new PersistenceManagerConnector(
(PersistenceManagerImpl) pm );
DBDictionary dict = conf.getDictionary( connector );
FieldMapping fm = ClassMapping.getFieldMapping(fmd, conf, resolver, dict);
Column[] cols = fm.getDataColumns();
Does that look about right?
Here's what I'm trying to do:
class Foo
String name; // application identity
String bar; // foreign key to Bar
class Bar
String name; // application identity
int weight;
Let's say I want to query for all Foo instances for which its bar.weight >
100. Clearly this is trivial to do in JDOQL, if Foo.bar is an object
reference to Bar. But there are frequently good reasons for modeling
relationships as above, for example when Foo and Bar are DTOs exposed by the
remote interface of an EJB. (Yeah, yeah, I'm lazy, using my
PersistenceCapable classes as both the DAOs and the DTOs.) But I still want
to do queries that navigate the relationship; it would be nice to do it in
JDOQL directly. I will also want to do other weird-ass queries that would
definitely only be expressible in SQL. Hence, I'll need Kodo's O/R mapping
metadata.
Is there anything terribly flawed with this logic?
Ben
Steve Kim
[email protected]
SolarMetric Inc.
http://www.solarmetric.com -
1xM relation working in Hibernate doesn't work in Kodo and EclipseLink
Greetings,
I'm migrating some applications from JBoss/Hibernate to WebLogic 10gR3 and I found lots of JPA problems. In order to simplify the context, I used a very simple one to many bidirectional relationship between 2 entities. Using the following persistence.xml file:
<?xml version="1.0"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="ww204-jpa" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>cgDataSource</jta-data-source>
<class>fr.simplex_software.jpa.Employee</class>
<class>fr.simplex_software.jpa.Department</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.transaction.factory_class"
value="org.hibernate.transaction.JTATransactionFactory" />
<property name="hibernate.transaction.manager_lookup_class"
value="org.hibernate.transaction.WeblogicTransactionManagerLookup" />
<property name="jta.UserTransaction" value="java:comp/UserTransaction" />
</properties>
</persistence-unit>
</persistence>
the test works correctly on WebLogic 10gR3. Now, I'm modifying the persistence.xml to read:
<?xml version="1.0"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="ww204-jpa" transaction-type="JTA">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<jta-data-source>cgDataSource</jta-data-source>
<class>fr.simplex_software.jpa.Employee</class>
<class>fr.simplex_software.jpa.Department</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="kodo.jdbc.SynchronizeMappings" value="refresh" />
</properties>
</persistence-unit>
</persistence>
The test raises the following exception:
Exception in thread "Main Thread" java.lang.ClassCastException: fr.simplex_software.jpa.Department
at fr.simplex_software.slsb.Facade_7ky0ac_FacadeRemoteImpl_WLSkel.invoke(Unknown Source)
at weblogic.rmi.internal.BasicServerRef.invoke(BasicServerRef.java:589)
at weblogic.rmi.cluster.ClusterableServerRef.invoke(ClusterableServerRef.java:230)
at weblogic.rmi.internal.BasicServerRef$1.run(BasicServerRef.java:477)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:363)
at weblogic.security.service.SecurityManager.runAs(Unknown Source)
at weblogic.rmi.internal.BasicServerRef.handleRequest(BasicServerRef.java:473)
at weblogic.rmi.internal.wls.WLSExecuteRequest.run(WLSExecuteRequest.java:118)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:201)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:173)
If I modify the persistence.xml to read:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="ww204-jpa" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider </provider>
<jta-data-source>cgDataSource</jta-data-source>
<class>fr.simplex_software.jpa.Employee</class>
<class>fr.simplex_software.jpa.Department</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
<property name="eclipselink.ddl-generation.output-mode"
value="database" />
</properties>
</persistence-unit>
</persistence>
the test raises the same exception. If I come back to the first persistence.xml file, the test works properly again. Is there something I'm doing wrong ?
Many thanks in advance for any help.
NicolasPerforming the following operations after having changed the persistence.xml file solve the problem:
1. Undeploy the application.
2. Run appc to re-generate stubs and copy them on the client CLASSPATH (see also How to run a Java EE client application ?
3. Stop the server.
4. Start the server.
5. Re-deploy the application.
All the above operations are purhaps not absolutely required but the whole procedure is sufficient to provide the expected result.
Kind regards,
Nicolas -
Kodo & non relational data storage
I noticed you are working on LDAP adapter for Kodo. That's nice
I was wondering why didn't you try to have support for Oracle Objects. It
should be relatively easy to map JDO onto oracle objects. JDQL might be
tricky but mapping itself should be pretty straightforward
I think the primary reason people do not use oracle objects much because
oracle did not provide any reasonable client binding mechanism. Their
JPublisher is pretty useless but given JDO frontent it will be nice
AlexAlex,
Kodo supports Versant object database as persistent storage in
Kodo/Versant JDO version.
Pinaki
Alex Roytman wrote:
I noticed you are working on LDAP adapter for Kodo. That's nice
I was wondering why didn't you try to have support for Oracle Objects. It
should be relatively easy to map JDO onto oracle objects. JDQL might be
tricky but mapping itself should be pretty straightforward
I think the primary reason people do not use oracle objects much because
oracle did not provide any reasonable client binding mechanism. Their
JPublisher is pretty useless but given JDO frontent it will be nice
Alex -
(Managed) Inverse relations and map mapping
Hi.
Is there any limitation in using (managed) inverse relations together
with map mapping? I've tried to setup my test model like this: a single
City object holds references to many Street objects. City has "name"
attribute , collection named "streetsList" (1-n with Streets) and map
named "streetsMap"(n-to-many map with Streets). Street objects have just
simple "name" attribute and single "city" reference to City object.
What I'd like to achieve is have Kodo to set inverse relation on Street
object (relation "city") when I put Street object into City's
"streetsMap". This works fine when using collection ("streetsList") but
doesn't seems to be working when map-mapped relation field is in use.
How do I use Kodo's inverse relations manager with map fields?
Everything is OK when I set the inverse side of relation manually
(setting Street.city field when putting Street to City.streetsMap) - but
I'd like InverseManager to do it!
My configuration:
- kodo.properties:
kodo.InverseManager: true(ManageLRS=true)
- package.mapping:
<class name="City">
<jdbc-class-map type="base" pk-column="JDOID"
table="TEST_CITY"/>
<jdbc-class-ind type="metadata-value" column="JDOTYPE"/>
<field name="name">
<jdbc-field-map type="value" column="CITY_NAME"/>
</field>
<field name="streetsMap">
<jdbc-field-map type="n-many-map" key-column="MAP_KEY"
table="TEST_STREET_MAP"
value-column.JDOID="STREET_JDOID"
ref-column.JDOID="CITY_JDOID"/>
</field>
<field name="streetsList">
<jdbc-field-map type="one-many" ref-column.JDOID="CITY_JDOID"
table="TEST_STREET"/>
</field>
</class>
<class name="Street">
<jdbc-class-map type="base" pk-column="JDOID"
table="TEST_STREET"/>
<jdbc-version-ind type="version-number" column="JDOVERSION"/>
<jdbc-class-ind type="metadata-value" column="JDOTYPE"/>
<field name="name">
<jdbc-field-map type="value" column="NAME"/>
</field>
<field name="city">
<jdbc-field-map type="one-one" column.JDOID="CITY_JDOID"/>
</field>
</class>
- package.jdo:
<class name="City">
<extension key="jdbc-class-ind-value" vendor-name="kodo" value="1"/>
<field name="streetsMap">
<map key-type="String" value-type="Street"/>
<extension vendor-name="kodo" key="inverse-owner" value="city"/>
<extension vendor-name="kodo" key="lock-group" value="none"/>
</field>
<field name="streetsList">
<collection element-type="Street"/>
<extension vendor-name="kodo" key="inverse-owner" value="city"/>
<extension vendor-name="kodo" key="lock-group" value="none"/>
</field>
<field name="name">
</field>
</class>
<class name="Street">
<extension key="jdbc-class-ind-value" vendor-name="kodo" value="2"/>
<field name="name">
</field>
</class>
Regards,
Pawe____ ____wierszczUnfortunately, inverse management is not available for Maps. We hope to
make it available in a future release. -
Unit test fails after upgrading to Kodo 4.0.0 from 4.0.0-EA4
I have a group of 6 unit tests failing after upgrading to the new Kodo
4.0.0 (with BEA) from Kodo-4.0.0-EA4 (with Solarmetric). I'm getting
exceptions like the one at the bottom of this email. It seems to be an
interaction with the PostgreSQL driver, though I can't be sure. I
haven't changed my JDO configuration or the related classes in months
since I've been focusing on using the objects that have already been
defined. The .jdo, .jdoquery, and .java code are below the exception,
just in case there's something wrong in there. Does anyone have advice
as to how I might debug this?
Thanks,
Mark
Testsuite: edu.ucsc.whisper.test.integration.UserManagerQueryIntegrationTest
Tests run: 15, Failures: 0, Errors: 6, Time elapsed: 23.308 sec
Testcase:
testGetAllUsersWithFirstName(edu.ucsc.whisper.test.integration.UserManagerQueryIntegrationTest):
Caused an ERROR
The column index is out of range: 2, number of columns: 1.
<2|false|4.0.0> kodo.jdo.DataStoreException: The column index is out of
range: 2, number of columns: 1.
at
kodo.jdbc.sql.DBDictionary.newStoreException(DBDictionary.java:4092)
at kodo.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:82)
at kodo.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:66)
at kodo.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:46)
at
kodo.jdbc.kernel.SelectResultObjectProvider.handleCheckedException(SelectResultObjectProvider.java:176)
at
kodo.kernel.QueryImpl$PackingResultObjectProvider.handleCheckedException(QueryImpl.java:2460)
at
com.solarmetric.rop.EagerResultList.<init>(EagerResultList.java:32)
at kodo.kernel.QueryImpl.toResult(QueryImpl.java:1445)
at kodo.kernel.QueryImpl.execute(QueryImpl.java:1136)
at kodo.kernel.QueryImpl.execute(QueryImpl.java:901)
at kodo.kernel.QueryImpl.execute(QueryImpl.java:865)
at kodo.kernel.DelegatingQuery.execute(DelegatingQuery.java:787)
at kodo.jdo.QueryImpl.executeWithArray(QueryImpl.java:210)
at kodo.jdo.QueryImpl.execute(QueryImpl.java:137)
at
edu.ucsc.whisper.core.dao.JdoUserDao.findAllUsersWithFirstName(JdoUserDao.java:232)
at
edu.ucsc.whisper.core.manager.DefaultUserManager.getAllUsersWithFirstName(DefaultUserManager.java:252)
NestedThrowablesStackTrace:
org.postgresql.util.PSQLException: The column index is out of range: 2,
number of columns: 1.
at
org.postgresql.core.v3.SimpleParameterList.bind(SimpleParameterList.java:57)
at
org.postgresql.core.v3.SimpleParameterList.setLiteralParameter(SimpleParameterList.java:101)
at
org.postgresql.jdbc2.AbstractJdbc2Statement.bindLiteral(AbstractJdbc2Statement.java:2085)
at
org.postgresql.jdbc2.AbstractJdbc2Statement.setInt(AbstractJdbc2Statement.java:1133)
at
com.solarmetric.jdbc.DelegatingPreparedStatement.setInt(DelegatingPreparedStatement.java:390)
at
com.solarmetric.jdbc.PoolConnection$PoolPreparedStatement.setInt(PoolConnection.java:440)
at
com.solarmetric.jdbc.DelegatingPreparedStatement.setInt(DelegatingPreparedStatement.java:390)
at
com.solarmetric.jdbc.DelegatingPreparedStatement.setInt(DelegatingPreparedStatement.java:390)
at
com.solarmetric.jdbc.DelegatingPreparedStatement.setInt(DelegatingPreparedStatement.java:390)
at
com.solarmetric.jdbc.LoggingConnectionDecorator$LoggingConnection$LoggingPreparedStatement.setInt(LoggingConnectionDecorator.java:1
257)
at
com.solarmetric.jdbc.DelegatingPreparedStatement.setInt(DelegatingPreparedStatement.java:390)
at
com.solarmetric.jdbc.DelegatingPreparedStatement.setInt(DelegatingPreparedStatement.java:390)
at kodo.jdbc.sql.DBDictionary.setInt(DBDictionary.java:980)
at kodo.jdbc.sql.DBDictionary.setUnknown(DBDictionary.java:1299)
at kodo.jdbc.sql.SQLBuffer.setParameters(SQLBuffer.java:638)
at kodo.jdbc.sql.SQLBuffer.prepareStatement(SQLBuffer.java:539)
at kodo.jdbc.sql.SQLBuffer.prepareStatement(SQLBuffer.java:512)
at kodo.jdbc.sql.SelectImpl.execute(SelectImpl.java:332)
at kodo.jdbc.sql.SelectImpl.execute(SelectImpl.java:301)
at kodo.jdbc.sql.Union$UnionSelect.execute(Union.java:642)
at kodo.jdbc.sql.Union.execute(Union.java:326)
at kodo.jdbc.sql.Union.execute(Union.java:313)
at
kodo.jdbc.kernel.SelectResultObjectProvider.open(SelectResultObjectProvider.java:98)
at
kodo.kernel.QueryImpl$PackingResultObjectProvider.open(QueryImpl.java:2405)
at
com.solarmetric.rop.EagerResultList.<init>(EagerResultList.java:22)
at kodo.kernel.QueryImpl.toResult(QueryImpl.java:1445)
at kodo.kernel.QueryImpl.execute(QueryImpl.java:1136)
at kodo.kernel.QueryImpl.execute(QueryImpl.java:901)
at kodo.kernel.QueryImpl.execute(QueryImpl.java:865)
at kodo.kernel.DelegatingQuery.execute(DelegatingQuery.java:787)
at kodo.jdo.QueryImpl.executeWithArray(QueryImpl.java:210)
at kodo.jdo.QueryImpl.execute(QueryImpl.java:137)
at
edu.ucsc.whisper.core.dao.JdoUserDao.findAllUsersWithFirstName(JdoUserDao.java:232)
--- DefaultUser.java -------------------------------------------------
public class DefaultUser
implements User
/** The account username. */
private String username;
/** The account password. */
private String password;
/** A flag indicating whether or not the account is enabled. */
private boolean enabled;
/** The authorities granted to this account. */
private Set<Authority> authorities;
/** Information about the user, including their name and text that
describes them. */
private UserInfo userInfo;
/** The set of organizations where this user works. */
private Set<Organization> organizations;
--- DefaultUser.jdo --------------------------------------------------
<?xml version="1.0"?>
<!DOCTYPE jdo PUBLIC
"-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 2.0//EN"
"http://java.sun.com/dtd/jdo_2_0.dtd">
<jdo>
<package name="edu.ucsc.whisper.core">
<sequence name="user_id_seq"
factory-class="native(Sequence=user_id_seq)"/>
<class name="DefaultUser" detachable="true"
table="whisper_user" identity-type="datastore">
<datastore-identity sequence="user_id_seq" column="userId"/>
<field name="username">
<column name="username" length="80" jdbc-type="VARCHAR" />
</field>
<field name="password">
<column name="password" length="40" jdbc-type="CHAR" />
</field>
<field name="enabled">
<column name="enabled" />
</field>
<field name="userInfo" persistence-modifier="persistent"
default-fetch-group="true" dependent="true">
<extension vendor-name="jpox"
key="implementation-classes"
value="edu.ucsc.whisper.core.DefaultUserInfo" />
<extension vendor-name="kodo"
key="type"
value="edu.ucsc.whisper.core.DefaultUserInfo" />
</field>
<field name="authorities" persistence-modifier="persistent"
table="user_authorities"
default-fetch-group="true">
<collection
element-type="edu.ucsc.whisper.core.DefaultAuthority" />
<join column="userId" delete-action="cascade"/>
<element column="authorityId" delete-action="cascade"/>
</field>
<field name="organizations" persistence-modifier="persistent"
table="user_organizations" mapped-by="user"
default-fetch-group="true" dependent="true">
<collection
element-type="edu.ucsc.whisper.core.DefaultOrganization"
dependent-element="true"/>
<join column="userId"/>
<!--<element column="organizationId"/>-->
</field>
</class>
</package>
</jdo>
--- DefaultUser.jdoquery ---------------------------------------------
<?xml version="1.0"?>
<!DOCTYPE jdo PUBLIC
"-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 2.0//EN"
"http://java.sun.com/dtd/jdo_2_0.dtd">
<jdo>
<package name="edu.ucsc.whisper.core">
<class name="DefaultUser">
<query name="UserByUsername"
language="javax.jdo.query.JDOQL"><![CDATA[
SELECT UNIQUE FROM edu.ucsc.whisper.core.DefaultUser
WHERE username==searchName
PARAMETERS java.lang.String searchName
]]></query>
<query name="DisabledUsers"
language="javax.jdo.query.JDOQL"><![CDATA[
SELECT FROM edu.ucsc.whisper.core.DefaultUser WHERE
enabled==false
]]></query>
<query name="EnabledUsers"
language="javax.jdo.query.JDOQL"><![CDATA[
SELECT FROM edu.ucsc.whisper.core.DefaultUser WHERE
enabled==true
]]></query>
<query name="CountUsers"
language="javax.jdo.query.JDOQL"><![CDATA[
SELECT count( this ) FROM edu.ucsc.whisper.core.DefaultUser
]]></query>
</class>
</package>
</jdo>I'm sorry, I have no idea. I suggest sending a test case that
reproduces the problem to support. -
Bug - multiple related instances of same class
We've discovered a rather subtle bug in the process by which Kodo
searches for reachable related objects to persist. If an instance of a
PC class (A) has two relationships to the same PC class (B), and both
related instances of B have the same value for their PK-field, then only
one of the related instances of B will be persisted.
Obviously, this problem only occurs in the context of application
identity. We've only encountered it when all the instances involved are
newly created and being made persistent for the first time (else the
instances would have different PK-values). It should also be noted that
we're assigning PK-values in jdoPreStore(). Here's the specific
situation we encountered:
Class A has two relationships to class B, represented by fields "B b1"
and "B b2". In our case, A.b1 is the many-side of a bidirectional
one-to-many relationship; the one-side is implemented by a field "List
aList" in B. A.b2 is the navigable side of a unidirectional
relationship; there is no corresponding field in B. (We haven't checked
whether or how the cardinality or navigability of the relationships
affects the problem.)
Let "a1" be the sole instance of A. If a1.b1 is set to an instance of B
but a1.b2 is null, and makePersistent( a1 ) is called, then a1 and b1
are persisted correctly and the relation field b2_id in TableA is NULL.
However, if a1.b2 is set to a second instance of B and both instances of
B have the same initial value of their PK-field, then a.b2 is not
persisted. Only one record is added to TableB; it corresponds to A.b1.
Interestingly, in this case the relation field b2_id in TableA is not
NULL, but has the default value of b2's PK-field. jdoPreStore() is not
called on b2 and b2 is not persisted, but its PK-field is read in the
process of persisting a1.
Since we've placed the jdoPreStore() callback in a common non-persistent
adapter superclass, we're currently able to work around the problem with
a static "seed" PK value that is incremented in the superclass default
constructor to provide a unique initial value for each PK-field. If
anyone would like the code for this approach we'll post it, although
it'll become unnecessary when the problem is fixed.
Jerry Pulley
Sr. Developer
Commerce Technologies, Inc.I'm curious what behavior, besides throwing an exception, could even be
possible. If the pm discovers two object with the same id, it seems that it
has to choose one of them to make persistent. How could it possibly resolve
differences in the fields of the two instances in deciding which one is the
correct one to put in the db? Additionally, allowing this behavior could
lead to subtle, difficult to detect bugs in your program, since ( as Abe
points out ) JDO promises that there will only be one instance of an object
with a given primary key per PM. Other code may make decisions based on
this expectation ( like refreshing one of the objects after making a change
in a different PM ), that would lead to problems for code still hanging on
to the second instance.
IMHO, it should throw an exception.
-Eric
"Abe White" <[email protected]> wrote in message
news:[email protected]...
Thanks for the bug report! However, I'm not entirely sure that this is a
bug (at least not the bug you think it is); either way it's an extremely
interesting case. The reason I say it might not be a bug is thatassigning
pk values in jdoPreStore seems suspect.
We know that a single PM cannot at any time contain multiple instances
with the same oid value, app id or otherwise. This is obvious from the
getObjectById method -- only one object can have a particular oid.
We also know that jdoPreStore is called only for instances managed by a
PM (duh!).
Thus it should not be possible to see a case where jdoPreStore is
called for 2 objects with the same initial oid.
Now, I realize that when you're dealing with persistence-by-reachability
things become less clear. However, I think the general point stands: at
the time that the objects are made persistent they all must have unique
oid values, and objects must be made persistent before jdoPreStore is
called.
Technically we could get around this. The current
persistence-by-reachability algorithm is something like:
flushed = {}
while flushed.size < persistent.size:
for each persistent instance:
if instance not in flushed:
instance.jdoPreStore // may persist more instances
instance.persistFirstClassFields // may persist more too
flushed += instance
In sum this is a breadth-first method of persisting relations. It could
be changed to a depth-first system instead of persisting all first class
fields each one is persisted and then immediately the algorithm is
repeated for that object before the other fields are touched. However,
this seems like it might lead to other unexpected behavior.
Generally, it just seems like waiting till jdoPreStore to assign the oid
of an object seems like a bad idea. I think the real bug is that Kodo is
not throwing an exception as soon as 2 object with the same oid are
detected (currently it just lets one overwrite the other in the cache,
which results in the behavior you see).
Does anyone else have an opinion on this? I'm certainly not fixed on my
interpretation of things; if you disagree I'd be very interested in
hearing other arguments. -
SQL Batch doesn't seem to work; How to eager-fetch related objects?
Hi,
I have two technical questions with Kodo.
1. SQL Batch doesn't seem to work. I have tried batch size of -1, 0, 1, 25.
But the performance from batch creating objects is not affected by batch
size.
kodo.jdbc.DBDictionary: BatchLimit=25
2. How to use custom fetch groups to eagerly fetch related persistable
objects? Example only showed attributes, not relationships.
Enviroment:
* Kodo 3.1.0 RC1
* Oracle 9i release 1.
Qingshan Luo
Senior Software Engineer
Open Harbor
1123 Industrial Road
San Carlos, CA 94070
Phone: 650-413-4251
Fax: 650-413-4298try poracle 10g driver. At least they fixed terrible CLOB bug may be batch
to. BTW 9.2.x has problem with batching with deferred constraints so be
careful
"Greg Campbell" <[email protected]> wrote in message
news:c3dmnu$rmj$[email protected]..
>
"Qingshan Luo" <[email protected]> wrote in message
news:c3dg7q$mdl$[email protected]..
Hi,
I have two technical questions with Kodo.
1. SQL Batch doesn't seem to work. I have tried batch size of -1, 0, 1,25.
But the performance from batch creating objects is not affected by batch
size.
kodo.jdbc.DBDictionary: BatchLimit=25You may be running into a bug in the Oracle 9.2 driver. That driverdoesn't
reliably give update counts when using batching and prepared statement
caching. By default, Kodo will turn off batching. You can manuallyenable
batching by setting the BatchLimit on your DBDictionary, as you've done.If
you do this, though, you may want to turn off prepared statement cachingby
setting MaxCachedStatements to 0 (see
http://www.solarmetric.com/Software/Documentation/3.1.0RC1/docs/ref_guide_dbsetup.html#ref_guide_dbsetup_builtin).
>
2. How to use custom fetch groups to eagerly fetch related persistable
objects? Example only showed attributes, not relationships.You can find information on setting up eager fetching of relations at
http://www.solarmetric.com/Software/Documentation/3.0.3/docs/ref_guide_
perfpack_eager.html
Basically, you'll need to add the relations to your fetch group, and
set the eager fetching mode.
Enviroment:
* Kodo 3.1.0 RC1
* Oracle 9i release 1.
Qingshan Luo
Senior Software Engineer
Open Harbor
1123 Industrial Road
San Carlos, CA 94070
Phone: 650-413-4251
Fax: 650-413-4298 -
One to many relation doesn't work
I tried without success to get a simple one to many relationship to work.
The select works fine but
I still have problems with insert.
I have two tables on a existing schema:
1 ANAG (ID_ANAG primary key,...)
2 INDI (ID_INDI primary key, ID_ENTITA,...), where INDI.ID_ENTITA points
to ANAG.ID_ANAG
the two classes are:
1 public class Anagrafica
private int idAnag; //ID_ANAG
private String ragSoc;
private String ragSocFonet;
private String codFisc;
private String sesso;
private Integer codTit;
private Date dtNasc;
private HashSet indis;
2 public class Indirizzo
private int idIndi; //ID_INDI
private long idEntita; //ID_ENTITA
private long tpEntita;
private String indirizzo;
private String localita;
private String prov;
private String cap;
private Anagrafica anagrafica;
the two metadata:
1 anagrafica.jdo:
<?xml version="1.0"?>
<!-- This JDO Metadata file was auto-generated on 08/10/02 17.44.
See http://www.solarmetric.com for Kodo JDO Documentation and examples. -->
<jdo>
<package name="domain">
<class name="Anagrafica"
identity-type="application"
objectid-class="domain.AnagraficaPK">
<extension key="table" value="ANAG" vendor-name="kodo"/>
<extension key="class-column" value="none" vendor-name="kodo"/>
<extension key="lock-column" value="none" vendor-name="kodo"/>
<field name="idAnag" primary-key="true">
<extension key="data-column" value="ID_ANAG"
vendor-name="kodo"/>
</field>
<field name="ragSoc">
<extension key="data-column" value="RAG_SOC"
vendor-name="kodo"/>
</field>
<field name="ragSocFonet">
<extension key="data-column" value="RAG_SOC_FONET"
vendor-name="kodo"/>
</field>
<field name="codFisc">
<extension key="data-column" value="COD_FISC"
vendor-name="kodo"/>
</field>
<field name="sesso">
<extension key="data-column" value="SESSO"
vendor-name="kodo"/>
</field>
<field name="codTit">
<extension key="data-column" value="COD_TIT"
vendor-name="kodo"/>
</field>
<field name="dtNasc">
<extension key="data-column" value="DT_NASC"
vendor-name="kodo"/>
</field>
<field name="indis">
<collection element-type="domain.Indirizzo"/>
<extension vendor-name="kodo" key="table" value="INDI"/>
<extension vendor-name="kodo" key="inverse"
value="anagrafica"/>
<extension vendor-name="kodo" key="idEntita-ref-column"
value="ID_ANAG"/>
</field>
</class>
</package>
</jdo>
2 Indirizzo.jdo
<?xml version="1.0"?>
<!-- This JDO Metadata file was auto-generated on 08/10/02 17.21.
See http://www.solarmetric.com for Kodo JDO Documentation and examples. -->
<jdo>
<package name="domain">
<class name="Indirizzo"
identity-type="application" objectid-class="domain.IndiPK">
<extension key="table" value="INDI" vendor-name="kodo"/>
<extension key="class-column" value="none" vendor-name="kodo"/>
<extension key="lock-column" value="none" vendor-name="kodo"/>
<!--extension vendor-name="kodo" key="idEntita-data-column"
value="ID_ENTITA"/-->
<field name="idIndi" primary-key="true">
<extension key="data-column" value="ID_INDI"
vendor-name="kodo"/>
</field>
<field name="idEntita">
<extension key="data-column" value="ID_ENTITA"
vendor-name="kodo"/>
</field>
<field name="tpEntita">
<extension key="data-column" value="TP_ENTITA"
vendor-name="kodo"/>
</field>
<field name="indirizzo">
<extension key="data-column" value="INDIRIZZO"
vendor-name="kodo"/>
</field>
<field name="localita">
<extension key="data-column" value="LOCALITA"
vendor-name="kodo"/>
</field>
<field name="prov">
<extension key="data-column" value="PROV"
vendor-name="kodo"/>
</field>
<field name="cap">
<extension key="data-column" value="CAP"
vendor-name="kodo"/>
</field>
<field name="anagrafica">
<extension vendor-name="kodo" key="idAnag-data-column"
value="ID_ENTITA"/>
</field>
</class>
</package>
</jdo>
The problem is:
I create a new Anagrafica object and then I try to save it in the
database. These are the SQL
statements that are generated:
INSERT INTO ANAG(DT_NASC, COD_FISC, RAG_SOC_FONET, SESSO, ID_ANAG,
RAG_SOC, COD_TIT)
VALUES (NULL, NULL, 'NATALE', NULL, 971963921, 'Natale', NULL)
INSERT INTO INDI(TP_ENTITA, PROV, LOCALITA, ID_ENTITA, ID_INDI, INDIRIZZO,
CAP)
VALUES (0, NULL, NULL, 0, 971963921, 'via 25 dicembre', NULL)
Why is the value of ID_ANAG (971963921) assigned to ID_INDI and not to
ID_ENTITA?
Regards
MirkoAbe White wrote:
<field name="indis">
<collection element-type="domain.Indirizzo"/>
<extension vendor-name="kodo" key="table" value="INDI"/>
<extension vendor-name="kodo" key="inverse"
value="anagrafica"/>
<extension vendor-name="kodo" key="idEntita-ref-column"
value="ID_ANAG"/>
</field>
Get rid of all extensions except the inverse:
<field name="indis">
<collection element-type="domain.Indirizzo"/>
<extension vendor-name="kodo" key="inverse" value="anagrafica"/>
</field>
As in the examples in our documentation, all 1-many relations should only
list their inverse 1-1 relation.
Also, make sure your object model is consistent; i.e. make sure you'resetting
both sides of the relation:
indi.setAnagrafica (anag);
anag.getIndis ().add (indi);
Let us know if you continue to have problems.Hi Abe,
I got rid of the unnecessary extensions and I set both sides of the
relation as you suggest but I still have the same problem:
INSERT INTO ANAG(ID_ANAG) VALUES (2088176453)
INSERT INTO INDI(ID_INDI, ID_ENTITA) VALUES (2088176453, NULL)
while I expect
INSERT INTO ANAG(ID_ANAG) VALUES (2088176453)
INSERT INTO INDI(ID_INDI, ID_ENTITA) VALUES (<some ID>, 2088176453)
any ideas?
regards -
Cant't get one to many relation to work.
I tried to without success to retrieve an object that represents a simple
parent child relation in an existing database. (the object is supposed to
represent one record of the parent table and contain a Collection of all
records in the child table)
I have these two tables:
table "refrul" is the parent table (column "nr" is the primary key)
table "reftab" is the child (column "refundrule" points to refrul.nr)
This is my .jdo file
<?xml version="1.0"?>
<jdo>
<package name="jdbctest">
<class name="RefundRule" objectid-class="RefundRuleId">
<extension vendor-name="kodo" key="table" value="refrul"/>
<extension vendor-name="kodo" key="lock-column" value="none"/>
<extension vendor-name="kodo" key="class-column" value="none"/>
<field name="ruleNr" primary-key="true">
<extension vendor-name="kodo" key="data-column" value="nr"/>
</field>
<field name="ruleName">
<extension vendor-name="kodo" key="data-column"
value="name"/>
</field>
<field name="minSalesAmount">
<extension vendor-name="kodo" key="data-column"
value="minsalesamount"/>
</field>
<field name="refundTable">
<collection element-type="RefundTableRow"/>
<extension vendor-name="kodo" key="table" value="reftab"/>
<extension vendor-name="kodo" key="ruleNr-ref-column"
value="refundrule"/>
</field>
</class>
<class name="RefundTableRow" objectid-class="RefundTableRowId">
<extension vendor-name="kodo" key="table" value="reftab"/>
<extension vendor-name="kodo" key="lock-column" value="none"/>
<extension vendor-name="kodo" key="class-column" value="none"/>
<field name="ruleNr" primary-key="true">
<extension vendor-name="kodo" key="data-column"
value="refundrule"/>
</field>
<field name="vatRate" primary-key="true">
<extension vendor-name="kodo" key="data-column"
value="ustsatz"/>
</field>
<field name="fromSalesAmount" primary-key="true">
<extension vendor-name="kodo" key="data-column"
value="ab_betrag"/>
</field>
<field name="refundPercent">
<extension vendor-name="kodo" key="data-column"
value="refund_prozent"/>
</field>
<field name="refundAmount">
<extension vendor-name="kodo" key="data-column"
value="refund_betrag"/>
</field>
</class>
</package>
</jdo>
I get an exception showing this query:
[SQL=SELECT t0.ab_betrag, t0.refundrule, t0.ustsatz, t0.refund_betrag,
t0.refund_prozent, t0.RULENAMEX
FROM reftab t0 WHERE(t0.refundrule = 0 AND t0.ab_betrag =
t0.FROMSALESAMOUNT_REFUNDTABLEX AND t0.refundrule = t0.RULENR_REFUNDTABLEX
AND t0.ustsatz = t0.VATRATE_REFUNDTABLEX)]
All columns in uppercase do not exist in my tables, so this must generate an
exception.
Also the join seems strange I would have expected only " ...
WHERE(t0.refundrule = parenttableRuleNr)".
Whats wrong?
I am using kodo 2.3
Regards,
BernhardAbe,
the strange column names are gone now, but it still does not work
This is my new .jdo file (Iadded the "inverse" line)
<?xml version="1.0"?>
<jdo>
<package name="jdbctest">
<class name="RefundRule" objectid-class="RefundRuleId">
<extension vendor-name="kodo" key="table" value="refrul"/>
<extension vendor-name="kodo" key="lock-column" value="none"/>
<extension vendor-name="kodo" key="class-column" value="none"/>
<field name="ruleNr" primary-key="true">
<extension vendor-name="kodo" key="data-column" value="nr"/>
</field>
<field name="ruleName">
<extension vendor-name="kodo" key="data-column"
value="name"/>
</field>
<field name="minSalesAmount">
<extension vendor-name="kodo" key="data-column"
value="minsalesamount"/>
</field>
<field name="refundStep">
<extension vendor-name="kodo" key="data-column"
value="refundstep"/>
</field>
<field name="refundTable">
<collection element-type="RefundTableRow"/>
<extension vendor-name="kodo" key="table" value="reftab"/>
<extension vendor-name="kodo" key="ruleNr-ref-column"
value="refundrule"/>
<extension vendor-name="kodo" key="inverse" value="ruleNr"/>
</field>
</class>
<class name="RefundTableRow" objectid-class="RefundTableRowId">
<extension vendor-name="kodo" key="table" value="reftab"/>
<extension vendor-name="kodo" key="lock-column" value="none"/>
<extension vendor-name="kodo" key="class-column" value="none"/>
<field name="ruleNr" primary-key="true">
<extension vendor-name="kodo" key="data-column"
value="refundrule"/>
</field>
<field name="vatRate" primary-key="true">
<extension vendor-name="kodo" key="data-column"
value="ustsatz"/>
</field>
<field name="fromSalesAmount" primary-key="true">
<extension vendor-name="kodo" key="data-column"
value="ab_betrag"/>
</field>
<field name="refundPercent">
<extension vendor-name="kodo" key="data-column"
value="refund_prozent"/>
</field>
<field name="refundAmount">
<extension vendor-name="kodo" key="data-column"
value="refund_betrag"/>
</field>
</class>
</package>
</jdo>
This the generated SQL:
[SQL=SELECT t0.nr, t0.minsalesamount, t0.refundstep, t0.name FROM refrul t0,
reftab t1 WHERE (t0.nr = t1.nr)]
This throws an exception because t1.nr (reftab.nr) does not exist, it should
be reftab.refundrule. This would be correct:
SELECT t0.nr, t0.minsalesamount, t0.refundstep, t0.name FROM refrul t0,
reftab t1 WHERE (t0.nr = t1.refundrule)]
Regards,
Bernhard
Maybe you are looking for
-
Hi when we are trying to update Communication data of an external candidate.. We are getting this error message... Internal error in IGS0, US. COMMUNICATION FAILURE (RFC: GIS_GEOCODE_DEST:Geocode) Please let me know how to fix this error... Thanks Ra
-
JCA Adapter Less than Symbol in OSB 11.1.1.5
Hey everyone, When trying to create a Business Service based off of a JCA Adapter created in JDeveloper for a custom query database call, I am having issues if the query has the less than symbol in it. When generating the service, it gives me the fol
-
Hello, I would like to link to a pdf - but instead of opening up full screen and a new browser - is there way to open it up so it stay embedded with in the portlet? I want to constrain the size to the layout - so for a 3 column layout, with the pdf i
-
MWA/MSCA Customization ERROR
Dear all, My requirement is to Customize a Page where i have FListener & Page file but not able to find Function File I have checked the the menu>function>it adress to a different Function File... where on condition it is pointing to different Page .
-
Hello! I had my macbook air for about a month when it was splashed with water and completely died the cost of repair was 1300 more then the actual laptop. With this being said dose anyone know of a good WATERPROOF hard shell case of soft sleeve. I ha