SPRING-SOURCE.RU

Ассоциация один-ко-многим

Отображение ассоциации многие-к-одному

Spring OneToMany ManyToOne

Связь однонаправлена.

Пример: есть Item (продукт, например) и у него есть Bid (ставка). Каждая ставка содержит ссылку на свой продукт: ставка на продукт.

Как такая связь отображается в JPA? Со стороны Item делать ничего не нужно, так как в нем нет ссылок на Bid-ы. В классе Bid будет присутствовать ссылка на Item. Получается, что над свойством класса Bid мы ставим аннотацию @ManyToOne. По сути, создатся таблица Bid и в ней будет стоять Foreign key на item.

Примечание: Внешний ключ (англ. foreign key) - понятие теории реляционных баз данных. Внешним ключом называется поле таблицы, предназначенное для хранения значения первичного ключа другой таблицы с целью организации связи между этими таблицами.

Под аннотацией @ManyToOne может стоять аннотация @JoinColumn(name="ITEM_ID"). Если @ JoinColumn не указать, то имя foreign key (колонка) будет состоять из имени переменной над которой стоит аннотация и имени первичного ключа базы на котороую эта переменная ссылается.

Переходим к двунаправленной связи.

Двунаправленная ассоциация один-ко-многим

Spring OneToMany ManyToOne

Здесь в Item есть ссылка на Bid и в Bid есть ссылка на Item. В этом случае Bid оставляем таким же как и в связи рассмотренной ранее. Но в Item мы должны создать коллекцию Bid-ов (либо Set, либо Collection, List) и над ней поставить аннотацию @OneToMany(mappedBy="item", cascade = CascadeType.ALL). В mappedBy указывается имя того поля которое ссылается с другой стороны, со стороны Bid-а, в нашем случае. Почему так? Hibernate, как и другая ORM реализация, не понимают двунаправленной связи. Для них все связи однонаправлены. Hibernate понимает это как две связи, одна идет к полю item класса Bid, а другая от поля item класса Bid к первичному ключу (полю) id класса Item.

Если мы делаем двунаправленные связи, то двунаправленностю нам нужно управлять самим. То есть мы должны создать какой-нибудь дополнительный метод (addBid(Bid bid) в котором установим bid.setItem(this) - метод класса Bid, bids.add(bid) - поле класса Item. Это и есть двунаправленная связь. Для поддержки двунаправленности предоставляется mappedBy (в Hibernate это inverse = true). Что этот атрибует позволяет делать? Он говорит, что для этой связи (OneToMany) у нас есть еще и обратная связь. То есть мы говорим, что другая связь тоже существует и Hibernate после этого начнет оптимизировать запросы.

Если mappedBy не указывать,то Hibernate при сохранении объектов сначала сохранит один объект, а потом тут же второй, то есть два раза выпониться команда INSERT. Если поставить это свойство, то foreign key не будет устанавливаться два раза.

Из всего этого важно подчеркнуть, что списками нужно управлять самим и если связь двунаправленная, то всегда используем mappedBy. Если мы хотим получит коллекцию Bid-ов, то делаем запрос к базе и получаем его.

Свойство CascadeType.ALL (есть еще INSTERT, UPDATE, DELETE, ALL включает в себя все три каскада). Это означает каскадное обновление записей в базе данных.
CascadeType.INSERT - ознчает, что когда мы сохраняем объект Item, автоматически сохраняться все Bid-ы, которые мы в него добавили. Здесь получается, что мы делаем отдельного сохранения для Bid-ов и для Item-ов.
CascadeType.UPDATE - обновили объект Item и по каскаду обнавляются все его Bid-ы или что-то изменили в Bid-е, то это опять по каскаду будет обновляться.
CascadeType.DELETE - если удаляем Item, то из базы удаляются все его Bid-ы.