users@glassfish.java.net

Re: TopLink Essentials bug with Set<Something> fields?

From: Witold Szczerba <pljosh.mail_at_gmail.com>
Date: Fri, 16 Feb 2007 00:43:39 +0100

Hi Markus,
thanks for help, I will try that tomorrow morning :)
Is that actually a workaround or this is how one should alter
collection based properties in JPA? Are you positive that merging
operation should not be performed by TopLink itself?

Thanks again,
Witek,
p.s.
This is uni-directional relationship, Phone class does not know
anything about Person, Phone instances are supposed to be used in
other entities as well.


2007/2/16, Markus Fuchs <Markus.Fuchs_at_sun.com>:
> Hi Witold,
>
> Looks like the problem is that the instances in the new Set<Phone> are
> detached. Try changing setPhones to
>
> @Stateless
> public class PersonService implements PersonServiceRemote {
> ...
> public void setPhones(Long personId, Set<Phone> phones) {
> Person p = em.getReference(Person.class, personId);
> Set <Phone> mergedPhones = new Set<Phone>();
>
> for (Phone phone : phones) {
> Phone mergedPhone = em.merge(phone);
> mergedPhones.add(mergedPhone);
> }
> p.setPhones(mergedPhones);
> }
> ...
> }
>
> Also note, that JPA relationships should always be maintained on both
> sides. So if above relationship is bi-directional, you'd need to compare
> the original and new Set<Phone> and do the appropriate updates
> (add/remove) on the Phone side manually.
>
> -- markus.
>
> Witold Szczerba wrote:
> > Hello there,
> > I have big problems with TopLink Essentials and it looks like there is
> > some bug.
> > Here is the case:
> >
> > @Entity
> > public class Person extends EntityBase<Long,Long> {
> > .....
> > public static final String PHONES = "phones";
> > @ManyToMany
> > private Set<Phone> phones;
> > ....
> > public Set<Phone> getPhones() {
> > return phones;
> > }
> >
> > public void setPhones(Set<Phone> phones) {
> > Set<Phone> old = this.phones;
> > this.phones=phones;
> > firePropertyChange(PHONES,old,phones);
> > }
> > ....
> > }
> > where EntityBase<K,V> is a non @Entity base class.
> >
> > I have Swing application using @Remote interfaces to access database:
> >
> > @Stateless
> > public class PersonService implements PersonServiceRemote {
> > ....
> > public List<Phone> getPhones(Long personId) {
> > Query query = em.createQuery(
> > "SELECT p.phones FROM Person p WHERE p.id=?1");
> > query.setParameter(1,personId);
> > return query.getResultList();
> > }
> > ....
> > public void setPhones(Long personId, Set<Phone> phones) {
> > Person p = em.getReference(Person.class, personId);
> > p.setPhones(phones);
> > }
> > ...
> > }
> >
> > Here is what happens:
> > in Swing application I call:
> > Set<Phone> phones = personService.getPhones(1); //1 is Person PK
> > phones collection contains one phone entity, then I call:
> > personService.setPhones(phones);
> >
> > then TopLink is trying ONCE AGAIN to insert that phone ID and person
> > ID into PERSON_PHONE table which causes exception as that row already
> > exists in PERSON_PHONE table. When I call:
> > personService.setPhones(new HashSet<Phone>());
> > then TopLink is doing everything OK, I mean it is removing existing
> > row from database.
> >
> > I really do not know what to do, as there is no way to force TopLink
> > to add any new phone into that set. Every time when my Set contains
> > something that already is in PERSON_PHONE table I get exception,
> > because it is trying to add existing phones again.
> >
> > I was trying that in Glassfish v1 with TopLink from that release and I
> > have also replaced libraries with TopLink Essentials Version 2 Build
> > 25 (but still on Glassfish V1).
> > Is that a bug?
> >
> > p.s.
> > I suppose the problem might have been not discovered as, in my case,
> > TopLink's Set implementation is serialized and deserialized back and
> > fourth between server and Swing application. Maybe no one made a test
> > case for that?
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscribe_at_glassfish.dev.java.net
> > For additional commands, e-mail: users-help_at_glassfish.dev.java.net
> >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_glassfish.dev.java.net
> For additional commands, e-mail: users-help_at_glassfish.dev.java.net
>
>