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

Раздел: Hibernate

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

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

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

Last updated: 11 мая 2025 г.

Теперь настроим в нашем приложении связь Многие-ко-Многим.

Пусть теперь в нашем приложении будет еще одна новая таблица – "Издательство".

Эта таблица будет связана с ранее созданной таблицей "Книги автора".

Любая книжка может быть напечатана несколькими издательствами и любое издательство может печатать какие-угодно книги.

То есть связь многие книги ко многим издательствам.

Ясное дело, при удалении издательства из таблицы publisher не должны удаляться связанные с этим издательством книги в таблице author_books, поскольку эти книги могут быть связаны и с другими издательствами.

И наоборот тоже – удаление книги не должно приводить к удалению связанных с ней издательств.

Поэтому и в классе таблицы publisher и в классе таблицы author_books необходимо исключить CascadeType=REMOVE.

Сделаем это.

Создадим теперь с помощью sql запроса таблицу publisher в которой будут храниться издательства.

Кто знает базы данных должен знать, что связь многие ко многим между двумя таблицами реализуется с помощью промежуточной таблицы, где есть два столбца – id издательства и id книги. Создадим эту таблицу.

Теперь создадим класс созданной только что таблицы publisher. И настроим связь Многие-ко-Многим между этим классом и классом AuthorBooks через промежуточную таблицу.

1package HibernateApps;
2
3import java.util.ArrayList;
4
5import javax.persistence.*;
6
7@Entity
8@Table(name = "publisher")
9public class Publisher {
10
11    @Id
12    @GeneratedValue(strategy=GenerationType.IDENTITY)
13    @Column(name="id")
14    private int id;
15
16    @Column(name="name")
17    private String publisherName;
18
19    //Теперь используем аннотацию
20    //@ManyToMany (Многие-ко-многим).
21    //многие Publisher ко многим AuthorBooks.
22    //Важно убрать CascadeType.REMOVE чтобы
23    //при удалении из БД какой-то из книги
24    //не удалялись из БД издательства
25    @ManyToMany(cascade = {CascadeType.DETACH,
26                           CascadeType.REFRESH,
27                           CascadeType.PERSIST,
28                           CascadeType.MERGE})
29    //Теперь настраиваем связи таблицы publisher
30    //с таблицей author_books через промежуточную
31    //таблицу author_books_publisher.
32    @JoinTable(
33               Имя промежуточной таблицы.
34               name = "authours_books_publisher",
35               //Указываем название атрибута
36               //промежуточной таблицы в котором
37               //хранятся идентификаторы строк
38               //из таблицы publisher.
39               joinColumns=@JoinColumn(name="publisher_id"),
40               //Указываем название атрибута
41               //промежуточной таблицы в котором
42               //хранятся идентификаторы строк
43               //из таблицы author_books.
44               inverseJoinColumns=@JoinColumn(name="authorbook_id"))
45    private List<AuthorBooks> authorbook;
46
47
48    public Publisher() {
49    }
50
51    public Publisher(String publisherName) {
52        this.publisherName = publisherName;
53    }
54
55    public int getId() {
56        return id;
57    }
58
59    public void setId(int id) {
60        this.id = id;
61    }
62
63    public String getPublisherName() {
64        return publisherName;
65    }
66
67    public void setPublisherName(
68            String publisherName) {
69        this.publisherName = publisherName;
70    }
71
72    public List<AuthorBooks> getAuthorbook() {
73        return authorbook;
74    }
75
76    public void setAuthorbook(
77            List<AuthorBooks> authorbook) {
78        this.authorbook = authorbook;
79    }
80
81    //Для связывания объекта книги
82    //с объектом издательства просто
83    //добавляем объект книги в List
84    //объекта издательства. Тогда при
85    //добавлении в БД издательства, через
86    //объект издательства добавляются в БД
87    //и книги находящиеся в List
88    //в этом объекте издательства.
89    public void setOneBook(
90            AuthorBooks authorbook){
91        if (this.authorbook==null) {
92            this.authorbook = new ArrayList<>();
93        }
94        this.authorbook.add(authorbook);
95    }
96
97
98    @Override
99    public String toString() {
100        return "Publisher [id=" + id
101                + ", publisherName="
102                + publisherName
103                + ", authorbook="
104                + authorbook + "]";
105    }
106}

Теперь в классе таблицы author_books настроим связь Многие-ко-Многим между этим классом и классом Publisher также через промежуточную таблицу.

Связь настраивается таким же образом как и в классе Publisher, только меняем местами publisher_id и authorbook_id

1package HibernateApps;
2
3import java.util.ArrayList;
4import java.util.List;
5
6import javax.persistence.CascadeType;
7import javax.persistence.Column;
8import javax.persistence.Entity;
9import javax.persistence.GeneratedValue;
10import javax.persistence.GenerationType;
11import javax.persistence.Id;
12import javax.persistence.JoinColumn;
13import javax.persistence.JoinTable;
14import javax.persistence.ManyToMany;
15import javax.persistence.ManyToOne;
16import javax.persistence.Table;
17
18
19@Entity
20@Table(name = "author_books")
21public class AuthorBooks {
22
23    @Id
24    @GeneratedValue(
25            strategy=GenerationType.IDENTITY
26    )
27    @Column(name="id")
28    private int id;
29
30    @Column(name="name")
31    private String bookName;
32
33    @ManyToOne(cascade ={CascadeType.DETACH,
34                         CascadeType.REFRESH,
35                         CascadeType.PERSIST,
36                         CascadeType.MERGE})
37    @JoinColumn(name="author_id")
38    private Author author;
39
40    //Также используем аннотацию
41    //@ManyToMany (Многие-ко-Многим).
42    //Многие AuthorBooks ко многим Publisher.
43    //Важно убрать CascadeType.REMOVE чтобы
44    //при удалении из БД какого-то из издательств
45    //не удалялись из БД книги напечатанные им.
46    @ManyToMany(cascade ={CascadeType.DETACH,
47                         CascadeType.REFRESH,
48                         CascadeType.PERSIST,
49                         CascadeType.MERGE})
50    @JoinTable(name="authorbooks_publisher",
51               //Связь с таблицей publisher
52               //через промежуточную таблицу
53               //в этом классе настраиваем также
54               //как и в классе Publisher только
55               //как можно увидеть ниже
56               //в joinColumns теперь authorbook_id,
57               //а в inverseJoinColumns
58               //теперь publisher_id.
59               joinColumns=
60                   @JoinColumn(name="authorbook_id"),
61               inverseJoinColumns=
62                   @JoinColumn(name="publisher_id"))
63    private List<Publisher> publisher;
64
65
66    public AuthorBooks () {
67    }
68
69    public AuthorBooks(String bookName) {
70        this.bookName = bookName;
71    }
72
73
74    public int getId() {
75        return id;
76    }
77
78    public void setId(int id) {
79        this.id = id;
80    }
81
82    public String getBookName() {
83        return bookName;
84    }
85
86    public void setBookName(String bookName) {
87        this.bookName = bookName;
88    }
89
90    public Author getAuthor() {
91        return author;
92    }
93
94    public void setAuthor(Author author) {
95        this.author = author;
96    }
97
98    @Override
99    public String toString() {
100        return "Book [id="
101               + id + ", bookName="
102               + bookName + "]";
103    }
104}

Пример программы со связью Многие-ко-Многим:

1package HibernateApps;
2
3import org.hibernate.Session;
4import org.hibernate.SessionFactory;
5import org.hibernate.cfg.Configuration;
6
7public class HibernateApp {
8    public static void main(String[] args) {
9        //Добавим Publisher в sessionfactory
10        SessionFactory sessionFactory = new Configuration()
11                .configure("hibernate.cfg.xml")
12                .addAnnotatedClass(Author.class)
13                .addAnnotatedClass(AuthorInfo.class)
14                .addAnnotatedClass(AuthorBooks.class)
15                .addAnnotatedClass(Publisher.class)
16                .buildSessionFactory();
17
18        Session session = sessionFactory.getCurrentSession();
19
20        try {
21            session.beginTransaction();
22            //создаем издательства
23            Publisher publisher = new Publisher("Yakaboo");
24            Publisher publisher1 = new Publisher("Vivat");
25            Publisher publisher2 = new Publisher("IPIO");
26            //извлем три книги из БД
27            AuthorBooks authorbook =
28                    session.get(AuthorBooks.class,1);
29            AuthorBooks authorbook1 =
30                    session.get(AuthorBooks.class,2);
31            AuthorBooks authorbook2 =
32                    session.get(AuthorBooks.class,3);
33
34            //Связываем первое издательство
35            //с первой и третьей книгой.
36            publisher.setOneBook(authorbook);
37            publisher.setOneBook(authorbook2);
38            //Связываем второе издательство
39            //с первой, второй и третьей книгой.
40            publisher1.setOneBook(authorbook);
41            publisher1.setOneBook(authorbook1);
42            publisher1.setOneBook(authorbook2);
43            //Связываем третье издательство
44            //со второй и третьей книгой.
45            publisher2.setOneBook(authorbook1);
46            publisher2.setOneBook(authorbook2);
47            //сохраняем издательства в базу
48            session.save(publisher);
49            session.save(publisher1);
50            session.save(publisher2);
51            session.getTransaction().commit();
52
53        } catch (Exception e) {
54            session.getTransaction().rollback();
55            e.printStackTrace();
56        } finally{
57            session.close();
58        }
59    }
60}

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

Как видим, сначала произошло три select запроса на выборку книг (как мы помним, мы извлекали из БД три книги с помощью get).

Далее произошла вставка (insert) трех издательств в таблицу publisher и потом произошло связывание издательств и книжек посредством вставки идентификаторов в промежуточную таблицу.

Как видим, вставка издательств в таблицу publisher произошла успешно. Можно убедиться, что в промежуточной таблице книги и издательства связаны в соответствии с тем как мы их связывали в программе


Дополнительные материалы

Additional Material Icon

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

Сборщик проектов Maven

17
мин.

Similar Articles Icon
Divider

Создание Maven веб-проекта в Eclipse IDE

16
мин.

Similar Articles Icon
Divider

Настройка файла pom.xml в Maven

20
мин.

Similar Articles Icon