ManyToOne с отношением JoinTable не работает должным образом

У меня есть объект отдела, отдел может иметь не более одного адреса, адрес, который также является объектом, может быть разделен между многими отделами.

Ради отработки отношений 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_idid_отдела
2223

Определение репозитория:

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=?
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
69
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Аннотация @JoinTable используется для указания сопоставления отношения таблицы «многие ко многим». Используйте @ManyToMany в этом случае

Из документации: его также можно использовать для сопоставления двунаправленных ассоциаций «многие к одному/один ко многим», однонаправленных отношений «многие к одному» и ассоциаций «один к одному» (как двунаправленных, так и однонаправленных).

xmen-5 20.03.2022 12:29

Да, ты прав

Gurkan İlleez 22.03.2022 21:19

Вам не передано нулевое значение метода toString правильно. Возможно, метод toString неверен

Gurkan İlleez 22.03.2022 21:26
Ответ принят как подходящий

левое внешнее соединение Адрес 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

Спасибо, это была ошибка.

xmen-5 22.03.2022 22:12

joinColumns: назначьте столбец третьей таблицы, относящийся к самой сущности (отделу в вашем случае). inverseJoinColumns: назначьте столбец третьей таблицы, относящийся к связанному объекту (адрес в вашем случае).

Ваш перевернут. У вас есть владеющая сущность (отдел) в inverseJoinColumns и адрес в joinColumns

Документация по присоединению к таблице

Другие вопросы по теме