2009-08-06 1 views
1

Вот моя ситуация: я загружаю объект, содержащий двунаправленные родительские отношения с дочерними элементами в мою базу данных. Позже этот объект загружается в мой пользовательский интерфейс, где могут быть сделаны изменения, в том числе удаление любого числа дочерних элементов из дочернего набора. Затем эта модифицированная копия моего объекта загружается с использованием метода saveOrUpdate. Однако, когда эта измененная копия сохраняется, все удаленные дети остаются в базе данных (новые дети, добавленные в набор, отлично работают). Во время этого процесса ошибок не возникает, но мне нужны эти удаленные дочерние элементы для фактического удаления из базы данных. Я вставил соответствующие части моего спящего и java-кода ниже.Hibernate не может удалить ребенка из базы данных

Родитель зимуют конфигурации:

<bag name="specimenTypes" table="masterPkSpecimenType" cascade="all-delete-orphan" inverse="true"> 
    <key column="runid"/> 
    <one-to-many class="SpecimenType"/> 
</bag> 

ребенка в спящий режим конфигурации:

<many-to-one name="reportCriteriaBean" class="ReportCriteriaBean" column="runid" not-null="true" /> 

Код объекта Родитель:

public List<SpecimenType> getSpecimenTypes() { 
    return specimenTypes; 
} 

public void setSpecimenTypes(List<SpecimenType> specimenTypes) { 
    this.specimenTypes = specimenTypes; 
    if(this.specimenTypes != null){ 
     for(SpecimenType specType : this.specimenTypes){ 
      specType.setReportCriteriaBean(this); 
     } 
    } 
} 

Код объекта Ребенок:

public ReportCriteriaBean getReportCriteriaBean() { 
    return reportCriteriaBean; 
} 
public void setReportCriteriaBean(ReportCriteriaBean reportCriteriaBean) { 
    this.reportCriteriaBean = reportCriteriaBean; 
} 

EDIT:

Видимо моя проблема связана с явным вызовом setSpecimenTypes() после того, как я получить родительский объект из БД, и, прежде чем я сохранить обновленный объект обратно. причина, по которой я это делаю, заключается в том, что из-за некоторого динамического связывания списков мне нужен Список, который должен быть конкретной реализацией List (в частности, LazyList от Apache), когда он представлен в пользовательском интерфейсе. Однако, когда объект извлекается из БД, он не реализован таким образом, поэтому я создаю копию LazyList обычного списка, который был вытащен из базы данных, и вызвал setSpecimenTypes(), чтобы заменить его на мой недавно заполненный LazyList. Кто-нибудь знает, как мне это сделать?

ответ

0

Ваше сопоставление выглядит правильно. Как вы удаляете детей? Что-то похоже на getSpecimenTypes().remove(X) или у вас есть специальный метод для этого (если да, можете ли вы его опубликовать)?

Кроме того, когда ваш родительский объект переносится на слой пользовательского интерфейса и обратно - это делается в пределах того же сеанса? Вы уверены, что никто не сбрасывает детскую коллекцию, вызывая setSpecimenTypes() где-то посередине?

Update (на основе разъяснений):

Сброс specimenTypes, безусловно, проблема. Как Hibernate знает, что вы удалили определенный элемент? Удаления отслеживаются в собственном PersistentList Hibernate, который переносит ваш список при загрузке родительского объекта.

LazyList (я предполагаю, что вы имеете в виду, что из Commons Collections) является декоратором, поэтому вы можете создать еще один метод getter в своем родительском объекте, который обернет вашу коллекцию specimenTypes в LazyList и вернет ее (кэширование в члене переменная для эффективности при повторных попытках доступа).

Суть в том, что вы не должны переписывать коллекцию, управляемую Hibernate, своей собственной версией.

+0

Я вызываю setSpecimenTypes(), прежде чем обновлять объект (по причинам, которые я изложил в обновлении моего сообщения), я не понимаю, почему это имеет значение. Не следует ли обновлять список дочерних элементов, чтобы отражать то, что содержит текущий набор дочерних элементов, тем самым удаляя записи старых дочерних элементов? – TimmyJ

+0

Спасибо за помощь. У меня все еще есть проблема.Когда я сменил геттер, чтобы вернуть украшенный список, я получаю следующую ошибку, когда родительский класс извлекается из БД: Коллекция с cascade = "all-delete-orphan" больше не ссылалась на экземпляр объекта-владельца. Я уверен, что setSpecimenTypes никогда не вызывается (я зашел так далеко, чтобы сделать его закрытым). Вы упомянули выше, что я должен создать * другой * getter, а не заменить текущий, как я. Есть ли причина, по которой мой путь был бы неправильным? – TimmyJ

+0

Проблема с возвратом украшенного списка из существующего геттера заключается в том, что он больше не является Hibernate PersistentList. Hibernate не знает, что вы его завернули (или как развернуть) - он просто видит, что PersistentList, который был там, теперь ушел - отсюда исключение. Вам действительно нужен другой getter, но если ваш код зависит от 'getSpecimenTypes()', вы можете сделать private 'getSpecimentTypesDB()' и отобразить его в Hibernate. Я лично предпочитаю украшать компоненты пользовательского интерфейса, а не бизнес-объекты, но каждый из них имеет свое место. – ChssPly76

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