Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [eclipselink-users] two instances of same object in an indirectList ?

If you are using field access, then that is not the issue.

Try calling refresh() on the object, after refreshing, does it still have
duplicates?  Also turn on logging and try executing the same SQL it is using
the query the relationship, are there two rows returned?



Phillip Ross-3 wrote:
> 
> I'm using field access (annotations on the field declarations, not on the
> methods), but I do have extra logic in the setter methods for handling the
> maintenance of the collections on the other side of the relationship as I
> illustrated in my last mail.  The link you pasted wouldnt apply to my case
> would it, since my annotations are on the variables themselves?
> 
> Thanks
> 
> 
> ----- Original Message ----
>> From: James Sutherland <jamesssss@xxxxxxxxx>
>> To: eclipselink-users@xxxxxxxxxxx
>> Sent: Wednesday, January 7, 2009 7:59:51 AM
>> Subject: Re: [eclipselink-users] two instances of same object in an
>> indirectList ?
>> 
>> 
>> Are you using field access or property access in your mappings?  If you
>> are
>> using property access this could cause the issue, using property access
>> with
>> side-effects in your get/set methods can corrupt your object model.  If
>> you
>> want to use property access, ensure you use get/set methods that have no
>> side-effects.
>> 
>> See,
>> http://en.wikibooks.org/wiki/Java_Persistence/Mapping#Odd_behavior
>> 
>> 
>> 
>> Phillip Ross-3 wrote:
>> > 
>> > 
>> > 
>> >> In EclipseLink Collection will default to IndirectList when reading
>> from
>> >> the
>> > 
>> >> database if the relationship is LAZY.  If it is EAGER it will default
>> to
>> >> Vector.  If it were of type Set, it would default to IndirectSet or
>> >> HashSet.
>> > 
>> > That makes sense, and that is what I was seeing, so that is good.
>> > 
>> > 
>> >> My guess as to what you are seeing is that in the container each
>> >> transaction
>> >> is a new persistence context, so you get a new clone in each
>> transaction
>> >> that has the IndirectList.  Outside the container the persistence
>> context
>> >> is
>> >> extended as long as the EntityManager exists, so when you do a find()
>> you
>> >> get the same object that you originally persisted, and I assume your
>> >> constructor is setting it to a HashSet.  If you create a new
>> >> EntityManager
>> >> or refresh() the object outside the container you will get the
>> >> IndirectList.
>> > 
>> > The code is a pretty simple test.  It involves two stateless session
>> > beans.  One is a "service" bean
>> > and the other is the "persistence fascade" bean.  They both use default
>> > container managed transactions
>> > without any explicit transaction attributes, and the fascade has its
>> > entity manager injected via a
>> > @PersistenceContext annotation.  The fascade is then injected into the
>> > service bean with an @EJB annotation.
>> > 
>> > The purpose of the method of the particular service bean being tested
>> is
>> > to count the number of
>> > related Opening entities that a specific OpeningStatus or Department
>> > entity may be related to.  There are
>> > two different methods, one for status and one for department but I'll
>> just
>> > talk about one for the purposes
>> > of this explanation.  The method simply takes the OpeningStatus, passes
>> it
>> > to the fascade method which takes
>> > the id value of the OpeningStatus, uses the entity manager in the
>> fascade
>> > to find a managed instance of the
>> > OpeningStatus, then return it back to the service method, and the
>> service
>> > method calls the getOpenings
>> > method to get the collection of related openings, then the size()
>> method
>> > to return the size of that collection.
>> > I know this could be done alternatively with a single jpa query but
>> let's
>> > not get into that now.
>> > 
>> > So, in my test, the transaction should begin at the service bean method
>> > invocation and continue through
>> > into the fascade, the instance of OpeningStatus should stay
>> > managed/attached, return the collection, and
>> > the size should correctly be calculated since the related openings can
>> be
>> > fetched lazily.  So the final size
>> > is determined within a single transaction and returned back to the
>> caller
>> > (the test code).
>> > 
>> > Also, you are correct, the constructors for OpeningStatus and
>> Department
>> > initialize the property with a HashSet.
>> > 
>> > Is my explanation clear and my logic sound?
>> > 
>> > 
>> > 
>> >> As to why you have duplicates, this is odd, it means you have
>> duplicate
>> >> rows
>> >> in your database, or you added the object to the collection twice,
>> which
>> >> is
>> >> not good.  You should not add the object to the collection if it is
>> >> already
>> >> contained in it.
>> > 
>> > I definately do not have duplicate rows in the database... there is a
>> > primary key on the id fields of each entity
>> > and setting FINEST log level in persistence.xml shows only a single
>> > insert, so I know the state of the database
>> > is valid, consistent, etc.
>> > 
>> > I definately do not add the Opening to the collection properties of
>> > OpeningStatus or Department entities more
>> > than once since I have rigid patterns for relating.  I always use the
>> > setter method on the Opening to assign an
>> > OpeningStatus or Department to an Opening, and that setter contains the
>> > logic to managed the relationship in
>> > both directions.  Here's example code:
>> > 
>> > public void setStatus(OpeningStatus status) {
>> >         if (this.status != null) {
>> >             this.status.getOpenings().remove(this);
>> >         }
>> >         if (status != null) {
>> >             Collectionopenings = status.getOpenings();
>> >             if (openings != null) {
>> >                 openings.add(this);
>> >                 this.status = status;
>> >             }
>> >         }
>> >     }
>> > 
>> > public void setDepartment(Department department) {
>> >         if (this.department != null) {
>> >             this.department.getOpenings().remove(this);
>> >         }
>> >         if (department != null) {
>> >             Collectionopenings = department.getOpenings();
>> >             if (openings != null) {
>> >                 openings.add(this);
>> >                 this.department = department;
>> >             }
>> >         }
>> >     }
>> > 
>> > 
>> > If you can find a bug in that code which shows the entities being added
>> > twice (or any bug at all
>> > for that matter) I'd greatly appreciate it!
>> > 
>> > I use the same pattern in about 6 or 7 other entities with one-to-many
>> > relationships and it works
>> > fine, but I just cant find the difference for these.  I've since worked
>> > around the entire issue by explicitly
>> > changing the types from Collection to Set, and changing all of the
>> queries
>> > to push the returned Lists
>> > with duplicates into Sets.  This works, but still concerned about the
>> > duplicates being returned in the
>> > lists returned by the queries :(
>> > 
>> > Thanks!
>> > - Phillip
>> > 
>> > 
>> > 
>> > 
>> > 
>> > 
>> >> 
>> >> 
>> >> 
>> >> Phillip Ross-3 wrote:
>> >> > 
>> >> > HI Tom, thanks for the response.  I can certainly attempt to post
>> the
>> >> > definition.
>> >> > 
>> >> > On one side of the relationship the entity has two properties as
>> >> follows:
>> >> > 
>> >> > 
>> >> 
>> @ManyToOne(cascade={CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REFRESH})
>> >> >  private Department department;
>> >> > 
>> >> > 
>> >> 
>> @ManyToOne(cascade={CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REFRESH})
>> >> > private OpeningStatus status;
>> >> > 
>> >> > While on the other side, the properties are as follows:
>> >> > 
>> >> > @OneToMany(mappedBy = "department",
>> >> > cascade={CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REFRESH})
>> >> > private Collectionopenings;
>> >> > 
>> >> > and
>> >> > 
>> >> > @OneToMany(mappedBy = "status",
>> >> > cascade={CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REFRESH})
>> >> > private Collectionopenings;
>> >> > 
>> >> > 
>> >> > I've worked around the issue for now by redefining all of the
>> >> Collection
>> >> > based properties as Set based instead.  Luckily they all fit within
>> the
>> >> > Set semantics so I'm happy to leave them that way.  But I'm still
>> >> > wondering why the underlying Lists contain duplicates, or... are
>> lists
>> >> at
>> >> > all rather than sets.  I should mention again that the query
>> involves
>> >> > invoking find() on an entity manager with either a Department or
>> >> > OpeningStatus and both of those have Collection based relational
>> >> > properties mapped to OpeningStatus and Department.  But the
>> underlying
>> >> > Collection is an IndirectList (when running inside the container)
>> and a
>> >> > HashSet when running outside.
>> >> > 
>> >> > Thanks
>> >> > - Phillip
>> >> > 
>> >> > 
>> >> > 
>> >> > ----- Original Message ----
>> >> >> From: Tom Ware 
>> >> >> To: EclipseLink User Discussions 
>> >> >> Sent: Tuesday, January 6, 2009 9:30:03 AM
>> >> >> Subject: Re: [eclipselink-users] two instances of same object in an
>> >> >> indirectList ?
>> >> >> 
>> >> >> Hi Phillip,
>> >> >> 
>> >> >>   I am a bit surprised that you are getting a TransparentList.  I
>> >> would
>> >> >> expect a 
>> >> >> TransparentSet.  Can you post the definition of the relationship?
>> >> >> 
>> >> >> -Tom
>> >> >> 
>> >> >> Phillip Ross wrote:
>> >> >> > Hi all... I'm looking for some quick ideas.
>> >> >> > 
>> >> >> > Was wondering if someone could quickly think of a few things for
>> me
>> >> to
>> >> >> check 
>> >> >> out with a problem I'm having.  I have a pair of entities with
>> >> OneToMany 
>> >> >> relationships to a third entity.  If I return an instance with the
>> >> entity 
>> >> >> manager using find and PK id, I get an instance and the Collection
>> >> >> contains two 
>> >> >> items.  Both items are references to the same related object...
>> exact
>> >> >> hashCodes, 
>> >> >> etc.  When I run outside the container, the Collection is a HashSet
>> >> and
>> >> >> it only 
>> >> >> contains one reference to the related item due to the Set semantics
>> >> which
>> >> >> works 
>> >> >> great... but inside the container the Collection is an eclipselink
>> >> >> specific 
>> >> >> IndirectList but with dups of the same item.
>> >> >> > 
>> >> >> > So, might there be something I'm doing wrong that's creating the
>> >> dups
>> >> >> in the 
>> >> >> indirect list?  I have several other similar OneToMany relations to
>> >> other 
>> >> >> entities and they don't exhibit the problem, but I've been racking
>> my
>> >> >> mind 
>> >> >> trying to figure out if there is something I'm missing here to get
>> the
>> > 
>> >> >> dedup to 
>> >> >> happen on the IndirectList.  There are several things I'm sure I
>> could
>> >> >> implement 
>> >> >> myself to work around all of this and handle deduping and such, but
>> >> I'm
>> >> >> really 
>> >> >> wondering why this duplication happens in the indirect list with
>> these
>> >> >> specific 
>> >> >> entities and not with the other three or four other similarly
>> >> patterned 
>> >> >> OneToMany related entites.
>> >> >> > 
>> >> >> > Any ideas?  I'm using eclipselink 1.0.2, container is glassfish
>> >> >> v2.1-b60e 
>> >> >> (tried with earlier glassfish versions as well).
>> >> >> > 
>> >> >> > Thanks!
>> >> >> > - Phillip
>> >> >> > 
>> >> > 
>> >> 
>> > 
> 
> 


-----
---
http://wiki.eclipse.org/User:James.sutherland.oracle.com James Sutherland 
http://www.eclipse.org/eclipselink/
 EclipseLink ,  http://www.oracle.com/technology/products/ias/toplink/
TopLink 
Wiki:  http://wiki.eclipse.org/EclipseLink EclipseLink , 
http://wiki.oracle.com/page/TopLink TopLink 
Forums:  http://forums.oracle.com/forums/forum.jspa?forumID=48 TopLink , 
http://www.nabble.com/EclipseLink-f26430.html EclipseLink 
Book:  http://en.wikibooks.org/wiki/Java_Persistence Java Persistence 
-- 
View this message in context: http://www.nabble.com/two-instances-of-same-object-in-an-indirectList---tp21297380p21351018.html
Sent from the EclipseLink - Users mailing list archive at Nabble.com.



Back to the top