Топ-100Двусторонняя связь между сущностями в Hibernate - CodOrbits
LogoCodOrbits

Раздел: Hibernate

Познакомьтесь с Hibernate — ORM-фреймворком Java для удобной работы с базами данных через объекты.

Все разделы
Иконка Hibernate

Двусторонняя связь между сущностями в Hibernate

Last updated: 11 мая 2025 г.

Связь между объектами таблиц была односторонняя, то есть через объект Author удалялся из БД или сохранялся в БД связанный объект AuthorInfo.

Теперь сделаем наоборот. Так, чтобы через объект AuthorInfo производились какие-то действия в БД со связанным объектом Author.

Теперь уже будет двухсторонняя связь. То есть мы, например, можем совершить выборку из базы с помощью метода get объекта AuthorInfo, и при этом автоматически будет получен из базы связанный с ним объект Author.

Для двусторонней связности объектов связанных строк, необходимо изменить класс AuthorInfo.

1package HibernateApps;
2
3import javax.persistence.CascadeType;
4import javax.persistence.Entity;
5import javax.persistence.GeneratedValue;
6import javax.persistence.GenerationType;
7import javax.persistence.Id;
8import javax.persistence.Column;
9import javax.persistence.OneToOne;
10import javax.persistence.Table;
11
12// Это класс с таблицы author_info.
13@Entity
14@Table(name = "author_info")
15public class AuthorInfo {
16
17    @Id
18    @GeneratedValue(
19        strategy = GenerationType.IDENTITY
20    )
21    @Column(name = "id")
22    private int id;
23
24    @Column(name = "books_written_number")
25    private int booksWritten;
26
27    @Column(name = "country")
28    private String country;
29
30    // Для двусторонней связанности указываем
31    // в mappedBy каким полем класс Author
32    // связан с данным классом AuthorInfo.
33    @OneToOne(mappedBy = "authorInfo",
34            cascade = CascadeType.ALL)
35    private Author author;
36
37    public AuthorInfo() {
38    }
39
40    public AuthorInfo(int booksWritten,
41                      String country) {
42        this.booksWritten = booksWritten;
43        this.country = country;
44    }
45
46    public int getId() {
47        return id;
48    }
49
50    public void setId(int id) {
51        this.id = id;
52    }
53
54    public int getBooksWritten() {
55        return booksWritten;
56    }
57
58    public void setBooksWritten(
59            int booksWritten) {
60        this.booksWritten = booksWritten;
61    }
62
63    public String getCountry() {
64        return country;
65    }
66
67    public void setCountry(String country) {
68        this.country = country;
69    }
70
71    public Author getAuthor() {
72        return author;
73    }
74
75    public void setAuthor(Author author) {
76        this.author = author;
77        // В прошлом уроке мы передавали
78        // объект AuthorInfo в сеттер
79        // объекта Author для того чтобы эти
80        // объекты были связаны как связаны
81        // строки этих объектов в БД.
82        // Чтобы можно было так связать
83        // эти объекты наоборот, то есть
84        // в сеттер объекта Author
85        // передать объект Author,
86        // нужно еще и передать
87        // текущий(this) объект AuthorInfo
88        // объекту Author потому что если
89        // этого не сделать то объект Author
90        // не будет знать ничего
91        // о объекте AuthorInfo.
92
93        // Уточним что класс, в котором
94        // mappedBy не связан с тем, в котором
95        // JoinColumn напрямую. Связанным напрямую 
96        // с другим классом можно назвать класс, 
97        // в котором JoinColumn. Поэтому обратную
98        // связанность мы скорее имитируем
99        // использованием mappedBy
100        // и конструкциями типа
101        // author.setAuthorInfo(this);
102        author.setAuthorInfo(this);
103    }
104
105    @Override
106    public String toString() {
107        return "AuthorInfo [id=" + id + ", "
108                + "booksWritten="
109                + booksWritten + ", country="
110                + country + ", author="
111                + author + "]";
112    }
113}

Теперь давайте создадим два объекта, свяжем их теперь уже используя сеттер объекта AuthorInfo и добавим их в БД.

1package HibernateApps;
2
3import org.hibernate.Session;
4import org.hibernate.SessionFactory;
5import org.hibernate.cfg.Configuration;
6
7public class HibernateApp {
8
9    public static void main(String[] args) {
10
11        // create session factory
12        SessionFactory factory = new Configuration()
13                                    .configure("hibernate.cfg.xml")
14                                    .addAnnotatedClass(Author.class)
15                                    .addAnnotatedClass(AuthorInfo.class)
16                                    .addAnnotatedClass(AuthorBooks.class)
17                                    .buildSessionFactory();
18
19        // create session
20        Session session = factory.getCurrentSession();
21
22        try {
23
24            session.beginTransaction();
25
26            //создадим два объекта и свяжем их
27            //только через сеттер объекта
28            //authorInfo, а не author как
29            //в прошлых уроках
30
31            AuthorInfo authorInfo = new AuthorInfo(10, "Great Britain");
32            Author author = new Author("JJ Rowling");
33
34            //связываем
35            authorInfo.setAuthor(author);
36
37            //при сохранении authorInfo сохраниться
38            //в базу и author поскольку они связаны
39
40            session.save(authorInfo);
41
42            AuthorInfo authorInfo1 = session.get(AuthorInfo.class, 1);
43            System.out.println(authorInfo1);
44
45            //строкой ниже удаляться связанные строки
46            //таблиц через связанные объекты этих строк.
47            session.delete(authorInfo1);
48
49            AuthorInfo authorInfo2 = session.get(AuthorInfo.class, 1);
50            System.out.println(authorInfo2);
51
52            session.getTransaction().commit();
53
54        }
55        catch (Exception e){
56            session.getTransaction().rollback();
57            e.printStackTrace();
58        }
59
60        finally {
61            session.close();
62        }
63
64    }
65}

Давайте запустим нашу программу.

Как видим, произошло два запроса на вставку, хотя метод save мы вызывали только над одним объектом actorinfo. Это доказывает, что каскадная PERSIST операция сработала и произошел insert не только объекта authorinfo в таблицу author_info, а и связанного с ним объекта author в таблицу author. То есть двусторонняя связь работает.

Далее с помощью get мы выбрали из таблицы author_info только что положенную туда строку и поместили ее в объект authorinfo1, в консоли можно увидеть содержимое объекта authorinfo1, и как видим он, содержит объект author, то есть опять таки, для выборки связь тоже работает.

После удаления из базы связанных объектов на консоль вывелось null, значит объекты успешно удалились из базы.

Проверим на всякий случай и базу удалились ли обе строки в таблицах:


Следующие уроки

Настройка связи Один-ко-Многим в Hibernate

20
мин.

Similar Articles Icon
Divider

Типы извлечения данных в Hibernate (fetch types)

19
мин.

Similar Articles Icon
Divider

Настройка связи Многие-ко-Многим в Hibernate приложении

20
мин.

Similar Articles Icon