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 12:24:32 +0100

Thanks very much, it works now :)

2007/2/16, Markus Fuchs <Markus.Fuchs_at_sun.com>:
> Hi Witek,
>
> Witold Szczerba wrote:
> > 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?
> This is not a workaround. JPA instances become detached when send across
> the wire. But another possible solution for your problem would be to
> modify the person instance (the phones fields) directly on the remote
> side. Then in the SessionBean, call em.merge(p) and specify that the
> merge operation should be cascaded in the POJO, i.e.
>
> public class Person extends EntityBase<Long,Long> {
> .....
> @ManyToMany(cascade=CascadeType.MERGE)
> private Set<Phone> phones;
> ....
> > Are you positive that merging
> > operation should not be performed by TopLink itself?
> >
> The merge operation must be called by the application (here:
> SessionBean). For more information about the merge operation, see JPA
> Spec, 3.2.4.1 Merging Detached Entity State.
>
> Regards,
>
> -- markus.
> > 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
> >>
> >>
> >
> > ---------------------------------------------------------------------
> > 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
>
>