-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 
Author Message
 Post subject: Persisting detached objects using merge
PostPosted: Thu Jan 17, 2008 3:46 pm 
Newbie

Joined: Thu Jan 17, 2008 3:19 pm
Posts: 4
Hi,

The problem:
When I try to persist a detached object using merge, Hibernate generates an Insert statement instead of an Update statement

Settings:
I am using hibernate-annotations-3.3.0.GA and
hibernate-entitymanager-3.3.1.GA
I'm running POJO code that runs in a tomcat 5.5

Details:
First I get a HostImpl object from the databse

EntityManager em = EmUtil.getEntityManager();

host = em.find(HostImpl.class, id);

em.close();

I put the host object I get in an Hashmap for later use
and its details are sent to the client application for update

in a later time updated detail are recieved from the client
I take the object back from the hashmap and call a few setters on it with the data I got from the client.

Then I call:

public static void saveHost(HostImpl host)
{
EntityManager em = EmUtil.getEntityManager();
em.getTransaction().begin();
em.merge(host);
em.getTransaction().commit();
em.close();

on the commit I get a constraint violation from the database because of a duplicate host name and I see in the log that hibernate generated an insert statement

What am I doing wrong?

Thanks


Top
 Profile  
 
 Post subject: Re: Persisting detached objects using merge
PostPosted: Thu Jan 17, 2008 4:18 pm 
Expert
Expert

Joined: Wed Apr 11, 2007 11:39 am
Posts: 735
Location: Montreal, QC
what is the id field and spec of HostImpl?



Farzad-


Top
 Profile  
 
 Post subject: Re: Persisting detached objects using merge
PostPosted: Fri Jan 18, 2008 10:57 am 
Newbie

Joined: Thu Jan 17, 2008 3:19 pm
Posts: 4
The hostImpl details are below:

@Entity
@Table(name="SYS_HOSTS")
@javax.persistence.SequenceGenerator(
name="SEQ_STORE",
allocationSize=5,
sequenceName="HIBERNATE_SEQUENCE")
@AccessType("field")
public class HostImpl extends AbstractEntity implements IHost
{

@Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_STORE")
@Column(name="HOST_ID")
private Long m_hostID;

@Column(name="HOST_CODE", unique=true, nullable=false)
private String m_name;

@Column(name="DESCRIPTION")
private String m_description;

@Column(name="OS_PLATFORM")
@Enumerated(EnumType.STRING)
private OsPlatform m_osPlatform;

@Column(name="HOST_TYPE")
private HostType m_hostType;

@Column(name="IP_ADDRESS")
private String m_ipAddress;

@Column(name="PRIMARY_HOST_IND")
private String m_primaryHostInd;

//,targetEntity=SiteImpl.class
@ManyToOne(cascade={CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name="SITE_ID")
private SiteImpl m_site;

@ManyToOne
@JoinColumn(name="HA_HOST_ID")
private HostImpl m_haHost;

@ManyToOne
@JoinColumn(name="DRP_HOST_ID")
private HostImpl m_drpHost;

@Column(name="ADDITIONAL_INFO")
private String m_additionalInfo;



/**
* Private constructor for use only by OR mapping code (Hibernate)
*/
private HostImpl()
{

}

public HostImpl(String i_name)
{
m_name = i_name;
}

// ----------------------------------------------------------------------------

public Long getHostID()
{
return m_hostID;
}
.....


Top
 Profile  
 
 Post subject: Re: Persisting detached objects using merge
PostPosted: Fri Jan 18, 2008 11:26 am 
Expert
Expert

Joined: Wed Apr 11, 2007 11:39 am
Posts: 735
Location: Montreal, QC
This is a bit weird. You can check two things:

1- I don't feel good about the private default constructor. Try it with a public one but in any case I doubt that has anything to do with this problem.


2- Are you sure the id property is not set to null? Can you log what its id is before merge? Also please check if you see a select statement upon merge.




Farzad-


Top
 Profile  
 
 Post subject: hibernate considers id field, not unique constraint
PostPosted: Tue Mar 18, 2008 11:34 am 
Newbie

Joined: Thu Nov 18, 2004 6:01 pm
Posts: 17
I'm struggling with this problem, too.

You and I share the same case.

You have a host name field that has a unique constraint. I also have a unique constraint.

You host id field is the identifier of the entity and is not the same field as the unique constraint. This is similar to my case.

We both want to see an update not an insert, but hibernate does not pay attention to the unique constraints of non-identity fields when deciding to insert or update.

I wonder what the practice is for this case. I will keep searching.

Good luck.


Top
 Profile  
 
 Post subject: here is answer:
PostPosted: Tue Mar 18, 2008 11:42 am 
Newbie

Joined: Thu Nov 18, 2004 6:01 pm
Posts: 17
http://forum.hibernate.org/viewtopic.ph ... +duplicate


Top
 Profile  
 
 Post subject: Re: here is answer:
PostPosted: Tue Mar 18, 2008 11:51 am 
Expert
Expert

Joined: Wed Apr 11, 2007 11:39 am
Posts: 735
Location: Montreal, QC
jfraney wrote:
http://forum.hibernate.org/viewtopic.php?t=963652&highlight=merge+duplicate



This is not the same problem. his problem here is that hibernate can not recognize if the object already has a primary key so it treats the object as a new one and tries to insert it.



Farzad-


Top
 Profile  
 
 Post subject: Persisting detached objects using merge
PostPosted: Tue Mar 18, 2008 12:13 pm 
Newbie

Joined: Thu Jan 17, 2008 3:19 pm
Posts: 4
That's correct, my problem is that Hibernate does not realize that I'm trying to update an existing object that has the same ID.

My understanding is that it happens since I use two separate EntityManagers one for getting the object from the database and another for updating it. Hibernate fails to identify that this is actually a detached object or maybe I am missing some code I need to call to re-attach it somehow

For now, I bypasses the problem by getting the object back from the database in the second Em, updating it and persisting it again


host = em.find(HostImpl.class, id);
// Update
host.updateControlFields();
//do some more update according to info passed from the UI layer

em.getTransaction().begin();
em.merge(host);
em.getTransaction().commit();
em.close();

This is of course not the correct solution since I already have the object in cache and I don't want to get it from the DB again


Top
 Profile  
 
 Post subject: oops...but wait
PostPosted: Tue Mar 18, 2008 2:50 pm 
Newbie

Joined: Thu Nov 18, 2004 6:01 pm
Posts: 17
Oops. You are right, of course. I was not careful enough when I read the first post. I guess I jumped to the conclusion that hibernate determined your host entity as transient for the same reason as for my entity: identifier field is unset.

I single stepped through the hibernate merge code to find out for myself what hibernate does to determine whether an object is transient or detached. I think in both our cases, we want the answer to be detached. This would I think result in an update, not an insert.

I found the test in in the method: org.hibernate.event.def.AbstractSaveEventListener.getEntityState(Object, Striing). This method uses org.hibernate.engine.ForeignKeys.isTransient(...).

Regards,
John


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.