skyman
skyman

Reputation: 2335

How to prevent Hibernate from creating duplicates in many to one mapping

I have two simple objects; Person and City. A City may have multiple Persons but a Person only one City. I would like to be able to save a Person and have Hibernate automatically save the City - only if it is a new City - that is cities should be unique. With my mapping I find that every time a Person is saved, a new City is inserted in the database, regardless if it is already there. I am sure that this is fairly straight forward, however I am new to Hibernate and struggling with it. Note, if I save two Person with a single City in one session - all works. This is an issue across sessions. I have also created equals and hashcode methods in the City class as per below.

Person.hbm.xml

  <id name="id" type="long" column="id" >
   <generator class="native"/>
  </id>

  <property name="firstName">
   <column name="firstname" />
  </property>

 <many-to-one name="city" class="com.project.City" cascade="save-update">
  <column name="cityId" not-null="true" />
 </many-to-one>


City.hbm.xml

   <id name="id" type="long" column="id" >
   <generator class="native"/>
  </id>

  <property name="description" unique="true">
   <column name="description" />
  </property>


public class City implements java.io.Serializable {
    private Long id;
    private String description;

      // getters and setters

    public boolean equals(Object other) {
        if (this==other) return true;
        if ( !(other instanceof City) ) return false;
        final City that = (City) other;
        return this.description.equals( that.getDescription() );
    }   

    public int hashCode() {
        return description.hashCode();
    }    
}




    try {
      Transaction tx = session.beginTransaction();

      Criteria criteria = session.createCriteria(City.class);
      criteria.add(Restrictions.eq("description", city.getDescription()));
      criteria.setMaxResults(1);

      // Possible to use:
      // List<City> cities = criteria.list();
      // However, this generates warnings about unsafe casting.  If you use this then
      // set @SuppressWarnings("unchecked")
      List<City> cities = HibernateUtil.castList(City.class, criteria.list());

      if (cities.isEmpty())  {
          session.save(city);
        }
      else  {
          city = (City) cities.get(0);
        }
          session.flush();
          tx.commit();
            }
        catch (Exception e) {
          return null;
            }
      }
return city;

Upvotes: 0

Views: 1667

Answers (1)

dfb
dfb

Reputation: 13289

    if ( !(other instanceof Ward) ) return false;
    final Ward that = (Ward) other;

Shouldn't this be City instead of Ward?

Upvotes: 1

Related Questions