今回はデータベースとのデータのやり取りについてやっていきたい。
Accessing Data with JPAをやってみる
Javaでデータベースを扱う方法でやったことがあるのはJDBCとOrmLiteくらいだったので、JPAは多分初めて使う。
まずはbuild.gradleを変更する。
dependencies { // compile("org.springframework.boot:spring-boot-starter-web:1.2.1.RELEASE") // compile("org.springframework.boot:spring-boot-starter-actuator:1.2.1.RELEASE") compile("org.springframework.boot:spring-boot-starter-thymeleaf:1.2.1.RELEASE") compile("org.springframework.boot:spring-boot-starter-security:1.2.1.RELEASE") compile("org.springframework.boot:spring-boot-starter-data-jpa:1.2.1.RELEASE") compile("com.h2database:h2:1.4.183") compile("org.webjars:jquery:2.1.3") testCompile("org.springframework.boot:spring-boot-starter-test:1.2.1.RELEASE") }
H2はJavaでできたデータベースだ。Javaでデータベースを試すのであればこれがお手軽のようだ。
シンプルなEntityクラスを作る
今回はJPAのEntityアノテーションを使ったシンプルなEntityクラスを作るようだ。
package sample; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @Entity public class Customer { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; private String firstName; private String lastName; protected Customer(){} public Customer(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } @Override public String toString() { return String.format( "Customer[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName ); } }
protectedなコンストラクタは直接使うことはしない。そしてpublicなコンストラクタはデータを保存するときに使う。@Tableアノテーションがない場合はCustomerテーブルがあると仮定して動くようだ。
そして、プライマリキーに@Idをつけ、@GeneratedValueアノテーションのstrategyにGenerationType.AUTOを設定することでインクリメントされていくということだろう。
Spring Data JPA
Spring Data JPAはJPAを使ってデータベースにアクセスするためのものだ。interfaceを定義しておいたら、継承したCrudRepositoryが様々な処理を追加してくれるようである。独自に定義したい場合もルールに則ったメソッドを定義しておいたら、おそらくメタプログラミングしてくれるのだろう。
package sample; import org.springframework.data.repository.CrudRepository; import java.util.List; public interface CustomerRepository extends CrudRepository<Customer, Long> { List<Customer> findByLastName(String lastName); }
通常のJavaアプリケーションであれば、CustomerRepositoryクラスを定義するところであろうが、Spring Data JPAはパワフルなのでそんな必要はない、と書いてあった。さぁ!早速試してみようぜ!と書いてあるので試してみよう。
Applicationクラスにrunメソッドを
今回は画面上にではなくて、システムログに出すだけのようだ。
CommandLineRunnerインターフェースを入れたApplicationクラスにするようだ。
package sample; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import java.util.Arrays; @SpringBootApplication public class Application implements CommandLineRunner { @Autowired CustomerRepository repository; public static void main(String[] args) { // 略 } @Override public void run(String... args) throws Exception { repository.save(new Customer("Jack", "Bauer")); repository.save(new Customer("Chloe", "O'Brian")); repository.save(new Customer("Kim", "Bauer")); repository.save(new Customer("David", "Palmer")); repository.save(new Customer("Michelle", "Dessler")); // fetch all customers System.out.println("Customers found with findAll():"); System.out.println("-------------------------------"); for (Customer customer : repository.findAll()) { System.out.println(customer); } System.out.println(); // fetch an individual customer by ID Customer customer = repository.findOne(1L); System.out.println("Customer found with findOne(1L):"); System.out.println("--------------------------------"); System.out.println(customer); System.out.println(); // fetch customers by last name System.out.println("Customer found with findByLastName('Bauer'):"); System.out.println("--------------------------------------------"); for (Customer bauer : repository.findByLastName("Bauer")) { System.out.println(bauer); } } }
CustomerRepositoryインターフェースがSpring Application Contextによって生成されるようなので、newとか別にしなくてもいいらしい。saveメソッドにCustomerインスタンスを渡すと保存されるし、findAllメソッドで全部のデータを持ってこれるし、findOneメソッドでidを指定すれば1件だけ取得することもできる。自分でメソッド名のみ定義したfindByLastNameメソッドも作られていて利用できる。うーむ、すごい。
whereとかはJPAのドキュメントを読めってことだと思うんだけれど、とりあえずここまででサンプルは終わっていて、RESTで使ってみるのは?へのリンクがあったので、次回はそれをやってみようと思う。