From: kamiseq on
hi,
I have very strange behaviour with my JPA entities.

I have to entities GenObject and GenObjectCnf that are linked with one-
to-many type, where in GenObject
@OrderBy
@OneToMany(cascade = CascadeType.ALL, mappedBy = "objects", fetch =
FetchType.LAZY)
private List<GenObjectCfg> objectsCfgSet = new ArrayList<GenObjectCfg>
();

now I create GenObject and persist it. then I instantiate new
GenObjectCnf object assign GenObject with it and persist. so in the db
everything is fine data is saved and I can move on. transaction is
over and my objects are detached from session.

the problem is now that my GenObject doesn't know about GenObjectCnf
as it was created before it and I didn't assigned GenObjectCnf back
after I created it. so I thought I can simply merge GenObject object
to update its state and data I need. so in other transaction Im
calling

this.em.merge(object);
GenObjectCfg parentCfg = object.getObjectsCfgSet().get(0);

as it should fetch all GenObjectCnf related to this GenObject object.
but is not and list remain empty.

BUT when I call
GenObject go = this.em.find(GenObject.class, object.getIdObject());
GenObjectCfg parentCfg = go.getObjectsCfgSet().get(0);

data is fetched and I get what I want, so essentially what am I
missing??
why is it so??

Im really out of ideas and it is something about how JPA works and I
didnt learn that yet, doesnt it?!
From: Lew on
On Dec 29, 4:33 pm, kamiseq <kami...(a)gmail.com> wrote:
> hi,
> I have very strange behaviour with my JPA entities.
>
> I have to entities GenObject and GenObjectCnf that are linked with one-
> to-many type, where in GenObject
> @OrderBy
> @OneToMany(cascade = CascadeType.ALL, mappedBy = "objects", fetch =
> FetchType.LAZY)
> private List<GenObjectCfg> objectsCfgSet = new ArrayList<GenObjectCfg>
> ();
>
> now I create GenObject and persist it. then I instantiate new
> GenObjectCnf object assign GenObject with it and persist. so in the db
> everything is fine data is saved and I can move on. transaction is
> over and my objects are detached from session.
>
> the problem is now that my GenObject doesn't know about GenObjectCnf
> as it was created before it and I didn't assigned GenObjectCnf back
> after I created it. so I thought I can simply merge GenObject object
> to update its state and data I need. so in other transaction Im
> calling
>
> this.em.merge(object);
> GenObjectCfg parentCfg = object.getObjectsCfgSet().get(0);
>
> as it should fetch all GenObjectCnf related to this GenObject object.
> but is not and list remain empty.
>
> BUT when I call
> GenObject go = this.em.find(GenObject.class, object.getIdObject());
> GenObjectCfg parentCfg = go.getObjectsCfgSet().get(0);
>
> data is fetched and I get what I want, so essentially what am I
> missing??
> why is it so??
>
> Im really out of ideas and it is something about how JPA works and I
> didnt learn that yet, doesnt it?!

I don't know your answer yet, but two things puzzle me so far, plus
can you provide an SSCCE <http://sscce.org/>?

Puzzle 1: Why are you explicitly allocating an ArrayList to
'objectsCfgSet'?
Puzzle 2: What is 'objects' in the 'GenObjectCfg' type? (This is one
place where an SSCCE would help.) That the name is plural but it's
mapping what presumably is a many-to-one from 'GenObjectCfg' is
suspicious.

An SSCCE might be a little tricky here; if so I understand. But at
the least give us complete (enough) source for 'GenObject' and
'GenObjectCfg', and the DDL for the associated tables.

Also, you didn't need to post your question twice. Someone eventually
will get around to answering, or they won't.

--
Lew

From: Tom Anderson on
On Tue, 29 Dec 2009, kamiseq wrote:

> I have to entities GenObject and GenObjectCnf that are linked with one-
> to-many type, where in GenObject
> @OrderBy
> @OneToMany(cascade = CascadeType.ALL, mappedBy = "objects", fetch =
> FetchType.LAZY)
> private List<GenObjectCfg> objectsCfgSet = new ArrayList<GenObjectCfg>
> ();
>
> now I create GenObject and persist it. then I instantiate new
> GenObjectCnf object assign GenObject with it and persist.
^^^^^^^^^^^^^^^^^^^^^^^^

What does this mean? It's not correct English, i'm afraid. Posting the
code that does this would be very helpful.

I assume that you mean that you assign the owning GenObject to the
GenObjectCnf's object field, like this:

GenObject someObject;
GenObjectCnf someCnf = new GenObjectCnf();
someCnf.object = someObject;

If my understanding is wrong, the rest of my advice will probably be
wrong.

> the problem is now that my GenObject doesn't know about GenObjectCnf as
> it was created before it and I didn't assigned GenObjectCnf back after I
> created it. so I thought I can simply merge GenObject object to update
> its state and data I need.

The solution is much simpler than this - you store the GenObjectCnf into
the GenObject's objectsCfgSet list:

someObject.objectsCfgSet.add(someCnf);

This is a very important point, which you may not have appreciated - JPA
does *not* manage bidirectional relationships at the object level, only at
the database level. So, if you create a bidirectional relationship, you
have to create both ends. See:

http://blog.xebia.com/2009/03/16/jpa-implementation-patterns-bidirectional-assocations/

It's possible i've misunderstood your problem completely - apologies if
so.

tom

--
FRUIT FUCKER has joined the party!
From: Tom Anderson on
On Tue, 29 Dec 2009, Lew wrote:

> On Dec 29, 4:33�pm, kamiseq <kami...(a)gmail.com> wrote:
>
>> @OrderBy
>> @OneToMany(cascade = CascadeType.ALL, mappedBy = "objects", fetch =
>> FetchType.LAZY)
>> private List<GenObjectCfg> objectsCfgSet = new ArrayList<GenObjectCfg>
>> ();
>
> Puzzle 1: Why are you explicitly allocating an ArrayList to
> 'objectsCfgSet'?

Because otherwise, it would be null, and so any attempt to use the object
before it was persisted would fail. No?

tom

--
FRUIT FUCKER has joined the party!
From: Arved Sandstrom on
kamiseq wrote:
> hi,
> I have very strange behaviour with my JPA entities.
>
> I have to entities GenObject and GenObjectCnf that are linked with one-
> to-many type, where in GenObject
> @OrderBy
> @OneToMany(cascade = CascadeType.ALL, mappedBy = "objects", fetch =
> FetchType.LAZY)
> private List<GenObjectCfg> objectsCfgSet = new ArrayList<GenObjectCfg>
> ();
>
> now I create GenObject and persist it. then I instantiate new
> GenObjectCnf object assign GenObject with it and persist. so in the db
> everything is fine data is saved and I can move on. transaction is
> over and my objects are detached from session.
>
> the problem is now that my GenObject doesn't know about GenObjectCnf
> as it was created before it and I didn't assigned GenObjectCnf back
> after I created it. so I thought I can simply merge GenObject object
> to update its state and data I need. so in other transaction Im
> calling
>
> this.em.merge(object);
> GenObjectCfg parentCfg = object.getObjectsCfgSet().get(0);
>
> as it should fetch all GenObjectCnf related to this GenObject object.
> but is not and list remain empty.
>
> BUT when I call
> GenObject go = this.em.find(GenObject.class, object.getIdObject());
> GenObjectCfg parentCfg = go.getObjectsCfgSet().get(0);
>
> data is fetched and I get what I want, so essentially what am I
> missing??
> why is it so??
>
> Im really out of ideas and it is something about how JPA works and I
> didnt learn that yet, doesnt it?!

A couple of notes:

1) The mappedBy name "objects" is jarring. If I understand you
correctly, you're saying that for one GenObject we have many GenObjCnf
objects. In the database the GenObjCnf table will have a foreign key for
GenObject, and GenObjCnf is considered to be the owning side; GenObject
is the inverse side, and has the mappedBy attribute, which you have
correctly. "objects" is the field in each GenObjCnf that refers to the
single GenObject, so would be something like

GenObject genObject;

and you'd more likely declare it as

mappedBy="genObject"

2) the declaration of the list List<GenObjCnf> objectsCfgSet is sort of
OK (better not to call it a list or a set, just call the variable
"cfgObjects" or suchlike).

3) EntityManager.merge() doesn't update state - calling refresh() or
explicitly changing state on the POJO instance does.

4) do you know for a fact that after persisting that the DB is updated?
Are you looking at console SQL or keeping an eye o the tables? What are
your transactions like? Are you using application-managed or
container-managed entity managers?

5) with CascadeType.ALL you could have just created the GenObject,
created a GenObjCnf, added the GenObjCnf to the list, then persisted
only the GenObject. That's what cascades are for.

6) Lazy initialization is not pinned down by the JPA spec, leastways not
JPA 1.0. Use at your own risk; persistence implementations have a lot of
leeway. If you are newish to JPA, consider setting the OneToMany to
EAGER (note that the default _is_ LAZY for that type of relationship, so
you didn't need to put that in) and get stuff working.

7) As pointed out by others, it's your responsibility to a great extent
to maintain relationships in code; JPA implementations take care of the
database. For example, if you were to call em.remove on one of the
GenObjCnf objects, would you expect Hibernate to take it out of the
collection?

8) As others have asked for, provide a short SSCCE. I believe we can
help you figure this out.

AHS