Бесплатный курс по Java: от основ до продвинутого уровня
Двусторонняя связь между сущностями в Hibernate
Связь между объектами таблиц была односторонняя, то есть через объект Author удалялся из БД или сохранялся в БД связанный объект AuthorInfo.
Теперь сделаем наоборот. Так, чтобы через объект AuthorInfo производились какие-то действия в БД со связанным объектом Author.
Теперь уже будет двухсторонняя связь. То есть мы, например, можем совершить выборку из базы с помощью метода get объекта AuthorInfo, и при этом автоматически будет получен из базы связанный с ним объект Author.
Для двусторонней связности объектов связанных строк, необходимо изменить класс AuthorInfo.
package HibernateApps;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Column;
import javax.persistence.OneToOne;
import javax.persistence.Table;
// Это класс с таблицы author_info.
@Entity
@Table(name = “author_info”)
public class AuthorInfo {
@Id
@GeneratedValue(
strategy = GenerationType.IDENTITY
)
@Column(name = “id”)
private int id;
@Column(name = “books_written_number”)
private int booksWritten;
@Column(name = “country”)
private String country;
// Для двусторонней связанности указываем
// в mappedBy каким полем класс Author
// связан с данным классом AuthorInfo.
@OneToOne(mappedBy = “authorInfo”,
cascade = CascadeType.ALL)
private Author author;
public AuthorInfo() {
}
public AuthorInfo(int booksWritten,
String country) {
this.booksWritten = booksWritten;
this.country = country;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getBooksWritten() {
return booksWritten;
}
public void setBooksWritten(
int booksWritten) {
this.booksWritten = booksWritten;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public Author getAuthor() {
return author;
}
public void setAuthor(Author author) {
this.author = author;
// В прошлом уроке мы передавали
// объект AuthorInfo в сеттер
// объекта Author для того чтобы эти
// объекты были связаны как связаны
// строки этих объектов в БД.
// Чтобы можно было так связать
// эти объекты наоборот, то есть
// в сеттер объекта Author
// передать объект Author,
// нужно еще и передать
// текущий(this) объект AuthorInfo
// объекту Author потому что если
// этого не сделать то объект Author
// не будет знать ничего
// о объекте AuthorInfo.
// Уточним что класс, в котором
// mappedBy не связан с тем, в котором
// JoinColumn напрямую. Связанным напрямую
// с другим классом можно назвать класс,
// в котором JoinColumn. Поэтому обратную
// связанность мы скорее имитируем
// использованием mappedBy
// и конструкциями типа
// author.setAuthorInfo(this);
author.setAuthorInfo(this);
}
@Override
public String toString() {
return “AuthorInfo [id=” + id + “, ”
+ “booksWritten=”
+ booksWritten + “, country=”
+ country + “, author=”
+ author + “]”;
}
}
Теперь давайте создадим два объекта, свяжем их теперь уже используя сеттер объекта AuthorInfo и добавим их в БД.
package HibernateApps;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateApp {
public static void main(String[] args) {
// create session factory
SessionFactory factory = new Configuration()
.configure(“hibernate.cfg.xml”)
.addAnnotatedClass(Author.class)
.addAnnotatedClass(AuthorInfo.class)
.addAnnotatedClass(AuthorBooks.class)
.buildSessionFactory();
// create session
Session session = factory.getCurrentSession();
try {
session.beginTransaction();
//создадим два объекта и свяжем их
//только через сеттер объекта
//authorInfo, а не author как
//в прошлых уроках
AuthorInfo authorInfo = new AuthorInfo(10, “Great Britain”);
Author author = new Author(“JJ Rowling”);
//связываем
authorInfo.setAuthor(author);
//при сохранении authorInfo сохраниться
//в базу и author поскольку они связаны
session.save(authorInfo);
AuthorInfo authorInfo1 = session.get(AuthorInfo.class, 1);
System.out.println(authorInfo1);
//строкой ниже удаляться связанные строки
//таблиц через связанные объекты этих строк.
session.delete(authorInfo1);
AuthorInfo authorInfo2 = session.get(AuthorInfo.class, 1);
System.out.println(authorInfo2);
session.getTransaction().commit();
}
catch (Exception e){
session.getTransaction().rollback();
e.printStackTrace();
}
finally {
session.close();
}
}
}
Давайте запустим нашу программу.
Как видим, произошло два запроса на вставку, хотя метод save мы вызывали только над одним объектом actorinfo. Это доказывает, что каскадная PERSIST операция сработала и произошел insertне только объекта authorinfo в таблицу author_info, а и связанного с ним объекта author в таблицу author. То есть двусторонняя связь работает.
Далее с помощью get мы выбрали из таблицы author_info только что положенную туда строку и поместили ее в объект authorinfo1, в консоли можно увидеть содержимое объекта authorinfo1, и как видим он, содержит объект author, то есть опять таки, для выборки связь тоже работает.
После удаления из базы связанных объектов на консоль вывелось null, значит объекты успешно удалились из базы.
Проверим на всякий случай и базу удалились ли обе строки в таблицах:
Настройте связь Один-ко-Многим в Hibernate с помощью @OneToMany. Узнайте, как работать с каскадными операциями и управлять связанными сущностями в Java приложениях.