3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Spring Data JPAでJPQLを書かずにJOINさせる

Last updated at Posted at 2022-02-19

概要

Spring Data JPAでfindAll()findById(id)実行時にJOINさせるようにし、N+1問題が起きないようにする。
JPQLは使わないで実現する。

Service

以下のようにそれぞれを呼び出す。以下の例ではpagingを実装しているが、していない場合でも同じ。

UserService
@Service
@RequiredArgsConstructor
public class UserService {

    private final UserRepository UserRepository;

    public Page<UserModel> findAll() {
        // paging
        Pageable limit = PageRequest.of(0, 10);
        return UserRepository.findAll(limit);
    }

    public Optional<UserModel> findById(Long id) {
        return UserRepository.findById(id);
    }
}

UserModel

findById()をjoinさせるためには、 @Fetch(FetchMode.JOIN)アノテーションを付与すればOK。
findAll()は、@NamedEntityGraphを使う。nameには任意の名前を定義する。

UserModel
@Entity
@Getter
@Table(name = "users")
@NamedEntityGraph(
        name = "group_with_all_associations",
        includeAllAttributes = true
)
public class UserModel {

    @Id
    private Long id;
    @Column(name = "user_name")
    private String userName;
    @Column(name = "group_id")
    private Long groupId;

    @ManyToOne
    @JoinColumn(name = "group_id", referencedColumnName = "id")
    @Fetch(FetchMode.JOIN)
    private GroupModel groupModel;

}

GroupModel

こちらは特筆すべきことはなし。

GroupModel
@Entity
@Getter
@Table(name = "groups")
public class GroupModel {

    @Id
    private Long id;
    @Column(name = "group_name")
    private String groupName;
}

UserRepository

UserModelの@NamedEntityGraphのnameの値を、以下のように@EntityGraphのvalueに定義する。
これでfindAll()もjoinされる。

UserRepository
public interface UserRepository extends JpaRepository<UserModel, Long> {

    @EntityGraph(value = "group_with_all_associations", type = EntityGraph.EntityGraphType.FETCH)
    public Page<UserModel> findAll(Pageable limit);
}

発行されるSQLを確認

実行して、発行されるSQLを確認する。

SQLのログを出力

SQLのログが出力されるようにする。

application.yml
logging:
  level:
    org:
      hibernate:
        SQL: DEBUG
        type:
          descriptor:
            sql:
              BasicBinder: TRACE

findAll()

select
    usermo0_.id as id1_1_0_,
    usermo0_.group_id as group_i49_1_0_,
    groupmodel1_.id as id1_0_1_,
    groupmodel1_.group_name as group_n17_0_1_
from
    users usermo0_
    left outer join
        groups groupmodel1_
    on  usermo0_.group_id = groupmodel1_.id
limit ?

findById()

select
    usermo0_.id as id1_1_0_,
    usermo0_.group_id as group_i49_1_0_,
    groupmodel1_.id as id1_0_1_,
    groupmodel1_.group_name as group_n17_0_1_
from
    users usermo0_
    left outer join
        groups groupmodel1_
    on  usermo0_.group_id = groupmodel1_.id
where
    usermo0_.id = ?

参考

3
2
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
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?