2019.04.08
今回はJPA(Java Persistence API)の機能を使ってアクセスの実装をします。 データベースアクセスには一般に「DAO」と呼ばれるオブジェクトを用意します。 これは、Data Access Objectの略で、文字通りデータベースにアクセスする手段を提供するためのオブジェクトです。
今回はこちらを作成、実装しました。 STSを使用しバージョンは3.9.2で、gradleでビルドをしています。 まずはデータベースの属性を定義するクラスを作成します。Spring Bootではこれをエンティティと呼び、データベースのレコード1つ1つがエンティティクラスのインスタンスの形になっているという感じです。 今回使用するエンティティは以下です。(getterとsetterは省略してあります)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | package com.transonic.springboot; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; import javax.validation.constraints.Min; import javax.validation.constraints.Max; import javax.validation.constraints.NotNull; import org.hibernate.validator.constraints.Email; import org.hibernate.validator.constraints.NotEmpty; @Entity @Table(name="mydata") public class MyData { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column private long id; @Column(length=50, nullable = false) private String name; @Column(length = 200, nullable = true) private String mail; @Column(nullable = true) @Min(value=0) @Max(value=200) private Integer age; @Column(nullable = true) private String memo; } |
順番に説明していきます。
エンティティとして定義するクラスにはクラス名の上に「@Entity」というアノテーションを付与します。 これにより、このクラスがエンティティということが認識されます。
引数に任意の名前を渡すことでテーブル名を指定することができます。 省略も可能です。その場合はクラス名がテーブル名となります。
プライマリキーを指定します。 エンティティを用意するときには、レコードをユニークにするために用意しておくとよいでしょう。
@GeneratedValue(strategy = GenerationType.AUTO)はプライマリキーをフィールドに対して自動的に付与します。AUTOを指定することにより自動的に値を割り振るようになります。
フィールドに割り当てられるカラム名を指定します。このアノテーションの引数は以下の通りです。
name | カラム名を指定 |
---|---|
length | 最大の長さを指定 |
nullable | 未入力を許可するかどうかを指定 |
文字通り最大最小の限度を決めるアノテーションです。 上記のソースを例にするとageフィールドは0から200の値までしか入力することができません。
1 2 3 4 5 6 7 8 | package com.transonic.springboot; import java.io.Serializable; import java.util.List; public interface MyDataDao extends Serializable{ public List getAll(); } |
DAOの定義としてインターフェースを用意しました。 全データ取得のメソッドのみ定義してあります。次にこれの実装クラスを作っていきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | package com.transonic.springboot; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.Query; import org.springframework.stereotype.Repository; @Repository public class MyDataDaoImpl implements MyDataDao { private static final long serialVersionUID = 1L; private EntityManager entityManager; public MyDataDaoImpl() { super(); } public MyDataDaoImpl(EntityManager manager) { this(); entityManager = manager; } @Override public List getAll() { Query query = entityManager.createQuery("from MyData"); @SuppressWarnings("unchecked") List list = query.getResultList(); entityManager.close(); // TODO Auto-generated method stub return list; } } |
このクラスがデータアクセスクラスであることを示しています。
クラスの最初に宣言してあるEntityManagerはエンティティを利用するために必要な機能を提供します。 基本的にエンティティを扱う場合はEntityManagerを用意することから始めるそうです。 エンティティを取得するためにここではQueryクラスを利用しています。
1 | Query query = entityManager.createQuery("from MyData"); |
QueryクラスはSQLでデータを問い合わせるためのクエリー文に相当する機能をもつオブジェクトです。 createQueryの引数はJPQLという言語が使われ ているそうで、SQLに似た形の構文をしています。 QueryインスタンスにそのJPQLによるクエリー分を指定し呼び出します。 from MyDataというのはselect * from mydataに相当するJPQLのクエリー文 MySQLを少しかじっていた身としてはとてもわかりやすいです。
1 | List list = query.getResultList(); |
getResultListメソッドによりクエリーの実行結果をlistに代入しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | package com.transonic.springboot; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.springframework.stereotype.Controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; import javax.annotation.PostConstruct; import java.util.Optional; @Controller public class RepoController { @Autowired MyDataRepository repository; @PersistenceContext EntityManager entityManager; MyDataDaoImpl dao; @PostConstruct public void init() { dao = new MyDataDaoImpl(entityManager); // 1つ目のダミーデータ作成 MyData d1 = new MyData(); d1.setName("あんぱんまん"); d1.setAge(24); d1.setMail("anp-man@xx.jp"); d1.setMemo("222-2222-2222"); repository.saveAndFlush(d1); // 1つ目のダミーデータ作成 MyData d2 = new MyData(); d2.setName("めろんぱんなちゃん"); d2.setAge(15); d2.setMail("melon@pan.com"); d2.setMemo("333-3333-3333"); repository.saveAndFlush(d2); // 1つ目のダミーデータ作成 MyData d3 = new MyData(); d3.setName("どきんちゃん"); d3.setAge(18); d3.setMail("dokinchan@kin.world"); d3.setMemo("111-1111-1111"); repository.saveAndFlush(d3); } @RequestMapping(value="/", method=RequestMethod.GET) public ModelAndView index(ModelAndView mav) { mav.setViewName("index"); mav.addObject("msg","This is a MyData sample."); Iterable list = dao.getAll(); mav.addObject("datalist",list); return mav; } } |
このアノテーションがついたフィールドにはすでに生成されている同じ型のインスタンスが自動的に渡されます。
@PostConstructはコンストラクタによりインスタンスが生成された後に呼び出されるメソッドです。ここで、データベースに初期値として3つのデータを登録しています。
ここではEntityManagerのフィールドを用意しています。 Spring Bootは起動時にEntityManagerのオブジェクトを生成します。 @PersistenceContextのアノテーションをつけることにより、自動でこのフィールドに割り当てられます。
indexメソッドでは先ほど実装したDAOクラスであるMyDataDaoImplクラスのgetAllメソッドを呼び出して、結果をaddObjectして返します。
実装は以上です。ビルドして、ブラウザからindexにアクセスすると、データの一覧が表示されます。