[
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.