LoginSignup
0
1

More than 5 years have passed since last update.

Spring Data JPA において、@OneToMany に targetEntity = RelatedClass.class を指定した際の挙動について

Last updated at Posted at 2017-10-27

概要

先日何気なく Spring Data JPA のエンティティをリファクタリングしていた時にしくっていることを発見したので、その備忘録です。
こんなリレーションがあったとします。


|---------------
|Company
|  id
|  employee_id
|---------------
    1
    |
    n
|------------
|Employee
|  id
|  name
|---------------

Company.java
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@NoArgsConstructor
@Getter
@Embeddable
public abstract class Company {
    @Id
    private Integer id;

    @OneToMany(targetEntity = Employee.class, fetch = FetchType.EAGER)
    @PrimaryKeyJoinColumn
    protected Set<Employee> employees;
}
Employee.java
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Getter
@NoArgsConstructor
public abstract class Employee {
    @Id
    private int id;

    @Column(name = "employee_id", insertable = false, updatable = false)
    private int employeeId;

    @ManyToOne
    private Company company;
}

これらのエンティティ (とその他雑多なエンティティ) に対して JPQL を実行したところ、下記のような SQL が実行されました。


select
    distinct many columns...
from
        company company3_
    left outer join
        company_employees employees4_
    on  company3_.id = employees4_.company_id
    left outer join
        employee employee5_
    on  employees4_.employees_id = employee5_.id

どうやら、下記のように、JPA では、Company と Employee の関係が ManyToMany の関係があるものとして認識されているようでした。。


|---------------
|Company
|  id
|  employee_id
|---------------
    1
    |
    n
|------------
|Company_Employees
|  company_id
|  employee_id
|---------------
    n
    |
    1
|------------
|Employee
|  id
|  name
|---------------

動作の要因について

Company の @OneToMany にて targetEntity 属性で関連を定義していたため、上記動作になったようです。
継承戦略を多用しているので、どうしてもそのような形になってしまうのかと考えていた (要因の一端ではある気がします) のですが、関連を通常の mappedBy に変更することで実行される SQL が変わりました。

Company.java
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@NoArgsConstructor
@Getter
@Embeddable
public abstract class Company {
    @Id
    private Integer id;

    @OneToMany(mappedBy = "company", fetch = FetchType.EAGER)
    @PrimaryKeyJoinColumn
    protected Set<Employee> employees;
}
Employee.java
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Getter
@NoArgsConstructor
public abstract class Employee {
    @Id
    private int id;

    @Column(name = "employee_id", insertable = false, updatable = false)
    private int employeeId;

    @ManyToOne
    private Company company;
}

実行される SQL。

select
    distinct many columns...
from
        company company3_
    left outer join
        employee employee5_
    on  company3_.id = employee5_.company_id
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1