| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Java EE (J2EE) и Spring > Hibernate. Annotations. CascadeType |
| Автор: garbuz 13.7.2009, 22:16 | ||||||||
| Использую Hibernate + Annotations. Запутался с cascadeType. Есть к примеру связь Many-to-One
Правильно ли я указал cascadeType? Я что-то не совсем догнал, что каждый из них значит. Будет ли при удалении юзера удаляться все его ордеры? Если не сложно, может кто в двух словах объяснит, что значит каждый cascade type? И еще один вопрос. Имеется класс Message, в нем есть два поля типа User - fromUser и toUser
У класса User есть коллекция мессджей, которые должны делиться на входящие и исходящие.
Как правильно указать mappedBy? На что замапить? Сейчас я просто через запятую написал fromUser, toUser, но уверен, что это не сработает. Да, и как тут с cascadeType? При удалении пользователя будут удаляться все его сообщения или нет? |
| Автор: MisterCleric 13.7.2009, 23:16 | ||
Про mappedBy точно могу сказть, что надо тебе две коллекции: входящие и исходящие.
Вот это не понятно: а как ты разюираешь от "кого" и "кому", если у тебя всего лишь один форинг кей - userId Вот о cascadeType и я бы послушал, так как у меня тоже такие траблы есть. Мое предыдущее сообщение. Ну если в общих чертах как я понял. То какскад нужен, если у тебя большая вложенность сущностей. Для твоего примера будет где-то так: У юзера есть мессажды, у месаждей есть файлы. И вот ты добавил несколько файлов к мессажду, а несколько удалил. А merge вызвал на юзере. Вот ты и увидешь несколько селектов, несколько инсертов, а по остальным делиты. Про DELETE FROM, конечно молчу, так получил с этим проблемы... |
| Автор: garbuz 15.7.2009, 12:38 | ||||||||
| Сделал две коллекции. User.java
Message.java
Хтбернейт ругается
Если сделать, как предлагается, т.е.
То все заводится, но смущают меня эти значения insertable = false, updatable = false Это типа значит, что значение этому полю мне не присвоить и не обновить? |
| Автор: MisterCleric 15.7.2009, 12:54 | ||
я же тебе говорил, что логика не верна: как ты понимаешь от "кого" "кому", если у тебя только один форинг кей на юзера? Нужно два. Поясни логику этих вот мессаджей. Как я понял, кто-то отправляет кому-то мессадж. Знач мессадж должен знать об этом. А у тебя всего один userId |
| Автор: garbuz 15.7.2009, 13:03 |
| Кто-то отправляет кому-то мессадж, типа как ты в личку пишешь мне, а я тебе Я что-то сам запутался с форинг ключами. В таблице messages два форинг ключа, только ссылаются они на один и тот же первичный ключ таблицы users. Как правильно сделать? http://ipicture.ru/ |
| Автор: MisterCleric 15.7.2009, 13:44 | ||
| все правильно. Ничего смертельного, что у тебя два форинг кея ссылаются на один. У меня есть такое в пиложении: Банк имеет форинг кей сам на себя, так как банк может филиалом и, естественно, у него есть главным банк Есть документ заведенный в определенном банке(а может и филиале), а также в этом документе есть форинг кей на главный банк. т.е. где-то так
и все отлично работает |
| Автор: garbuz 15.7.2009, 13:58 | ||
Вот что сгенерила моя тулза, где я БД рисовал
Что не так? |
| Автор: MisterCleric 15.7.2009, 14:00 | ||
| Правильно тулза сделала. у тебя мепинг неверный:
обратить внимание на userId в тексте! |
| Автор: garbuz 15.7.2009, 14:17 |
| MisterCleric, я видимо чего-то не понимаю, раз мне ошибку не увидеть. Если можешь, объясни пожалуйста. |
| Автор: MisterCleric 15.7.2009, 14:47 |
| Может и я что-то не понимаю. Но как мне кажеться: 1. Ты пишешь, что у тебя есть в таблице messages две колонки: toUserId, fromUserId 2. Ты меппишь сущность Message на эту таблицу. Но при этом не меппишь эти колонки. 3. Ты все указал правильно в @ManyToOne, но только у каждого User в аннотации @JoinColumn должен быть указан не примари кей юзера, а его соответствующий форин кей из таблицы messages |
| Автор: garbuz 15.7.2009, 14:58 | ||
MisterCleric,
|
| Автор: garbuz 16.7.2009, 15:32 | ||||||||||
| Едем дальше. Опять непонятки у меня с каскадностью. Есть юнит тест.
Вот что выводит консоль
Как видно из лога, хибернейт удаляет application
Однако, если после удаления, мы у категории проитерируем коллекцию приложений, то мы все равно увидим размер коллеции 3, хотя должно быть 2 Вот маппинг у классов Category.java
Application.java
|
| Автор: garbuz 16.7.2009, 16:11 | ||||
Если удалять не так
А вот так
Тогда все нормально. Ерунда какая-то получается. Т.е. если мы у родительской коллекции удаляем елемент, то он удаляется, а если удаляем сам отдельно элемент, то он остается. Странно. |
| Автор: MisterCleric 20.7.2009, 14:51 | ||||
| Привет еще раз. Тут ситуация в том, что в Persistence есть такое понятие как managed & detached. Т.е. сущности, которые поцулены из базы и находятся сейчас в памяти - PersistenceContext (еще его называют кешем первого уровня). detached - те сущности, которые созданы в этом PersistenceContext, но еще не лежат в базе(а может и лежат, но PersistenceContext еще об этом не знает). Так вот. согласно твоему примеру. У тебя не то что, может а как раз так и есть, что сущность Category заменеджена и имеет у себя внутри коллекцию applications один из элементов которой как раз и есть тот объект, который ты хочешь грохнуть. Ты ему говоришь куском кода:
удали-ка такой-то объект из базы и PersistenceContext. Он так и сделает, но ссылка на него в коллекции-то останется... Ты же тут не сказал что ее надо убрать и из коллекции. А вот второй кусок:
Работает правильно, так как эта коллекция есть запроксированная PesistanceSet, т.е. все изменения в этой коллекции будут отделегированы PersistenceContext для выполнения соответствующих изменений: CRUD-операций. Делаем выводы: первый кусок тоже отработает. Но надо или в отдельной транзакции его удалять, а уже потом заправшивать в другой транзакции родительскую сущность. Или надо руками из коллекции удалить, а потом вызвать удаление из базы. вроде так... |
| Автор: garbuz 27.7.2009, 00:50 | ||||||
| MisterCleric, после нескольких перечитываний разобрался, в том, что ты хотел до меня донести - недельный отдых дает о себе знать, мозг еще не включился Итак по делу. А допустим у меня есть несколько сущностей, который содержат коллекцию пользователей. Хочу я удалить одного пользователя из базы. Мне придется сперва из всех этих коллекций удалить пользователя, а потом уже удалить его из базы? Ерунда какая-то получается. MisterCleric, что скажешь про orphan deletion? Я что-то почитал, но если честно что-то не очень понял. Встает такой вопрос. Если столько проблем с этими коллекциями, удалением элементов etc. Надо ли вообще эти коллекции? В чем удобство?
Сразу отпадает проблема с ленивыми коллекциями и удалением элементов. Удалил
И нигде больше не вылезет этот application. Или я не прав? Короче я запутался |
| Автор: MisterCleric 27.7.2009, 10:41 | ||
| Привет. Слушай, давай ты почитаешь http://www.google.com.ua/search?q=manning+java+persistence+with+hibernate&btnG=Search страница 273. А потом попытаемся разобраться. Вряд ли я смогу своими словами более толково объяснить, чем там написано. Все ты рассуждаешь правильно. И про коллекции и про ленивость, но у меня одно замечание: Зачем так наворачивать в одном PersistenceContext такую логику, что у тебя будет куча сущностей с коллекциями OneToMany да еще так, что придется убивать одну из сущностей, что может быть в этих коллекциях? Последний твой пример абсолютно верный: но он естественно, будет работать верно, если ты ленивую коллекцию позовешь после удаления. Да еще, по-моему, придется перед вызовом ленивой коллекции или сразу после удаления вызвать
для насильного вызова всех предыдущих перзистенс-операций. Так как INSERT/DELETE/UPDATE по-умолчанию планируются для вызова при коммите транзакции. |
| Автор: garbuz 27.7.2009, 16:14 | ||||||||||
Ну видимо логика не очень удачная получилась. Есть много ленивых коллекции. Категория - приложения, пользователь - заявки, пользователь - сообщения etс. У некоторых сущностей получается по несколько коллекций. Все и правда получется как-то слишком наворочено. Вот я и думаю, может вообще отказаться от них.
Ну наверно так и буду делать.
Получится, что ассоциации у меня будут не bidirectional, а undirectional. Цитата из книги
|
| Автор: MisterCleric 27.7.2009, 16:34 | ||||
Может с логикой и все нормально. Бывает же такое как тернарное соединение и иногда без него никуда, особенно, если надо писать приложение на уже готовую базу. Проблема здесь заключается в том, как много сущностей и их связок ты пытаешься использовать в одном PersistenceContext, может надо подумать о чем-то дискретном: одна бизнес-операция с транзакцией и PersistenceContext, а в ней немного кода использующего базу на все вот эти связки, что ты назвал. Врядли при работе с категориями тебе придеться работать с сообщениями пользователей.
Не всегда это плохо. У меня тут по каскадному удалению была тема. И как раз bidirectional выручил |
| Автор: garbuz 27.7.2009, 17:37 |
| Да, чувствуется, что не хватает теоритических знаний :( Насколько я понимаю, PersistenceContext - это область памяти, где хранятся мои объекты в рамках одной транзакциb или сессии. Верно? Если так, то естественно в одном контексте не будет использоваться так много сущностей. Я понял, что ты хотел сказать. Ладно, вечером попробую поэксперементировать с тестами. Еще отпишу чего-нить |
| Автор: MisterCleric 27.7.2009, 17:50 | ||
Да ты знаешь: не всегда. У меня получилась такая логика в приложении, что уже не рад: банк, программы страхования, группы рисков, тарифы, опросники, ответы на опросы, полис, физ. лицо. И иногда получалось такое несуразное, что мама не горюй: так оно не укладывалось в голове. В одной транзакции удалял ответ из коллекции - было все ОК(Это логика анкеты). В другой транзакции по логике "невидимых вопрос" вызвал тот же метод удаления ответа из коллекции получил эксепшн, что-то типа in detached state. В общем надо как-то приводить логику своего приложения к какому-то нормализованному виду, как это делается в базе введение примари кеев одним полем. Но на это все надо времени, естественно... |