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)と双方向に変換するメソッドを定義。
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コンテナによって注入されるため、実装クラスを記述する必要はない。
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が行う。
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と一緒。