Пришло время продолжить статьи о Hibernate. Последний был посвящен однонаправленной ассоциации @OneToOne . Итак, сегодня я покажу вам, как получить двунаправленную связь первичного ключа @OneTonOne . Пример из этого урока основан на предыдущей статье. Давайте начнем.
Я буду работать с теми же таблицами, которые я создал ранее. Чтобы установить двунаправленную связь один к одному, мне нужно обновить два POJO и способ сохранения процесса. Давайте рассмотрим новую версию класса Author:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
import javax.persistence.*;@Entity@Table(name='authors')public class Author { @Id @GeneratedValue private Integer id; private String name; @OneToOne(mappedBy='author', cascade=CascadeType.ALL) private Biography biography; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Biography getBiography() { return biography; } public void setBiography(Biography biography) { this.biography = biography; }} |
Изменения минимальны. Я только что удалил @PrimaryKeyJoinColumn из поля биографии. В двунаправленном объединении появляется две стороны объединения — владеющая и обратная . Для двунаправленных отношений один к одному сторона-владелец соответствует стороне, которая содержит соответствующий внешний ключ. В нашем случае владельцем является класс Author. Вперед.
Цитата из спецификации JPA 2:
Обратная сторона двунаправленного отношения должна ссылаться на свою собственную сторону с помощью элемента mappedBy аннотации OneToOne, OneToMany или ManyToMany. Элемент mappedBy обозначает свойство или поле в объекте, который является владельцем отношения.
Обратной стороной в этом примере является класс Biography. Это требует более существенных изменений по сравнению с классом Author.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
import javax.persistence.*;import org.hibernate.annotations.GenericGenerator;import org.hibernate.annotations.Parameter;@Entity@Table(name='biographies')public class Biography { @Id @Column(name='author_id') @GeneratedValue(generator='gen') @GenericGenerator(name='gen', strategy='foreign', parameters=@Parameter(name='property', value='author')) private Integer authorId; private String information; @OneToOne @PrimaryKeyJoinColumn private Author author; public Author getAuthor() { return author; } public void setAuthor(Author author) { this.author = author; } public Integer getAuthorId() { return authorId; } public void setAuthorId(Integer authorId) { this.authorId = authorId; } public String getInformation() { return information; } public void setInformation(String information) { this.information = information; } } |
Первым важным моментом является оформление поля authorId дополнительными аннотациями.
|
1
2
3
4
5
|
...@GeneratedValue(generator='gen')@GenericGenerator(name='gen', strategy='foreign', parameters=@Parameter(name='property', value='author'))... |
В @GeneratedValue я указываю имя генератора («gen»), а в @GenericGenerator я определяю стратегию для генератора. Вторым важным моментом является добавление автора, зарегистрированного в классе, с соответствующими методами получения и установки.
|
1
2
3
4
5
|
... @OneToOne @PrimaryKeyJoinColumn private Author author;... |
Таким образом, мы получаем двунаправленную ассоциацию. Теперь мы можем получить доступ к автору из биографии и наоборот, поскольку оба объекта имеют ссылки друг на друга. Теперь процесс сохранения объектов должен быть обновлен:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
... public static void main(String[] args) { SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); Session session = sessionFactory.openSession(); session.beginTransaction(); Author author = new Author(); author.setName(' O. Henry'); Biography biography = new Biography(); biography.setInformation('William Sydney Porter better known as O. Henry...'); author.setBiography(biography); biography.setAuthor(author); session.save(author); session.getTransaction().commit(); session.close(); }... |
Обратите внимание, что теперь я не сохраняю свою сторону, пока не добавляю обратную сторону. Но вы можете видеть, что я установил биографию для автора, и в следующей строке я установил автора для биографии . Это основная цель двунаправленной ассоциации. Результат выполнения кода:
|
1
2
|
Hibernate: insert into authors (name) values (?)Hibernate: insert into biographies (information, author_id) values (?, ?) |
Ссылка: Двунаправленная ассоциация первичного ключа @OneToOne от нашего партнера по JCG Алекса Фрузенштейна в блоге заметок Фрузенштейна .