Hi,
thanks for your infos on that. I will stick with setting the backrefs
manually as you did it and keep chosing the @ManyToOne on the child.
What strikes me even more is that you can just do that:
public class Team {
...
@OneToMany(cascade = CascadeType.PERSIST, mappedBy = "team")
public List<Player> players;
}
public class Player {
....
@ManyToOne
public Team team;
}
So no ElementJoinColumn or JoinColumn as i would need to if using
unidirectional links from parent to child. Makes kind of sense because
now mapping the parent in the child class, i dont need to tell him
where the FK thingy is. Now its just a direct mapping and the defaults
are ok to map to the FK field "team_oid" in the Player Table.
To me the documentation is lacking heavily in exactly this spot.
Because it turns out that the bidirectional mapping of a child-FK-
Mapping is completely different as the unidirectional one because then
we would need all that ElementJoinColumn magic. Took me one day to
figure this out and you helped me in getting the facts straight that
the ORM layer is not that smart as i believed. For me, OpenJPA could
easily figure the backrefs for itself, at least it looks as it could
do so.
Would be interessting to know if this keeps being this way in Version
2. But on the other hand, it wont kill you to set the backref, you
just have to know it in the first place. And now i finally created
test classes for all that mapping stuff so that i can fiddle around
with various mappings in a short timeframe w/o boostrapping my J2EE app.
Again, thanks a lot for your help.
---
regards
Marc Logemann
http://www.logemann.org
http://www.logentis.de
Am 13.11.2009 um 19:09 schrieb Michael Dick:
Hi Marc,
The example I sent was something I hacked together to populate a
database
using your model. Basically it creates 3 Fathers with 2 children for
each of
them. Hopefully that didn't distract you too much.
The real issue is setting the backrefs. In JPA the application must
maintain
both sides of a bi-directional relationship (on your Java objects).
There's
some wording in the spec to this effect which I can drag up if you're
interested.
The other thing that might be worth noting is that when you add
mappedBy="something" JPA will consider the Many side (in your case
Child, or
Player) the _owner_ of the relationship. Using the @Embedded
annotations may
reverse the owners - but you need to remove the mappedBy attribute of
@OneToMany. It's the owner of the relationship which matters "most".
So for general JPA use I definitely recommend setting both sides of
the
relationship to make sure they get persisted properly.
That said, OpenJPA does provide a mechanism to manage the inverse
side of
relationships for you. You can read about it in the users guide here :
http://openjpa.apache.org/builds/1.2.1/apache-openjpa-1.2.1/docs/manual/manual.html#ref_guide_inverses
.
It sounds like it's exactly what you're looking for.
Hope this helps. If you have other questions keep posting.
-mike
On Fri, Nov 13, 2009 at 11:39 AM, Marc Logemann <[email protected]>
wrote:
Hi,
for the records, i am using 1.2.0.
To your question: i am only doing that (sorry, i changed my example
to be
Team->Player, instead of Father->Child) :
Player p = new Player();
p.setName("Huiboo");
List<Player> list = new ArrayList<Player>();
list.add(p);
Team t = new Team();
t.setName("VfL");
t.setPlayers(list);
em.persist(t);
So yes, i am only setting the child references in the list and i dont
manually set the backreference. To be honest, i dont understand your
example too well. I wouldnt expect that i need to do the
backreferences
manually.
At this point i know something that works without setting backrefs
manually, but this looks also quite weird to me because i must use
OneToOne
on the child. If i do the mapping on the Team (Father) like this:
@OneToMany(cascade = CascadeType.PERSIST)
@ElementJoinColumn(name = "team_oid", referencedColumnName = "oid")
public List<Player> players;
and then do the mappedBy in the child (player)
@OneToOne(mappedBy = "players")
public Team team;
Then i have my bidirectional link and i also have the FK column
filled like
if i wouldnt use the mappedBy.
Would you recommend doing it like you have done it? As i said, i
would
expect the ORM layer to work out the back reference because i already
defined the relationship via setting childs to a list, why telling
the
childs again to which object they belong?
Thanks for being with me on that one. Appreciate that.
---
regards
Marc Logemann
http://www.logemann.org
http://www.logentis.de
Am 13.11.2009 um 18:27 schrieb Michael Dick:
Hi Marc,
Are you setting the relationship for both the Father and Child
entities?
I see the behavior you describe if I do this :
Father f;
Child c;
for (int i = 0; i < nFathers; i++) {
f = new Father();
f.setChildren(new ArrayList<Child>());
em.persist(f);
for(int j = 0 ; j < nChildren; j++ ) {
c = new Child();
// c.setFather(f);
f.getChildren().add(c);
em.persist(c);
}
Uncommenting c.setFather(f); fixes the problem. If that doesn't
help let
me
know which version of OpenJPA and which database you're using and
I'll try
to recreate.
-mike
On Fri, Nov 13, 2009 at 10:33 AM, Marc Logemann <[email protected]>
wrote:
Hi,
what you have done works of course but thats not my problem
because thats
what i had before i wanted to do the inverse. Your example simply
demonstrates how to use ElementJoinColumn and i am pretty aware
of that
;-)
The problem starts when using mappedBy on the children inside
Father.
When i am doing it as you described it in your email before, i am
at
least
not getting any errors back but instead he inserts a "null" in my
FK
field.
@ManyToOne
@ForeignKey
@JoinColumn(name="team_oid", referencedColumnName="oid")
public Team team;
I am really clueless. It simply cant be so hard and uncommon to
make an
inverse OneToMany with a FK field in the child table.
I googled for hours and all example i ve found just dont work.
---
regards
Marc Logemann
http://www.logemann.org
http://www.logentis.de
Am 13.11.2009 um 17:17 schrieb Michael Dick:
Hi Marc,
Did some more reading and I was wrong about the use case for the
@Element
annotations. The @Element annotations allow you to specify the FK
constraint
on the One side of a @OneToMany, so your annotations would look
like
this
:
@Entity
public class Father extends Person {
@OneToMany
@ElementForeignKey
@ElementJoinColumn(name="father_oid", referencedColumnName="oid")
Collection<Child> children;
. . .
}
@Entity
public class Child extends Person {
@ManyToOne
private Father father;
. . .
}
It appears to be functionally identical to using @JoinColumn and
@ForeignKey
on the Child class, but the documentation is a bit sparse on this
annotation..
There are several examples in our unit tests though. For example
openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/
persistence/jdbc/mapping/bidi/ParentWithAutoIdentity.java
looks somewhat similar to your model.
Hope this helps,
-mike
---------- Forwarded message ----------
From: Michael Dick <[email protected]>
Date: Fri, Nov 13, 2009 at 9:52 AM
Subject: Re: inverse OneToMany relation - getting weird
To: [email protected]
Hi Marc,
I think the @ElementForeignKey and @ElementJoinColumn
annotations are
intended to be used with non-entity types (ie
PersistentCollections).
If Child is an entity you'd want to use @ForeignKey and
@JoinColumn
instead
(I gave this a quick try and it looks like it worked for me).
Regards,
-mike
On Fri, Nov 13, 2009 at 7:03 AM, Marc Logemann <[email protected]>
wrote:
Hi,
after struggling for several hours, i need to ask for help.
Following scenario.....
DB Table: Father
---------------------------
INT oid
....
DB Table: Childs
------------------------
INT oid
INT father_oid
...
Java Entity: Father
--------------------------
...
@OneToMany(cascade = CascadeType.PERSIST, mappedBy = "father")
private List<Child> childList;
Java Entity: Child
--------------------------
...
@ManyToOne(cascade = CascadeType.PERSIST)
@ElementForeignKey
@ElementJoinColumn(name="father_oid", referencedColumnName="oid")
protected Father father;
When i try to persist a Father, i am getting:
<openjpa-1.2.0-r422266:683325 fatal user error>
org.apache.openjpa.persistence.ArgumentException: Field
"Father.childList"
declares "Child.father" as its mapped-by field, but this field
is not a
direct relation. at......
Ok, then i changed Child to:
Java Entity: Child
--------------------------
...
@ManyToOne(cascade = CascadeType.PERSIST)
@Column(name = "father_oid")
protected Father father;
When i now do persist a Father object, both DB records (Father
and
Childs)
are filled with records but the FK column in Child (father_oid)
is
empty.
So
the FK relation is broken but it did persist childs, which is
somehow
weird.
So whatever i do, i never get a fully persisted graph with
correct FK
values.
Can anyone give me a hint what i am doing wrong here?
Thanks a lot.
---
regards
Marc Logemann
http://www.logemann.org
http://www.logentis.de