Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
13
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

[Java][Spring Boot][JPA] データベースを使う - NetBeansで始めるSpring Boot (6)

概要

Spring Bootは、データベースアクセスにSpring Dataを使用します。
Spring Dataは、JPAやMongoDBなどのデータストアへのアクセスを抽象化する層です。

自分はJPAを使います。

作らなくちゃいけないもの

Entityクラス

データベースのテーブルへ対応するクラスです。

すでにデータベースが用意されているのであれば、NetBeansの機能を使って生成するのが簡単です。

[File]>[New File]メニューから、Persistence > Entity Classes from Databaseとたどれば、データベースのテーブルからEntityクラスを生成できます。

Repositoryインターフェース

Entityを操作するインターフェースです。org.springframework.data.repository.Repository<T, ID extends Serializable>の派生インターフェースにします。

派生インターフェースとして、あらかじめ次のものが用意されています。

インターフェース 解説
CrudRepository 一般的なCread/Read/Update/Delete操作が定義されています
PagingAndSortingRepository ソートとページング付きの全検索が定義されています。CrudRepositoryを継承しています。

使い方

Repositoryインターフェースに対して@Autowired等で依存しておくと、Springが自動的にプロキシインスタンスを作成してくれます。

@Component
public class SomeClass {
  // ...
  @Autowired
  private SomeRepository someRepository;
  // ...
}

あとは定義されているメソッドを呼び出せばよいです。

CRUD以外の操作をしたい

CrudRepositoryにあらかじめ用意されているCRUD以外の操作をしたいときのやり方です。

方法1 - 命名規約にそったメソッドを実装

以下の命名規約にそったメソッドを実装すると、メソッド名に応じて振る舞いが用意されます。

  • find...By
  • read...By
  • get...By
  • query...By
  • stream...By Java 8のStreamを返します。
  • count...By
  • exists...By
  • delete...By
  • remove...By

最初に出てくるByより後ろが検索式になります。

...の副式部分にはDistinctや、リレーション先のEntity名等が入ります。

検索式いろいろ

あらかじめいろいろなものが用意されています。

2016/11/11追記 【Spring Data JPA】自動実装されるメソッドの命名ルール に解説がありました。

検索式
2項目をAndで結ぶ findByFirstnameAndLastname(String lastname)
2項目をOrで結ぶ findByFirstnameOrLastname(String firstname, String lastname)
2項目の間 findByCreateDateBetween(Date since, Date to)
After/GreaterThan
GreaterThanEqual
Before/LessThan
LessThanEqual
IsNull
IsNotNull
NotIn
In
StartingWith/EndingWith/Containing
NotContaining
Like
NotLike
大文字小文字を無視 findByFirstnameIgnoreCase(String firstname)
ソート findAllOrderByFirstnameAsc() findAllOrderByFirstnameDesc()

副式...に入るもの

副式 解説
Distinct SQLのDISTINCTと一緒です。
Top<数字> / First<数字> 先頭から<数字>レコード分を返します。
エンティティ名 リレーション先のエンティティを返します。

方法2 - @Queryをつけたメソッドを実装

例えば、このようになります。

@Query("SELECT u FROM User WHERE u.firstname = :firstname")
List<User> findByFirstname(String firstname);

@Queryの中身はJPQLでよいのかな?

Spring Expression Languageも使えます。

方法3 - Customクラスを作る

命名規約やJPQLでは足りない機能を実装するときには、Customクラスを作ります。

例えば、もともとこんなRepositoryインターフェースがあったとしたら、

UserRepository.java
public interface UserRepository extends CrudRepository<User, Long> {}

まずは独自の機能をもったインターフェースを作ります。

UserRepositoryCustom.java
public interface UserRepositoryCustom {
  public void executeSomeOperation(User user);
}

もともとあったインターフェースに継承させます。

UserRepository.java
public interface UserRepository extends CrudRepository<User, Long>, UserRepositoryCustom {}

さらに実装を作ります。

public class UserRepostitoryImpl implements UserRepositoryCustom {
    public void executeSomeOperation(User user) {
       // なにか特別な処理
    }
}

もう少し詳しく書きました。 > Customクラスを使用してデータベースアクセスする

テストする

Repositoryインターフェースをテストします。

テストにはHSQLデータベースを使用します。

pom.xmlを変更

テストのスターター、JDBCドライバ、いつものjunitを依存ライブラリに追加します。

2016/11/11編集 junitとhamcrestは、スターターに入っていたので不要でした。

pom.xml
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hsqldb</groupId>
            <artifactId>hsqldb</artifactId>
            <scope>test</scope>
        </dependency>

テスト用アプリケーションクラスの作成

アプリケーションクラスがなければ作成します。

src/test/java/com/example/TestApplicationi.java
package com.example;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@SpringBootApplication
@EnableJpaRepositories("com.example.repository")
public class TestApplication {

}

普通は@SpringBootApplicationだけで足りるのですが、Repositoryクラスが別にあるので@EnableJpaRepositoriesを付けています。

テストクラスの作成

@RunWithを付けて、テストランナーを指定します。

@SpringBootTest@Transactionalは何をやっているのかわかりません。 :sweat:

2016/11/17 追記 @SpringBootTest@Transactionalは不要でした。@DataJpaTestを付けるだけでよいです。これをつければSQLもログ出力してくれます。

src/test/java/com/example/repository/UserRepositoryTest.java
package com.example.repository;

import com.example.entity.User;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;

@RunWith(SpringRunner.class)
@DataJpaTest
public class UserRepositoryTest {

    @Autowired
    private UserRepository instance;

    @Before
    public void setUp() {
       // 初期データの用意等
    }

    @Test
    public void testFindSomething() {
       // テストを書く
    }
}

参考リンク

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
13
Help us understand the problem. What are the problem?