persistence@glassfish.java.net

Re: Cascade merge does not occur

From: Marina Vatkina <Marina.Vatkina_at_Sun.COM>
Date: Tue, 09 Jan 2007 12:54:16 -0800

Hi Greg,

Can it be the case that you end up with different instances managed by different
  EMs? If you close an EM that manages an instance, all changes are lost. Please
try your test with a single EM and see if it solves the problem.

Another possible problem: starting utx after acquiring EM. Is your EM
application- or container-managed? If the former, you need to call
em.joinTransaction() after utx.begin().

regards,
-marina

Greg Ederer wrote:
> Hi Marina,
>
> Thanks for the reply.
>
> Marina Vatkina wrote:
>
>> Hi Greg,
>>
>> Does the person have its relationship to the address instantiated
>> at any point of time?
>>
>>
>
> Yes, I add the Address instances to the Person instance via
> Person.addAddress(). However, this call simply returns without doing
> anything because the Addresses are already in the Person.addresses
> collection.
>
> I actually perform this call (and all of the calls on entities) using
> reflection.
>
>> Also, what is the purpose of finding the address and detaching it
>> right away by closing the EM?
>>
>>
>
> This is embedded within a method that gets called recursively. The call
> to saveObject() takes place after the initial invocation of this method
> returns. I suppose I could do all of this processing using a single EM
> in object scope (or I could pass in the EM as an argument to the
> recursive method). Would this solve the problem?
>
> Thanks!
>
> Greg
>
>> thanks,
>> -marina
>>
>> Greg Ederer wrote On 01/06/07 23:00,:
>>
>>
>>> Hi,
>>>
>>> I have an entity called Person that has a list of Address entities.
>>> In Person, I have:
>>>
>>> @OneToMany(cascade=CascadeType.ALL, mappedBy="person")
>>> private List<Address> addresses = new ArrayList<Address>();
>>>
>>> public void addAddress(Address address)
>>> {
>>> if(this.getAddresses().contains(address))
>>> {
>>> return;
>>> }
>>> getAddresses().add(address);
>>> address.setPerson(this);
>>> }
>>>
>>> In Address, I have:
>>>
>>> @ManyToOne
>>> @JoinColumn(name="person", nullable = false)
>>> private Person person;
>>>
>>> In another class, I modify a Person instance, and also modify its
>>> owned Address instances, and then merge the Person instance.
>>> Afterward, the changes to the Person instance are reflected in the
>>> database, as expected; however, changes to the Address instances do
>>> not appear in the database.
>>>
>>> I get a reference to each Address via EntitManager.find(), like so:
>>>
>>> EntityManager em = getEntityManager();
>>> Object o = em.find(javaType, id);
>>> em.close();
>>>
>>> (where javaType is a Person Class instance) rather than retrieving
>>> from the Person object graph. Does this matter?
>>>
>>> I then merge the Person by calling the following method:
>>>
>>> private Object saveObject(Object o)
>>> {
>>> EntityManager em = getEntityManager();
>>> try
>>> {
>>> utx.begin();
>>> if(PropertyUtils.getProperty(o, "id") == null)
>>> {
>>> em.persist(o);
>>> }
>>> else
>>> {
>>> o = em.merge(o);
>>> }
>>> utx.commit();
>>> }
>>> catch (Exception ex)
>>> {
>>> //logger.severe("save failed.");
>>> ex.printStackTrace();
>>> try
>>> {
>>> utx.rollback();
>>> }
>>> catch (Exception e)
>>> {
>>> //logger.severe("rollback falied.");
>>> e.printStackTrace();
>>> }
>>> }
>>> finally
>>> {
>>> em.close();
>>> }
>>> return o;
>>> }
>>>
>>> My Person instance does have an id, so em.merge(o) should get
>>> executed. Also, utx is a UserTransaction obtained via @Resource.
>>>
>>> Can anyone tell me how to get this working?
>>>
>>> Thanks!
>>>
>>> Greg
>>>
>>>
>
>
>