LoginSignup
9

More than 5 years have passed since last update.

Spring BootとJPAでREST APIを実装する(インフラ層編)

Last updated at Posted at 2018-07-14

Spring Boot + MySQLでシンプルなWeb REST APIサーバを実装する - Qiita

Outline

以下の設計に従って、インフラ層を実装する。
Spring Bootで実装するWebAPIのアーキテクチャを考える - Qiita

以下の3クラスを作成する。

  • UserEntity.java
  • UserJpaRepository.java
  • UserRepository.java
├── infrastructure
│   ├── entity
│   │   └── UserEntity.java
│   └── repository
│       ├── UserJpaRepository.java
│       └── UserRepositoryImpl.java

UserEntity.java

MySQLのレコードがマッピングされるクラス。
Domain Object(User.java)と双方向に変換するメソッドを定義。

UserEntity.java
package com.example.springapi.infrastructure.entity;

import com.example.springapi.domain.object.User;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * RDBレコードのマッピング用クラス
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "test_users")
public class UserEntity {
    @Id
    @Column(name = "id")
    private String id;

    @Column(name = "value")
    private String value;

    /**
     * ドメインオブジェクトからインスタンスを生成
     *
     * @param user ドメインオブジェクト
     * @return UserEntity
     */
    public static UserEntity build(User user) {
        return UserEntity.builder()
                .id(user.getId())
                .value(user.getValue())
                .build();
    }

    /**
     * ドメインオブジェクトへ変換
     *
     * @return ドメインオブジェクト
     */
    public User toDomainUser() {
        return User.builder()
                .id(this.id)
                .value(this.value)
                .build();
    }
}

※ JPAアノテーション

@Entity

これでJPAのEntity(マッピングされるクラス)ってことを表現する。

@Table

テーブル名を指定する。

@id

プライマリキーであることを指定する。
複合キーの場合は書き方が変わる。

@Column

テーブルの列名を指定する。

※ Lombokアノテーション

@NoArgsConstructor

引数なしのコンストラクタを自動で作成する。
JPAのEntityのライフサイクル上、引数なしのコンストラクタが必要。
引数なしのコンストラクタが存在するような構成ならば不要。(finalなフィールドが無い場合など。@Builder使うなら絶対必要)

@AllArgsConstructor

すべてのフィールドを引数に取るコンストラクタを作成する。
NoArgsConstructorを指定した場合、こちらも指定しないと、@Builderが動かない(@Builderではすべてのフィールドを引数にとるコンストラクタを自動で生成するが、xxxArgsConstructorがついてるクラスに対しては、コンストラクタを作成しない。そして動かない。)

UserJpaRepository.java

JPAの実装を利用するために必要なインタフェース。
JpaRepositoryを継承し、Entityクラスと、プライマリキーの型を指定する。
実行時にはSimpleJpaRepositoryというspring-data-jpaが用意している標準実装がDIコンテナによって注入されるため、実装クラスを記述する必要はない。

UserJpaRepository.java
package com.example.springapi.infrastructure.repository;

import com.example.springapi.infrastructure.entity.UserEntity;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * JPAを利用するためのインタフェース
 */
public interface UserJpaRepository extends JpaRepository<UserEntity, String> {
}

UserRepositoryImpl.java

ドメイン層で定義したUserRepositoryインタフェースの実装クラス。
実際の処理はSimpleJpaRepositoryが行う。

UserRepositoryImpl.java
package com.example.springapi.infrastructure.repository;

import com.example.springapi.domain.object.User;
import com.example.springapi.domain.repository.UserRepository;
import com.example.springapi.infrastructure.entity.UserEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.Optional;

/**
 * 永続化の実装クラス
 * ドメインオブジェクトをEntityに変換してJPAをラップする
 */
@Repository
@RequiredArgsConstructor
public class UserRepositoryImpl implements UserRepository {

    @NonNull
    private final UserJpaRepository userJpaRepository;

    /**
     * {@inheritDoc}
     */
    @Override
    public Optional<User> findById(String id) {
        return this.userJpaRepository.findById(id)
                .map(UserEntity::toDomainUser);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public User save(User user) {
        return this.userJpaRepository.save(UserEntity.build(user))
                .toDomainUser();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void deleteById(String id) {
        this.userJpaRepository.deleteById(id);
    }
}

@Repository

@Compornentのエイリアス。
@Serviceと一緒。

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
9