2014-10-16 2 views
0

Мое желаемое действие: Вставка строки в дочернюю таблицу автоматически добавляет строку в родительскую таблицу, если это необходимо, в противном случае используйте идентификатор существующей строки в родительской таблице в качестве внешнего ключа во вставленной строке в дочерней таблице.В Hibernate, как автоматически получить родительский идентификатор и использовать его при вставке ребенка в качестве внешнего ключа?

Мне интересно, есть ли способ сделать то, что упоминалось выше в спящем режиме, используя один оператор session.save(child).

Я использую Hibernate с Java и SQLite. Ниже приведены мои особенности БД и конфигурации:

Таблица Родитель:

{id (int): primary key, description (text): unique} 

Таблица детей:

{id(int): primary key, address (text), parent_id (integer): foreign key refers Parent(id)} [UNIQUE (address, parent_id)] 

POJO Родитель:

{int id, String description, Set<Child> children, [getters and setters] } 

POJO ребенка:

{int id, String address, Parent parent, [getters and setters]} 

Parent.hbm:

... 
<id column="id" name="id" type="long"> 
    <generator class="native"/> 
</id> 
<property column="description" name="description" type="string" unique="true" /> 
<set fetch="select" inverse="true" lazy="true" name="children" table="Child"> 
    <key> 
     <column name="parent_id" not-null="true"/> 
    </key> 
    <one-to-many class="Child"/> 
</set> 
... 

Child.hbm:

.... 
<id column="id" name="id" type="long"> 
    <generator class="native"/> 
</id> 
<property column="address" name="address" type="string"/> 
<many-to-one cascade="save-update" class="Parent" fetch="select" name="parent"> 
    <column name="parent_id" not-null="true"/> 
</many-to-one> 
... 

В настоящее время, родитель вставляется вместе с ребенком, если родитель (с тем же 'описание') не существует , В противном случае дочерний элемент не вставлен, поскольку родительская вставка не выполняется из-за уникального требования «описание».

Поскольку я не знаю идентификатора родителя при вставке ребенка (я знаю только описание родителя), я не могу сделать session.load (Parent.class, parentId) для извлечения родительского объекта и использования он должен вставить ребенка. То, что я делаю сейчас следующее:

Parent parent = new Parent(); 
parent.setDescription("D1"); 

Child child = new Child(); 
child.setAddress("A1"); 

parent.getChildren().add(child); 
child.setParent(parent); 
session.save(child); 

Я знаю, что всегда могу посмотреть родительский идентификатор первого, выполнив запрос select id from Parent where description="D1", а затем, если ResultSet пуст, спасти ребенка, как я это делаю сейчас (который также вставляет родительский элемент), и если результат не пуст, используйте session.load() для загрузки родительского объекта и его использования для вставки дочернего элемента. Но я думал, что спящий режим может справиться с этим для меня за одним session.save(child). Может это?

+0

Я having такой же выпуск. Удалось ли вам найти решение? – Maz

ответ

0

Попробуйте эти шаги;

1.Change ваш Parent.hbm

... 
<id column="id" name="id" type="long"> 
    <generator class="native"/> 
</id> 
<property column="description" name="description" type="string" unique="true" /> 
<set fetch="select" inverse="true" lazy="true" name="children" table="Child" cascade="save-update"> 
    <key> 
     <column name="parent_id" not-null="true"/> 
    </key> 
    <one-to-many class="Child"/> 
</set> 
... 

2.Изменение ваш Child.hbm

.... 
<id column="id" name="id" type="long"> 
    <generator class="native"/> 
</id> 
<property column="address" name="address" type="string"/> 
<many-to-one class="Parent" fetch="select" name="parent"> 
    <column name="parent_id" not-null="true"/> 
</many-to-one> 
... 

3.And добавить ребенка до того родителя, как вы хотите

Parent parent = new Parent(); 
parent.setDescription("D1"); 

Child child = new Child(); 
child.setAddress("A1"); 
child.setParent(parent); 

session.save(child); 
Set<Child> childsSet = new HashSet<Child>(); 
childsSet.add(child); 

parent.setChildren(childsSet); 
session.save(parent); 
+0

Работает, когда в родительском списке нет строки с описанием, но она не выполняется при последующей вставке ребенка (с другим адресом), связанного с родителем с тем же описанием (требуется уникальное описание столбца).Последний случай является более распространенным сценарием в моем приложении, где дети будут вставлены с уже существующим родителем, но иногда он может иметь родителя, который еще не существует в db, в этом случае родительский элемент также должен быть вставлен. Я хочу, чтобы логика приложения не могла знать эти случаи, используя один 'session.save (child)' (или 'session.save (parent)') – Tarik