SE_BOKUのまとめノート的ブログ

SE_BOKUが知ってること・勉強したこと・考えたことetc

データアクセス:JPAを使って簡単にCRUDする。 STS3 +Spring Boot + JPA + MySQL

Spring Boot + JPA + MySQLで簡単なデータアクセスのサンプルを作ってみます。 

なお、STS3(3.9.6)+SpringBoot2.0+tymeleaf3.0迄動作確認しています。

f:id:arakan_no_boku:20190222012501j:plain

 

今回の仕様

 

プライマリキーが一つの単純なテーブルばかりではないので、後のことも考えて、簡単と言いながら、ちょっとだけ実用を意識します。 

今回の目標は、以下にします。

  1. 複数キーを持つテーブルを作る。
  2. そのテーブルに対するCRUDを、Jprepositoryで用意する。
  3. 一連のテーブルアクセスを、JUNITテストでやってみる。

 

複数キーを持つテーブルを作る。

 

名前は、person_entityにしています。

create table person_entity (
        pid VARCHAR(150) not null comment 'パーソンID'
      , item_id VARCHAR(150) not null comment '項目ID'
      , value VARCHAR(300) comment '値'
      , update_date TIMESTAMP comment '更新日'
      , constraint person_entity_PKC primary key (pid,item_id)
) comment 'パーソン' ;

 

対応するエンティティクラスを作る

 

名前付けルールで、クラス名は「PersonEntity」の必要があります。 

@Entity
@IdClass(value=PersonEntityKey.class)
public class PersonEntity {
     public PersonEntity(String id,String itemId,String value){
           super();
           setPid(id);
           setItemId(itemId);
           setValue(value);
     }
   @Id

    private String pid;

   @Id

    private String itemId;

    private String value;

    @Temporal(TemporalType.TIMESTAMP)

    private Date updateDate;

    @PrePersist
    @PreUpdate
     protected void now(){
          setUpdateDate(new Date());
     }

}

 ※ごちゃごちゃするので、getter、setterは省いて引用してます。 

@Idというアノテーションがついているとプライマリキーです。 

キーが一つの場合は、@Idを指定するだけで良いのですが、キーが2つ以上だと、@Idを2つ書くだけだとエラーになります。 

それを回避するための定義が、「@IdClass(value=PersonEntityKey.class)」の部分です。 

プライマリキーにする項目だけを定義したクラスをつくります。 

valueの後ろに指定します。 

今回の場合の中身はこんな感じです。

public class PersonEntityKey implements Serializable {

       private static final long serialVersionUID = 1L;
       private String pid;
       private String itemId;

※これもgettter、setterは省略してます。 

このクラスを「@IdClass(value=PersonEntityKey.class)」の様に指定すれば、@Idを2つ指定してもエラーにならなくなり、後の操作は@Id一つの場合と同じように扱えます。

 

そのテーブルに対するCRUDを、Jprepositoryで用意する。

 

このエンティティクラスPersonEntityに対応する、リポジトリクラスを作ります。

@Repository
public interface PersonRepository extends JpaRepository<PersonEntity, PersonEntityKey> {
      // Select
      public List<PersonEntity> findByPid(String pid);
}

こんな感じで、 JpaRepositoryを継承したインタフェースを作るだけで、基本的なCRUDが提供されるので、超楽です。 

<PersonEntity, PersonEntityKey>の部分は、対象とするエンティティクラスと、プライマリキーを収めたクラスを指定します。 

ちなみに、Entityクラスの@Idアノテーションがひとつだけ(キーが1つ)の場合は、上記のPersonEntityの部分に、Stringなどのキーの型を表すクラスを指定すれば良いです。 

しかも、エンティティクラスに、こう書いておくだけで、INSERT/UPDATE時に自動的に更新日付を記録してくれます。

@Temporal(TemporalType.TIMESTAMP)

private Date updateDate;

public Date getUpdateDate() {
     return updateDate;
}
public void setUpdateDate(Date updateDate) {
     this.updateDate = updateDate;
}

@PrePersist
@PreUpdate
protected void now(){
     setUpdateDate(new Date());
}

これは結構、手間が省けて助かりますね。  

とりあえず、pidを指定してselectしたいので、findByPidというメソッドを定義してます。 

これも、名前付けルールだけ気をつけて、定義だけしとけば中身は自動的に生成されます。(findBy・・の後ろの名前とDB物理名が一致しないと実行時エラーになります)

 

一連のテーブルアクセスを、JUNITテストでやってみる

 

じゃあ、これで本当にCRUDできるのか、JUNITのテストケースを書いてみます。

@RunWith(SpringRunner.class)
@SpringBootTest
public class TestPersonRepository {

      @Autowired
      public PersonRepository personRepository;

      @Test
      public void test() {
            PersonEntity pe = new PersonEntity("001","001","value W 2 格納テスト");

            // Create(Insert)  

            personRepository.saveAndFlush(pe);

            //  Read(Select)

            List<PersonEntity> peList =         personRepository.findByPid("001");

            //  Update

            personRepository.saveAndFlush(pe);


            assertTrue(peList.get(0).getItemId().equals("001"));
      PersonEntity pe1 = peList.get(0);

            //  Delete
            personRepository.delete(pe1);
}

 saveAndFlush() というメソッドを2回よんでいるのは、レコードがなければInsert、あればupdate を自動で切り替えてくれるみたいなので、それを確認しているわけです。 

これでJUNITテストを実行して、グリーンならOKです。

 

まとめ

 

とりあえず、この程度の手間で、一通りのCRUDができて、かつ、単体テストまでできるのは有り難いですね。 

もちろん、もっと複雑なSQLが必要な場合は、ダイレクトにSQLを書いたり、それなりの手間はかかります。 

でも、今時、ガリガリと複雑なSQLばかりを書くのもスマートじゃないし、設計で考慮して、極力、このシンプルな手順で処理できるようにしたらいいのかなと思ってます。 

 


 STS+Spring Boot+thymeleaf 関連記事

 

入力画面に関連する記事

画像をSUBMITボタン代わりに使う

ラジオボタンとラジオボタングループを使う 

ラジオボタンとラジオボタングループを使う 

チェックボックスを使う。 

HTMLのタグの閉じ忘れで例外が発生する!

プルダウンリストとマルチセレクトボックスを使う。

今度はテキストエリアで複数行入力する。 

テキストボックスの入力と基本的なチェックを使う。

 

参照画面・画面遷移に関連する記事

参照画面:テーブルを使い、行毎に色分けした一覧表を表示する。 

参照画面:条件に一致した時のみHTML要素を出力する。

セッションを使って画面間で情報を受け渡す 

画面遷移:GET時のリクエストパラメータを受け取る 

日本語しか使わなくても、i18N対応はする意味がある。

 

入力チェックに関連する記事

入力チェック:未入力時に空文字が渡される仕様を回避する。 

入力チェック:@Patternと正規表現で独自チェックする。

入力チェック:アノテーション定義を自分で作る。(再利用版)

入力チェック用アノテーション定義を自分で作る。(独自実装版)

入力チェック:複数項目の相関チェックアノテーションの作り方

 

データアクセス・その他に関連する記事

データアクセス:Jprepositoryを使って簡単にCRUDする。 

データアクセス:ネイティブなSQL文を実行する 

クラスパス内の静的ファイルにアクセスする 

SpringBootだとログの書き出しも楽ちんです。 

SpringBootプロジェクトでJUNIT4を使った単体テストをする。