|
The power of a Java persistence solution like DataNucleus is demonstrated when persisting relationships between objects.
There are many types of relationships.
-
1-1 relationships - this is where you have an object A relates to a second
object B.
The relation can be
unidirectional
where A knows about B, but B doesnt know about A.
The relation can be
bidirectional
where A knows about B and B knows about A.
-
1-N relationships - this is where you have an object A that
has a collection of other objects of type B.
The relation can be
unidirectional
where A knows about the objects B but the Bs dont know about A.
The relation can be
bidirectional
where A knows about the objects B and the Bs know about A
-
N-1 relationships - this is where you have an object B1 that relates
to an object A, and an object B2 that relates to A also etc.
The relation can be
unidirectional
where the A doesnt know about the Bs.
The relation can be
bidirectional
where the A has a collection of the Bs.
[i.e a 1-N relationship but from the point of view of the element]
-
M-N relationships - this is where you have objects of type A that
have a collection of objects of type B and the objects of type B also have a collection of objects of type A.
The relation is always
bidirectional
by definition
When the relation is
unidirectional
you simply set the related field to refer to the other object.
For example we have classes A and B and the class A has a field of type B. So we set it like this
A a = new A();
B b = new B();
a.setB(b); // "a" knows about "b"
When the relation is
bidirectional
you
have to set both sides
of the relation.
For example, we have classes A and B and the class A has a collection of elements of type B, and B has a
field of type A. So we set it like this
A a = new A();
B b1 = new B();
a.addElement(b1); // "a" knows about "b1"
b1.setA(a); // "b1" knows about "a"
So it is really simple, with only 1 real rule.
With a
bidirectional
relation you must set both sides of the relation
To persist an object with JPA you call the
EntityManager
method
persist
.
The object passed in will be persisted. By default all related objects will
not
be persisted with that
object. You can however change this by specifying the cascade PERSIST property for that field. With this the related
object(s) would also be persisted (or updated with any new values if they are already persistent).
This process is called
persistence-by-reachability
. With JDO the default is to persist all reachables, whereas
with JPA you have to explicitly set this behaviour.
For example we have classes A and B and class A has a field of type B and this field has the cascade property PERSIST set.
To persist them we could do
A a = new A();
B b = new B();
a.setB(b); // "a" knows about "b"
em.persist(a);
As we have mentioned above, it is for the user to set both sides of a bidirectional relation.
If they dont and object A knows about B, but B doesnt know about A then what is the persistence solution
to do ? It doesnt know which side of the relation is correct.
JPA doesnt define the behaviour currently for this situation.
DataNucleus has two ways of handling this situation. If you have the persistence property
"datanucleus.manageRelationships" set to true then it will make sure that the other side of
the relation is set correctly, correcting obvious omissions, and giving exceptions for
obvious errors. If you set that persistence property to false then it will assume that your
objects have their bidirectional relationships consistent and will just persist what it finds.
|
|