Return-Path: Delivered-To: apmail-openjpa-dev-archive@www.apache.org Received: (qmail 52942 invoked from network); 18 Dec 2007 16:40:22 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 18 Dec 2007 16:40:22 -0000 Received: (qmail 30507 invoked by uid 500); 18 Dec 2007 16:40:11 -0000 Delivered-To: apmail-openjpa-dev-archive@openjpa.apache.org Received: (qmail 30355 invoked by uid 500); 18 Dec 2007 16:40:10 -0000 Mailing-List: contact dev-help@openjpa.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@openjpa.apache.org Delivered-To: mailing list dev@openjpa.apache.org Received: (qmail 30346 invoked by uid 99); 18 Dec 2007 16:40:10 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 18 Dec 2007 08:40:10 -0800 X-ASF-Spam-Status: No, hits=4.0 required=10.0 tests=DNS_FROM_OPENWHOIS,FORGED_YAHOO_RCVD,SPF_HELO_PASS,SPF_PASS,WHOIS_MYPRIVREG X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: domain of lists@nabble.com designates 216.139.236.158 as permitted sender) Received: from [216.139.236.158] (HELO kuber.nabble.com) (216.139.236.158) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 18 Dec 2007 16:39:48 +0000 Received: from isper.nabble.com ([192.168.236.156]) by kuber.nabble.com with esmtp (Exim 4.63) (envelope-from ) id 1J4fTz-0002Qz-1C for dev@openjpa.apache.org; Tue, 18 Dec 2007 08:39:51 -0800 Message-ID: <14400747.post@talk.nabble.com> Date: Tue, 18 Dec 2007 08:39:51 -0800 (PST) From: jackson12 To: dev@openjpa.apache.org Subject: Re: merge only works with managed entity In-Reply-To: <7262f25e0712160733id740cf8v407505ae3298a539@mail.gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-Nabble-From: kemin_chen@yahoo.com References: <14216438.post@talk.nabble.com> <89c0c52c0712070922m167a6934j14535d459cd7e9c@mail.gmail.com> <14217307.post@talk.nabble.com> <89c0c52c0712100824t498dc987m37c9b55102f636a2@mail.gmail.com> <14274498.post@talk.nabble.com> <89c0c52c0712110653t5d895acah954d0f7471d74bb7@mail.gmail.com> <14276253.post@talk.nabble.com> <14336208.post@talk.nabble.com> <14339820.post@talk.nabble.com> <7262f25e0712160733id740cf8v407505ae3298a539@mail.gmail.com> X-Virus-Checked: Checked by ClamAV on apache.org I will create a small use case for this. thanks Patrick Linskey-2 wrote: > > Hi, > > Is it possible for you to post an example of the failure behavior? I'd > like to a) see why it's not Just Working, and b) have a regression > test in place if this fix does the trick. > > -Patrick > > On Dec 15, 2007 5:55 AM, jackson12 wrote: >> >> After making some small changes in OpenJPA source code, I am able to call >> a >> merge() method with an entity that's not detached. This allows our code >> that >> works in JBoss also work in IBM Websphere. >> >> Here is the change: >> >> in the attach method of class VersionAttachStrategy >> replace line 76: >> boolean isNew = !broker.isDetached(pc); >> with: >> Object id = getDetachedObjectId(manager, toAttach); >> boolean isNew = true; >> if (id != null) isNew = false; >> >> Do you see any issues with this change? >> >> Thanks for the help! >> >> >> >> >> jackson12 wrote: >> > >> > Kevin, Patrick, >> > >> > Any update on this? >> > >> > We want to quickly decide if we can switch to OpenJPA with IBM >> Websphere, >> > this is currently our show stopper. >> > >> > >> > >> > jackson12 wrote: >> >> >> >> Kevin, >> >> >> >> What you described is exactly the problem. >> >> >> >> But unfortunately we don't have the luxury to use the approach you >> >> proposed (find-->detach-->merge) >> >> because our application is a struts based web application, and on the >> web >> >> tier we have a different set of DTOs to hold the changes from end user >> >> and currently we are only migrating our backend to use EJB3. >> >> >> >> so at someplaces, we have to copy the values from DTO to managed or >> >> detached entities, but I don't know any "smarter copy" that can also >> >> maintain the extra code in the managed or detached entity. >> >> >> >> This should be a very common scenarios. Please let me know if you or >> >> Patrick have some other ideas. >> >> >> >> Thanks in advance! >> >> >> >> >> >> >> >> Kevin Sutter wrote: >> >>> >> >>> jackson12, >> >>> I understand your problem. Since the Person object holds a nested >> >>> Address >> >>> object, when you use the copyProperties() method, the nested managed >> >>> Address >> >>> object gets overwritten with an unmanaged instance. Right? >> >>> >> >>> The copyProperties() method is kind of simple. It just copies >> attribute >> >>> by >> >>> attribute. Since it sees an Address attribute, it just copies the >> new >> >>> Address attribute right on top of the managed one. The problem here >> is >> >>> that >> >>> the managed instance of Address has OpenJPA state associated with it. >> >>> When >> >>> the copyProperties() is invoked, we lose all of that state data (and >> >>> code) >> >>> due to the unmanaged Address object. Hibernate's method of keeping >> >>> track of >> >>> object state must be different from the way that OpenJPA does it. >> >>> >> >>> What it sounds like you need is a smarter copyProperties() method. >> One >> >>> that >> >>> will copy the simple property values, but then traverse into the >> nested >> >>> managed objects to do it's own copyProperties(). But, then if these >> >>> nested >> >>> objects have additional nested managed objects, you run into the same >> >>> complication. >> >>> >> >>> How about using the merge() operation to accomplish this task? >> Instead >> >>> of >> >>> just creating new unmanaged instances of your Person objects, do a >> find >> >>> operation to get them managed by your persistence context. Then, >> detach >> >>> the >> >>> entities and do whatever updates you want to these detached >> instances. >> >>> When >> >>> you are ready to copy them back in to the persistence context, call >> the >> >>> merge() method and let the changes merge back into the persistence >> >>> context. >> >>> This would seem to be along the lines of processing that you are >> looking >> >>> for, but from a different angle. >> >>> >> >>> I'll copy Patrick on this reply just to see if he has some other >> ideas. >> >>> >> >>> Thanks, >> >>> Kevin >> >>> >> >>> >> >>> On Dec 11, 2007 8:02 AM, jackson12 wrote: >> >>> >> >>>> >> >>>> Kevin, >> >>>> >> >>>> Thanks again for the clarification. >> >>>> >> >>>> Here is the scenario for the nested properties. >> >>>> >> >>>> Suppose I have an entity Person that holds a nested entity Address. >> >>>> Assume >> >>>> I >> >>>> use find() method to load >> >>>> the Person entity with Address. Now in order to apply the changes, >> we >> >>>> normally use >> >>>> >> >>>> PropertyUtils.copyProperties(managedPerson, inputPerson); >> >>>> >> >>>> or >> >>>> BeanUtils.copyProperties(managedPerson, inputPerson); >> >>>> >> >>>> but these copyProperties method will make the nested Address entity >> >>>> non-managed (because the Address reference will be replaced by , and >> >>>> hence >> >>>> OpenJPA will throw exception when I call the merge() method later. >> In >> >>>> order >> >>>> to bypass this, we have to copy field by field from inputPerson to >> >>>> managedPerson including the nested entity. This makes the code very >> >>>> error >> >>>> prone and ugly. >> >>>> >> >>>> JBoss's implementation does not require the inputPerson to be >> managed >> >>>> or >> >>>> detached, I know this maybe beyond JPA1.0 spec, but it is really >> very >> >>>> helpful. >> >>>> >> >>>> Do I misunderstand anything? >> >>>> >> >>>> thanks a lot >> >>>> >> >>>> >> >>>> >> >>>> Kevin Sutter wrote: >> >>>> > >> >>>> > jackson12, >> >>>> > If I am understanding your scenario correctly, your userProfile >> input >> >>>> > parameter is an unmanaged entity, but the key for this entity does >> >>>> already >> >>>> > exist in the database. So, when you attempt to do the merge() >> >>>> processing >> >>>> > (and subsequent transaction commit), you are getting a "duplicate >> >>>> key" >> >>>> > exception from Oracle. >> >>>> > >> >>>> > Calling merge() with a new unmanaged entity acts like a persist() >> >>>> call >> >>>> and >> >>>> > adds it to the persistence context. The persist() method is >> intended >> >>>> for >> >>>> > new entities that do not currently exist in the database. >> >>>> > >> >>>> > So, on the surface, your scenario seems to be acting as I would >> >>>> expect >> >>>> > with >> >>>> > any JPA implementation. But, you have indicated that JBoss' >> >>>> Hibernate >> >>>> is >> >>>> > processing as you had hoped. Based on my understanding of the >> spec >> >>>> and >> >>>> > your >> >>>> > scenario, I think you are getting lucky with Hibernate. >> >>>> > >> >>>> > I would suggest doing the find() operation first to properly load >> the >> >>>> > entity >> >>>> > into the persistence context and then do your updates. You can >> >>>> always >> >>>> > detach this entity from the persistence context, if necessary, for >> >>>> other >> >>>> > processing and then merge it back in later. Since the merge() >> would >> >>>> be >> >>>> > operating on a known, detached entity, an update operation will be >> >>>> > performed >> >>>> > instead of the insert. >> >>>> > >> >>>> > A few other observations... Remember that the merge() operation >> >>>> returns >> >>>> > the >> >>>> > managed entity as a return value. The original entity that you >> >>>> passed >> >>>> > into >> >>>> > the merge() method is not managed. So, if you want any state >> changes >> >>>> to >> >>>> > the >> >>>> > entity to be properly maintained and persisted, you need to use >> the >> >>>> > returned >> >>>> > managed instance of the entity from the merge() operation. >> >>>> > >> >>>> > You also mentioned how the nested properties are not managed. >> This >> >>>> may >> >>>> be >> >>>> > related to the above observation. Another possibility is that you >> >>>> need >> >>>> to >> >>>> > declare whether you want the merge processing to be cascaded to >> the >> >>>> > objects >> >>>> > pointed to by the entity. You would specify this on the >> relationship >> >>>> > annotation via the cascade=CascadeType.MERGE element. You haven't >> >>>> > provided >> >>>> > the complete entity definition, so I'm not exactly sure how you >> have >> >>>> these >> >>>> > entity types defined. >> >>>> > >> >>>> > Hope this information helps. >> >>>> > >> >>>> > Good luck, >> >>>> > Kevin >> >>>> > >> >>>> > On Dec 7, 2007 11:50 AM, jackson12 wrote: >> >>>> > >> >>>> >> >> >>>> >> Thanks Kevin for your prompt response. >> >>>> >> Here is a simple use case we have: >> >>>> >> within an EJB , we have the following method: >> >>>> >> >> >>>> >> public UserProfile updateUserProfile(UserProfile userProfile) { >> >>>> >> return getProfileDAO().update(userProfile); >> >>>> >> } >> >>>> >> >> >>>> >> when this method is called, the input parameter has all of the >> >>>> values >> >>>> >> including the key, but we got a runtime exception because it's >> >>>> trying >> >>>> to >> >>>> >> insert userProfile into database. >> >>>> >> >> >>>> >> org.apache.openjpa.persistence.PersistenceException: ORA-00001: >> >>>> unique >> >>>> >> constraint (VPDNGDITR17.PK_SECURITY_USER_PROFILE) violated >> >>>> FailedObject: >> >>>> >> prepstmnt 1645109774 INSERT INTO SECURITY_USER_PROFILE (OID, >> >>>> >> MODIFIED_BY_USER, ........ >> >>>> >> >> >>>> >> After we change the code to the following, it works fine: >> >>>> >> public UserProfile updateUserProfile(UserProfile >> userProfile) >> >>>> { >> >>>> >> UserProfileDAO profileDAO = getProfileDao(); >> >>>> >> UserProfile tmpUserProfile = >> >>>> >> profileDAO.getUserProfile(userProfile.getName()); >> >>>> >> PropertyUtils.copyProperties(tmpUserProfile, >> >>>> userProfile); >> >>>> >> return getProfileDao().update(tmpUserProfile); >> >>>> >> } >> >>>> >> >> >>>> >> Here is the update method of ProfileDAO: >> >>>> >> >> >>>> >> public T update(T entity) >> >>>> >> { >> >>>> >> getEntityManager().merge(entity); >> >>>> >> } >> >>>> >> >> >>>> >> When the input parameter has nested object, even the above >> approach >> >>>> won't >> >>>> >> work any more, because PropertyUtils.copyProperties will make the >> >>>> nested >> >>>> >> object not managed anymore. >> >>>> >> >> >>>> >> Thanks a lot >> >>>> >> >> >>>> >> >> >>>> >> Kevin Sutter wrote: >> >>>> >> > >> >>>> >> > jackson12, >> >>>> >> > Could you be more specific with your example? We have various >> >>>> >> testcases >> >>>> >> > that do this exact process of merging in non-managed entities >> >>>> (without >> >>>> >> > first >> >>>> >> > retrieving the entity from the DB). Could you further explain >> >>>> your >> >>>> >> test >> >>>> >> > scenario and what results you are getting? >> >>>> >> > >> >>>> >> > Thanks, >> >>>> >> > Kevin >> >>>> >> > >> >>>> >> > On Dec 7, 2007 11:12 AM, jackson12 >> wrote: >> >>>> >> > >> >>>> >> >> >> >>>> >> >> Hi, We are trying to migrate our JBoss EJB3 application to IBM >> >>>> >> websphere >> >>>> >> >> with >> >>>> >> >> OpenJPA. We noticed in OpenJPA, the merge method does not work >> >>>> with >> >>>> >> >> non-managed entity. You have to retrieve the entity from DB, >> make >> >>>> some >> >>>> >> >> changes and then call merge. But with JBoss's implementation, >> you >> >>>> >> don't >> >>>> >> >> have >> >>>> >> >> to retrieve the entity from DB first. the merge method works >> fine >> >>>> for >> >>>> >> >> non-managed entity. >> >>>> >> >> >> >>>> >> >> Is there anyway for OpenJPA to work the same way as JBoss's >> JPA >> >>>> >> >> implementation on this part? or is there a way in OpenJPA to >> make >> >>>> a >> >>>> >> >> non-managed entity managed? >> >>>> >> >> >> >>>> >> >> thanks in advance >> >>>> >> >> -- >> >>>> >> >> View this message in context: >> >>>> >> >> >> >>>> >> >> >>>> >> http://www.nabble.com/merge-only-works-with-managed-entity-tf4963245.html#a14216438 >> >>>> >> >> Sent from the OpenJPA Developers mailing list archive at >> >>>> Nabble.com. >> >>>> >> >> >> >>>> >> >> >> >>>> >> > >> >>>> >> > >> >>>> >> >> >>>> >> -- >> >>>> >> View this message in context: >> >>>> >> >> >>>> >> http://www.nabble.com/merge-only-works-with-managed-entity-tf4963245.html#a14217307 >> >>>> >> Sent from the OpenJPA Developers mailing list archive at >> Nabble.com. >> >>>> >> >> >>>> >> >> >>>> > >> >>>> > >> >>>> >> >>>> -- >> >>>> View this message in context: >> >>>> >> http://www.nabble.com/merge-only-works-with-managed-entity-tp14216438p14274498.html >> >>>> Sent from the OpenJPA Developers mailing list archive at Nabble.com. >> >>>> >> >>>> >> >>> >> >>> >> >> >> >> >> > >> > >> >> -- >> View this message in context: >> http://www.nabble.com/merge-only-works-with-managed-entity-tp14216438p14339820.html >> >> Sent from the OpenJPA Developers mailing list archive at Nabble.com. >> >> > > > > -- > Patrick Linskey > 202 669 5907 > > -- View this message in context: http://www.nabble.com/merge-only-works-with-managed-entity-tp14216438p14400747.html Sent from the OpenJPA Developers mailing list archive at Nabble.com.