カツオ !

起業、転職、サラリーマン生活、Webサービス、アプリ、働き方、プログラミング、Java、JavaScript

IT java

【SpringBoot入門】Spring Boot+JPAで複数テーブル結合処理

投稿日:

SpringBootのプログラミングネタ連投で失礼します。

先日、PostgresSQL+SpringBootでDBアクセスから画面表示までの実装を行いました。

【SpringBoot入門】Spring Boot + PostgreSQLの設定・DB検索

ここでは単独テーブルを利用しています。

現実的にWebアプリケーションを構築するとなると、複数テーブルをジョインしてデータ取得を行う必要があります。今回は複数テーブルを使ったデータアクセスをやってみたいと思います。

PostgresSQLの準備

テーブル作成

--親テーブル
CREATE TABLE client (
id SERIAL PRIMARY KEY,
name text,
mail text, 
memo text
);
--子テーブル
CREATE TABLE orders (
order_num SERIAL PRIMARY KEY,
id int,
order_title text
);

データ登録

--client
insert into client values(1,'山田 太郎','yamada@yama.com','大口のお取引先');
insert into client values(2,'鈴木 花子','suzuki@hanako.com','とても美人');
insert into client values(3,'田中 大輔','tanaka@daisuke.com','若くて優秀');
insert into client values(4,'伊藤 カイジ','kaizi@ito.com','負債者。お金がない。');
insert into client values(5,'大槻 ハンチョウ','hancho@kuzu.com','地下の班長');
--orders
insert into orders values(1,1,'マルゲリータ');
insert into orders values(2,1,'ビスマルク');
insert into orders values(3,1,'ポテト');
insert into orders values(4,2,'コーラ');
insert into orders values(5,2,'カレー');
insert into orders values(6,3,'ハンバーガー');
insert into orders values(7,3,'レバニラ定食');
insert into orders values(8,4,'さんま');
insert into orders values(9,4,'焼き鳥');
insert into orders values(10,5,'Tボーンステーキ');
insert into orders values(11,5,'柿ピー');
insert into orders values(12,5,'柿ピーボール');

clientテーブルに対してordersテーブルが複数ある関係です。

SQLであればを以下を投げればjoinしてレコードを取ってくることができます。

select * from client A , orders B where A.id = B.id;

SpringBootのプログラム修正

前提として先日の記事で作成したプログラムを追記しています。

【SpringBoot入門】Spring Boot + PostgreSQLの設定・DB検索

Clientエンティティモデルの修正

Clients.java

package com.example.demo;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name="client")
public class Client {
@Id
//@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", unique = true, nullable = false)
private Integer id;
@OneToMany(cascade = CascadeType.ALL)
private List<Orders> orders;
@Column(name="name")
private String name;
@Column(name="mail")
private String mail;
@Column(name="memo")
private String memo;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMail() {
return mail;
}
public void setMail(String mail) {
this.mail = mail;
}
public String getMemo() {
return memo;
}
public void setMemo(String memo) {
this.memo = memo;
}
}

Ordersエンティティモデルの追加

Orders.java

package com.example.demo;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name="orders")
public class Orders {
@Id
//@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "order_num", unique = true, nullable = false)
private Integer order_num;
@Column(name = "order_title")
private String order_title;
@ManyToOne
@JoinColumn(name = "id")
private Client client;
public Orders() {
super();
client = new Client();
}
public Client getClient() {
return client;
}
public void setClient(Client client) {
this.client = client;
}
public Integer getOrder_num() {
return order_num;
}
public void setOrder_num(Integer order_num) {
this.order_num = order_num;
}
public String getOrder_title() {
return order_title;
}
public void setOrder_title(String order_title) {
this.order_title = order_title;
}
}
@JoinColumn(name = "id")

こちらのアノテーションを使うことで、テーブルの項目を指定してJoinすることができる。

Ordersリポジトリの追加

OrdersRepository.java

package com.example.demo.repositories;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import com.example.demo.Orders;
@Repository
public interface OrdersRepository extends JpaRepository<Orders, Integer> {
@Query("select max(order_num) from Orders")
public Integer findMaxOrderNum();
}

ここでfindMaxOrderNum()を定義しているが、こちらはOrdersの主キーのMax値を取得するもの。

Insert機能を作成したときにアノテーションだと、キーを+1して登録するって動きをどう実装したらいいかわからなかったので、力技でキーを取得している…

コントローラーの修正

package com.example.demo;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import com.example.demo.repositories.ClientRepository;
import com.example.demo.repositories.OrdersRepository;
@Controller
@DataJpaTest
public class PosgresSampleController {
@Autowired
ClientRepository repository;
@Autowired
OrdersRepository OrdersRepository;
@RequestMapping(value="/",method=RequestMethod.GET)
public ModelAndView index(
@ModelAttribute("formModel") Client tmp ,
ModelAndView mav) {
mav.setViewName("index");
Iterable<Client> list = repository.findAll();
mav.addObject("list",list);
return mav;
}
@RequestMapping(value="/",method=RequestMethod.POST)
@Transactional
public ModelAndView form(
@ModelAttribute("formModel") Client tmp ,
ModelAndView mav) {
tmp.setId(repository.findMaxId()+new Integer(1));
repository.saveAndFlush(tmp);
return new ModelAndView("redirect:/");
}
@RequestMapping(value="/orders",method=RequestMethod.GET)
public ModelAndView orders(
@ModelAttribute("formModel") Orders tmp ,
ModelAndView mav) {
mav.setViewName("orders");
Iterable<Orders> list = OrdersRepository.findAll();
mav.addObject("list",list);
return mav;
}
@RequestMapping(value="/orders",method=RequestMethod.POST)
@Transactional
public ModelAndView form(
@ModelAttribute("formModel") Orders tmp ,
ModelAndView mav) {
tmp.setOrder_num(OrdersRepository.findMaxOrderNum()+new Integer(1));
OrdersRepository.saveAndFlush(tmp);
return new ModelAndView("redirect:/orders");
}
}

ビューの作成

<!DOCTYPE html>
<html>
<head>
<title>orders</title>
<meta http-equiv="Content-Type"
content="text/html; charset=UTF-8" />
<style>
h1 { font-size:18pt; font-weight:bold; color:gray; }
body { font-size:13pt; color:gray; margin:5px 25px; }
tr { margin:5px; }
th { padding:5px; color:white; background:darkgray; }
td { padding:5px; color:black; background:#e0e0ff; }
</style>
</head>
<body>
<h1>注文</h1>
<h2>注文一覧</h2>
<table>
<tr><th>注文番号</th><th>注文内容</th><th>ID</th><th>名前</th></tr>
<tr th:each="obj : ${list}">
<td th:text="${obj.order_num}"></td>
<td th:text="${obj.order_title}"></td>
<td th:text="${obj.client.id}"></td>
<td th:text="${obj.client.name}"></td>
</tr>
</table>
<hr>
<h2>新規注文</h2>
<table>
<form method="post" action="/orders" th:object="${formModel}">
<tr><td><label for="name">ID</label></td>
<td><input type="text" name="client"/></td></tr>
<tr><td><label for="order_title">注文</label></td>
<td><input type="text" name="order_title"  th:value="*{order_title}" /></td></tr>
<tr><td><input type="submit" /></td></tr>
</form>
</table>
</body>
</html>

動作結果

こんな感じでテーブルを結合して取得することができました。登録についても動作しました。

JPAによるテーブルアクセスに正直慣れておらずSQLは自分で書きたいと思いもしますが、これはこれで便利な面もあるのだろうと、ひとまず続けてみようと思います。

-IT, java

執筆者:


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

no image

2020年プログラミング教育必須化で日本はどう変わるのか

日本では2020年にプログラミング教育が小学校で必須化されます。国をあげてIT技術力を高めようとしている意思を感じられ、一応IT業界にいる私としては嬉しく思っています。プログラミングスキルが正当に評価 …

no image

【起業】新規Webサービスの立ち上げは忍耐だ

私もいつかは起業を夢見ているサラリーマンの1人です。新しいWebサービスのアイディアを考えたり、誰かと議論したりするのって本当に楽しいですよね。 アイディアを考えたり、デモを作ってみたりというところま …

no image

【SpringBoot入門】Spring Boot + PostgreSQLの設定・DB検索

この週末にSpringBootの入門書を1冊写経しながら勉強しました。入門書の中ではDBアクセスがHSQLDBのみの例しかなかったので、Webサイトなどを参考にしつつ、PosgresSQLとの接続を試 …

no image

【SpringBoot】faicon(ファビコン)の設定方法

SpringBootの場合、デフォルトだとfavicon(ファビコン)にSpringBootの葉っぱの画像が使われています。さすがにそのままサービスをローンチするわけにもいかないので、favicon( …

no image

【VR】昔夢見たゲームが現実に!VR版ドラクエ

朝何気なくWebニュース見てたら衝撃の記事が!なんとドラクエがVRになるしい。 30代はドラクエ世代ですよね! ドラクエといえば言わずと知れた超人気RPG。というかドラクエがRPGというゲームジャンル …