У меня есть объект отдела, отдел может иметь не более одного адреса, адрес, который также является объектом, может быть разделен между многими отделами.
Ради отработки отношений ManyToOne в спящем режиме я решил иметь JoinTable, вот мое определение сущностей:
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
@Getter
@Setter
@Entity(name = "Address")
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String city;
}
Адресная сущность:
@Getter
@Setter
@Entity(name = "department")
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToOne
@JoinColumn(name = "person_id")
private Person manager;
// many departments can have the same address
// one department should have at most one address
// todo not working as expected, we are not fetching the address of the department
@ManyToOne(fetch = FetchType.EAGER)
@JoinTable(name = "department_address",
joinColumns = @JoinColumn(name = "address_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "department_id", referencedColumnName = "id"))
private Address address;
}
Объект Person (только что добавленный для полноты примера):
@Getter
@Setter
@Entity(name = "person")
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "address_id")
private Address address;
}
При извлечении отдела из базы данных с использованием данных Spring jpa мы как бы не получаем адресные данные, связанные с отделом.
Вот содержимое базы:
Столовый отдел
| я бы | название | person_id |
|---|---|---|
| 23 | ЭТО | 3 |
Адрес стола
| я бы | название |
|---|---|
| 2 | Париж |
| 3 | хараджив |
Таблица address_address
| я бы | address_id | id_отдела |
|---|---|---|
| 2 | 2 | 23 |
Определение репозитория:
public interface DepartmentRepository extends JpaRepository<Department, Long> {}
При поиске данного отдела, для моего примера, это отдел 23, отделы/23:
Department department = departmentRepository.findById(id).get();
Address address = department.getAddress();
System.out.println("address = " + address);
Адрес всегда нулевой, даже если для отдела 23 есть строка в таблице адрес_отдела, и вот вывод отдела
System.out.println("department = " + department);
department = Department(id=23, name=IT, manager=Person(id=3, name=hamida, address=Address(id=3, city=kharajiv)), address=null)
Вот напечатанный sql-запрос:
Hibernate: select department0_.id as id1_1_0_, department0_.person_id as person_i3_1_0_, department0_.name as name2_1_0_, department0_1_.department_id as departme1_2_0_, person1_.id as id1_3_1_, person1_.address_id as address_3_3_1_, person1_.name as name2_3_1_, address2_.id as id1_0_2_, address2_.name as name2_0_2_, address3_.id as id1_0_3_, address3_.name as name2_0_3_ from department department0_ left outer join department_address department0_1_ on department0_.id=department0_1_.address_id left outer join person person1_ on department0_.person_id=person1_.id left outer join Address address2_ on person1_.address_id=address2_.id left outer join Address address3_ on department0_1_.department_id=address3_.id where department0_.id=?




Аннотация @JoinTable используется для указания сопоставления отношения таблицы «многие ко многим». Используйте @ManyToMany в этом случае
Да, ты прав
Вам не передано нулевое значение метода toString правильно. Возможно, метод toString неверен
левое внешнее соединение Адрес address3_ в отделе0_1_.department_id=address3_.id где
Может быть, я неправильно вижу, но идентификатор отдела и идентификатор адреса не могут совпадать. Должно быть deparment0_1.address_id = address3_.id
Можете ли вы попробовать изменить обратную колонку на address_id
joinColumns = @JoinColumn(name = "deparment_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "address_id", referencedColumnName = "id"))
private Address address
Спасибо, это была ошибка.
joinColumns: назначьте столбец третьей таблицы, относящийся к самой сущности (отделу в вашем случае). inverseJoinColumns: назначьте столбец третьей таблицы, относящийся к связанному объекту (адрес в вашем случае).
Ваш перевернут. У вас есть владеющая сущность (отдел) в inverseJoinColumns и адрес в joinColumns
Из документации: его также можно использовать для сопоставления двунаправленных ассоциаций «многие к одному/один ко многим», однонаправленных отношений «многие к одному» и ассоциаций «один к одному» (как двунаправленных, так и однонаправленных).