persistence@glassfish.java.net

RE: [Issue 914] Bidirectional ManyToMany broken

From: Gordon Yorke <gordon.yorke_at_oracle.com>
Date: Thu, 10 Aug 2006 13:09:29 -0400

No problem,
   Removing "mappedBy" created 2 Uni-directional ManyToMany mappings. If you are using DDL-generation you will see 2 join tables. If you are using a single join table and you add a doctor to a patient and the patient to the doctor you will see 2 entries in the join table, which may not be portable and may cause duplicates on queries.
   If the doctor patient relationship is really a OneToMany bi-directional you may be able to map the relation table as a secondary table (join table would need to allow nulls) on Patient and map as a OneToMany from Doctor to Patient and a ManyToOne from Patient to Doctor. Cascade Delete would then work for you.
--Gordon

-----Original Message-----
From: Matt Powell [mailto:matt_tricks_at_hotmail.com]
Sent: Thursday, August 10, 2006 11:48 AM
To: Gordon Yorke
Subject: Re: [Issue 914] Bidirectional ManyToMany broken


Hi Gordon,

Wow, thanks for the fast reply :-)

My bad, I forgot that I filed it as two separate bug reports, hence my
confusion at your response! Heh. It's been a long day and it's almost
midnight.

The confusing thing is that removing the "mappedBy" annotation caused it to
work properly without having to maintain the inverse side of the operation.
So if I add a doctor to a patient but not the inverse, the JoinTable is
being updated and everything seems to work fine. Obviously it would nice to
write portable code so I'll probably fix it but does that sound right to
you? See my original text for the @ManyToMany definitions and code. Try it!
It works!

I noticed your comments in the sample code about using find() instead of
merge() as well, I've been wondering that because sample code I've seen
around the place seems to mostly use merge() but find() felt more logical.
So thanks for that!

Matt

----- Original Message -----
From: "Gordon Yorke" <gordon.yorke_at_oracle.com>
To: "Matt Powell" <matt_tricks_at_hotmail.com>; <gyorke_at_dev.java.net>
Cc: <persistence_at_glassfish.dev.java.net>
Sent: Thursday, August 10, 2006 11:33 PM
Subject: RE: [Issue 914] Bidirectional ManyToMany broken


> Hello Matt,
> There appears to be an issue with cascade delete and ManyToManys. We
> are not determining the delete order correctly and thanks for filing issue
> 915. The user should not be required to maintain the relational table at
> all. If you were to remove the Patients from the Doctor's ( and visa
> versa )before calling remove on the Patient (or Doctor) then the JoinTable
> would be updated automatically for you.
>
> With the issue you filed for 914 however, the JoinTable is not being
> updated because both sides of the ManyToMany bi-directional are not being
> set, as required by the Specification.
> --Gordon
>
> -----Original Message-----
> From: Matt Powell [mailto:matt_tricks_at_hotmail.com]
> Sent: Thursday, August 10, 2006 11:16 AM
> To: gyorke_at_dev.java.net
> Subject: Re: [Issue 914] Bidirectional ManyToMany broken
>
>
> Hi,
>
> What about for removal? Is the best way to perform an QL delete on the
> JoinTable? Will that cause any referential problems in the persistence
> context?
>
> Why is the cascade option allowed at all on a ManyToMany definition if it
> will never do anything?
>
> Thanks for your time.
>
> Matt
>
> ----- Original Message -----
> From: <gyorke_at_dev.java.net>
> To: <matt_tricks_at_dev.java.net>
> Sent: Thursday, August 10, 2006 9:38 PM
> Subject: [Issue 914] Bidirectional ManyToMany broken
>
>
>> https://glassfish.dev.java.net/issues/show_bug.cgi?id=914
>>
>>
>>
>> User gyorke changed the following:
>>
>> What |Old value |New value
>> ================================================================================
>> Status|NEW |RESOLVED
>> --------------------------------------------------------------------------------
>> Resolution| |INVALID
>> --------------------------------------------------------------------------------
>>
>>
>>
>>
>> ------- Additional comments from gyorke_at_dev.java.net Thu Aug 10 13:38:06
>> +0000 2006 -------
>> The specification requires that users maintain their own relationship
>> integrity.
>> The addDoctor() method should be as folows:
>> public void addDoctor(Patient patient, Doctor doctor) {
>> // a find() should be performed instead of the merge.
>> // the merge will overwrite the contents of the PC version with
>> the
>> // provided user version
>> // merge should only be used if the desire is to take advantage of
>> // optimistic locking and the patient and doctor are serialized
>> // from client.
>> Patient p = em.merge(patient); // get the em context version of
>> patient
>> Doctor d = em.merge(doctor); // get the em context version of
>> doctor
>> p.getDoctors().add(d);
>> d.getPatients().add(p); // it is important to set both
>> relationships as
>> per spec
>> }
>>
>>
>>