Hibernate удалить на ребенка не работает, если есть другие дети - PullRequest
0 голосов
/ 24 мая 2018

есть сущность "адрес" и другая сущность "здание".По адресу может быть несколько зданий.

В building.java у меня есть адрес, определенный с помощью:

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ADDRESS_ID_REF")
public Address getAddress() {
    return this.address;
}

По адресу здание определяется как:

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "address")
public Set<Building> getBuildings() {
    return this.buildings;
}

При попытке сделать em.remove(building) он работает

  • нормально, когда есть только на здании по одному адресу
  • плохо, когда есть два здания по одному адресу

Плохой случай построен точно так же, как хороший случай плюс вставка второго здания в базу данных со ссылкой на тот же адрес.

  • вставка в значения адреса ('address123', [...]);
  • вставить в значения здания ('building234', 'address123', [...]);
  • вставить в значения здания ('building235', 'address123', [...]);

В плохом случае (hibernate не выполняет удаление) Я все еще могу удалить строку в базе данных (delete from building where building_id = '123'). Нет ошибок SQL в отношении ссылок.

В аналогичных темах я читал, что в этом случае обычно остаются ссылки, такие как hibernate правильно не может удалить эту сущность.

К сожалению, я также не получаю никакого вывода log4j из спящего режима, и никаких исключений не происходит.Так что я не знаю, в чем проблема hibernate в этом месте.

Мои log4j.properties отлично работают для моих регистраторов.Выходы записываются, как ожидается, в консоль.Но я не получаю никаких журналов Hibernate.Я прочитал в другой ветке, что этот регистратор должен дать мне несколько советов: org.hibernate.event.internal.DefaultPersistEventListener

log4j.rootLogger=TRACE, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

log4j.category.com.myproject.mypackage=INFO
log4j.category.com.myproject.mypackage.myclass=DEBUG

log4j.category.org.hibernate.event.internal.DefaultPersistEventListener=TRACE
log4j.category.org.hibernate=TRACE
log4j.category.org.springframework=TRACE

При установке в persistence.xml show_sql значения true, я получу SQL, записанные в консоль,Там я вижу, что удаление sql не выполняется.Но я не вижу никаких ошибок.

<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />

Как написано в большинстве случаев в других темах, похоже, остались некоторые ссылки, которые нужно было удалить в первую очередь.Но в моем случае моя сущность - это дочерний объект, а это значит, что я не ожидаю, что посторонние лица, обращающиеся к зданию, будут проблемой.Кроме того, я могу удалить строительный ряд непосредственно через SqlDeveloper.И при изменении моего кода с

em.remove(building)

на

em.remove(address)

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

Если вам нужна дополнительная информация, пожалуйста, попросите их.Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 24 мая 2018

Я не уверен, правильно ли это и задумано платформой, но я нашел решение / обходной путь:

Вместо того, чтобы только делать:

em.remove(b);

Я сейчас делаю:

Building b .... // current Object to be deleted
Address a = b.getAddress();
Set<Building> bSet = a.getBuildings();
bSet.remove(b);
em.remove(b);

Это отлично работает.Надеемся, что это действительно так.

Объяснение может быть таким: удаление дочерней сущности не обновляет список родительских дочерних объектов даже после завершения транзакционного метода (означает, что фиксация выполнена).

Я ожидал, что при удалении дочерней сущности и выполнении коммита эта сущность удаляется из базы данных.Когда затем в новой транзакции загружается родительская сущность, все ее дочерние права извлекаются из базы данных, следовательно, удаленная дочерняя сущность больше не указывается на родительской стороне.Может быть (хотя и при транзакционном выполнении) некоторые данные хранятся в кэше?

Как сказано в другом комментарии, только добавление orphanRemoval = true к cascadeAll-Line в Address-entity ничего не влияет.

0 голосов
/ 24 мая 2018

(Это был бы комментарий, но у меня недостаточно репутации) Чего вы пытаетесь достичь или лучше, что не работает?удаление здания не должно удалять адрес, поскольку в аннотации @ManyToOne нет опции каскада.если вы пытаетесь удалить здание, удаляя его из набора зданий, вам нужно использовать orphanRemoval = true в аннотации @OneToMany

РЕДАКТИРОВАТЬ (после прочтения комментария)

Самый простой способ будет следующим: добавьте orphanRemoval = true для сопоставления адресов @OneToMany.Чем

Building b .... // current Object to be deleted
b.getAddress().getBuildings().remove(b);
b.setAddress(null);
em.merge(a);

для этого фрагмента кода

b.getAddress().getBuildings().remove(b);
b.setAddress(null);

вы можете создать отдельный метод в объекте адреса, например

public void removeBuilding(Building b){
    buildings.remove(b);
    b.setAddress(null);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...