-->
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.  [ 2 posts ] 
Author Message
 Post subject: natural id behavior?
PostPosted: Wed Dec 07, 2005 5:58 pm 
Newbie

Joined: Thu Dec 01, 2005 11:34 am
Posts: 19
Hibernate version:
3.0.05

Hi! I'm a complete newbie to hibernate, and just starting to get things working. I'm trying to get hibernate to behave the way my previous home-rolled DAOs did. One such behavior is this: If you try to insert a record into a table that has the same natural key as one that already exists, don't do the insert.

For example: I have a class that has 2 properties: name and description. If I create an object with the name and description both set to "test", hibernate will persist the object and get an ID assigned. If I create a second object of the same type with the same name and description ("test"), I'd like hibernate to NOT insert a second row.

Now, I could do a hit on the database myself to look up that object, and then I'd know the primary key for that object, and I'd be done. But that's extra code to do each time I do an insert (and it's an extra database hit) that I'd rather automate if possible. I ran across natural ID's, and thought this might be a good solution. However, even with the natural ID defined in the mapping file, and equals defined in the class, I still get an insert of a new row. I'd like to avoid that.

Mapping documents:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!--
Auto-generated mapping file from
the hibernate.org cfg2hbm engine
-->
<class name="pinnacle.dao.datavo.hibernatetest.CoordinateFeatureType" table="COORDINATE_FEATURE_TYPE" schema="PINNACLE">
<id name="id" type="long">
<column name="ID" />

<generator class="seqhilo">
<param name="sequence">SQ_COORDINATE_FEATURE_TYPE</param>

<param name="max_lo">100</param>
</generator>
</id>

<natural-id mutable="true">
<property name="name" type="string">
<column name="NAME" length="100" />
</property>

<property name="description" type="string">
<column name="DESCRIPTION" length="500" />
</property>
</natural-id>

<set name="coordinateFeatures" inverse="true">
<key>
<column name="FEATURE_TYPE_ID" precision="22" scale="0" />
</key>

<one-to-many class="pinnacle.dao.datavo.hibernatetest.CoordinateFeature" />
</set>
</class>
</hibernate-mapping>

POJO:

public class CoordinateFeatureType implements java.io.Serializable {

// Fields

private long id;
private String name;
private String description;
private Set coordinateFeatures;

// Constructors

/** default constructor */
public CoordinateFeatureType() {
}

/** constructor with id */
public CoordinateFeatureType(long id) {
this.id = id;
}

// Property accessors

public long getId() {
return this.id;
}

public void setId(long id) {
this.id = id;
}

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

public String getDescription() {
return this.description;
}

public void setDescription(String description) {
this.description = description;
}

public Set getCoordinateFeatures() {
return this.coordinateFeatures;
}

public void setCoordinateFeatures(Set coordinateFeatures) {
this.coordinateFeatures = coordinateFeatures;
}

public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if ( (obj == null) || (obj.getClass() != this.getClass())) {
return false;
}
CoordinateFeatureType o = (CoordinateFeatureType) obj;
// object must be corrent type at this point
return
EqualsUtil.areEqual(this.getName(), o.getName()) &&
EqualsUtil.areEqual(this.getDescription(), o.getDescription());
}

public int hashCode() {
int result = HashCodeUtil.SEED;
result += HashCodeUtil.hash(result, this.getName());
result += HashCodeUtil.hash(result, this.getDescription());
return result;
}
}

My code to test looks like this (I know it's simplistic to the extreme, but I just want to see what I can get working before I start implementing patterns) Running this code a second time should not result in a table insert (or, that's my hope.) What should I change to make this work?

Running Code
Configuration cfg = new Configuration();
SessionFactory f = cfg.buildSessionFactory();
Session s = f.openSession();
Transaction tx = s.beginTransaction();
CoordinateFeatureType t = new CoordinateFeatureType();
t.setName("test");
t.setDescription("test");
s.saveOrUpdate(t);
tx.commit();

Thanks for any help!

-Jim


Top
 Profile  
 
 Post subject: me too...
PostPosted: Tue May 30, 2006 9:36 pm 
Newbie

Joined: Tue May 30, 2006 9:29 pm
Posts: 2
I have found the same thing as you wrt natural-id not being enforced.
Apparently, it is not implemented to do so...
http://forum.hibernate.org/viewtopic.ph ... =naturalid
... which suggests that natural-id is only good for the Restrictions.naturalId() type lookup and creation of unique constraints for the database (if you are generating db guff from your mappings).
If you've discovered anything to the contrary in the last 5 months, please share :)


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 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.