Home > Net >  ManyToOne with JoinTable relationship doesn't work properly
ManyToOne with JoinTable relationship doesn't work properly

Time:03-23

I have a departement entity, a departement can have at most one address, an adress which is also an entity, can be shared between many departments.

I decided for the sake of practicing ManyToOne relationship in hibernate, to have a JoinTable, here is my entities definition:

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;
} 

The Address entity:

@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;
}

The Person entity (just added for the completness of the example):

@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;
}

When retriving a departement from the database using spring data jpa, it's like we don't fetch the address data associated with the department.

Here is the content of the database:

Table department

id name person_id
23 IT 3

Table address

id name
2 Paris
3 kharajiv

Table department_address

id address_id department_id
2 2 23

The repository definition:

public interface DepartmentRepository extends JpaRepository<Department, Long> {}

When looking for a given department, for my example, it is the department 23, departments/23:

Department department = departmentRepository.findById(id).get();
Address address = department.getAddress();
System.out.println("address = "   address);

The address is always null, even if for the department 23, there is a row in the table department_address, and here is the output of the department

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)

Here is the printed sql query:

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=?

CodePudding user response:

left outer join Address address3_ on department0_1_.department_id=address3_.id whe

Maybe I see wrong but deparment id and address id can not match. It has to be deparment0_1.address_id = address3_.id

Can you try to change inversecolumn to address_id

joinColumns = @JoinColumn(name = "deparment_id", referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(name = "address_id", referencedColumnName = "id"))
    private Address address

CodePudding user response:

@JoinTable annotation is used to specify the mapping of a many-to-many table relationship. Use @ManyToMany in this case

CodePudding user response:

joinColumns: Assign the column of third table related to entity (department in your case) itself. inverseJoinColumns: Assign the column of third table related to associated entity (address in your case).

Yours is inverted. You have the owning entity (department) in inverseJoinColumns and address in joinColumns

JoinTable Documentation

  • Related