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 ?

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) {
>             Collection<Opening> openings = 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) {
>             Collection<Opening> openings = 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---tp21297380p21330862.html
Sent from the EclipseLink - Users mailing list archive at Nabble.com.



Back to the top