2013-07-08 3 views
0

Возьмем, к примеру эти две сущности:Hibernate: использовать тот же внешний ключ, если x.equals (у)

Город:

<class name="City" table="city"> 
    <id name="id" column="id"/> 
    <property name="city_name" column="city_name"/> 
    <property name="country_name" column="country_name"/> 
</class> 

лицо:

<class name="Person" table="person"> 
    <id name="id" column="id"/> 
    <property name="name" column="name"/>  
    <many-to-one cascade="save-update" name="city" column="city_id" class="City"/> 
</class> 

City.equals() реализация возвращает true если оба city_name и coutry_name одинаковы.

Если я сохранить два Person во время одного сеанса:

Person person1 = new Person("Peter"); 
Person person2 = new Person("John"); 

City city1 = new City("Paris", "France"); 
City city2 = new City("Paris", "France"); 

person1.setCity(city1);  
person2.setCity(city2); 

session.save(person1); 
session.save(person2); 

Hibernate будет производить следующие записи:

город:

| id | name | city_id | 
------------------------- 
| 1 | Peter | 1 | 
| 2 | John | 2 | 

лицо:

| id | city_name | country_name | 
---------------------------------- 
| 1 | Paris | France | 
| 2 | Paris | France | 

Но могу ли я использовать Hibernate для повторного использования тех же city_id в person, когда cityX.equals(cityY)?

EDIT:

я должен уточнить, что city1 не может быть такой же, как экземпляр city2. Для краткости я не могу описать всю проблему, с которой я столкнулся. В фактическом случае таблица может содержать элементы дубликатов, я просто пытаюсь сохранить некоторое пространство, группируя некоторые конкретные элементы. Спасибо!

+0

Думаю, что в этом случае вы столкнулись с проблемой, потому что вы используете новый объект City на человека. Для Hibernate следует признать, что они фактически являются одним и тем же объектом, один и тот же объект (например, city1) необходимо повторно использовать. Обычно вы можете искать город в БД по имени и стране и использовать этот объект столько раз, сколько необходимо, назначив его каждому человеку. – Durandal

+0

Возможно, это не ответ на ваш вопрос, но указатель на дизайн базы данных: у вас действительно должно быть УНИКАЛЬНОЕ ограничение на ваши имена city_name и country_name. Это приведет к сбою ошибок, которые дублируют данные, а не оставляют их, чтобы, возможно, вызвать неясные сбои на более позднем этапе. – Jules

+0

Почему ограничение города? Использование разных экземпляров для одного и того же объекта в базе данных или сохранение нескольких записей и их сохранение не имеет никакого смысла, по крайней мере для меня. – Gamb

ответ

0

Создайте один объект City и присвойте тот же объект обоим объектам. Сначала вы захотите перенести этот объект City, чтобы ассоциация выполнялась с существующим объектом.

Здесь есть улов.

Поскольку вы присваиваете одинаковое значение для обоих Person случаях, каскад не должно быть на самом деле сделано, но City должен быть удален, если он будет сиротой после сбросив Person.

В вашем конкретном случае, поскольку вы имеете дело с городами, существующая таблица со многими городами может быть хорошим вариантом, позволяющим назначить ранее существующий город новому человеку, если вы хотите создать третью Person in Paris после удаления Peter и John.

0

Попробуйте это:

Person person1 = new Person("Peter"); 
Person person2 = new Person("John"); 

City city1 = new City("Paris", "France"); 

person1.setCity(city1);  
session.save(person1); 
person2.setCity(city1); 
session.save(person2); 
0

Может быть, у вас есть что-то другое в виду, но вот как бы я справиться с этим:

  1. Прежде всего, я бы поставил уникальный индекс по следующим направлениям (city_name, country_name)
  2. Конечно, я хотел бы сообщить Hibernate об этом уникальном индексе
  3. Вместо City city1 = new City("Paris", "France") Я бы

    //use session.createQuery or createCriteria here 
    City city = findByNameAndCountry("Paris", "France") 
    if (city == null){ 
        city = new City("Paris", "France"); 
        session.save(city) 
    } 
    
0

Лучше иметь city_name и COUNTRY_NAME в качестве первичного ключа. Поэтому в этой ситуации вы не можете вставить одно и то же значение в базу данных. как ..

City city1 = new City("Paris", "France"); 
City city2 = new City("Paris", "France"); 

Таким образом, вы должны иметь один объект города с одинаковыми значениями. Тогда это не будет повторяться.

Не забудьте переопределить hashCode() в соответствии с методом equals().

+0

Таблица лиц будет содержать как название города, так и страну, которая делает таблицу города бесполезной. –

0

Город является сущностью, и его равенство зависит от его идентичности. Пока вы связываете два разных города с двумя людьми, вы получите двух человек.

Чтобы избежать этого, вы должны создать только городской объект, если он не существует, и в противном случае использовать уже существующий.

Также проблема: что произойдет, если два города в одной стране имеют одно и то же имя? Они не будут одним и тем же городом, но будут иметь одну и ту же идентичность.

Смежные вопросы