MyBatisでSQLをXMLに記入する！（初心者向け）

現在学習中のSpring bootで、SQLをXMLに記入し、Mybatisと合わせて利用することを学んだので、アウトプットも兼ねて投稿します。

## MyBatisとは
DB（データベース）にアクセスできるフレームワークのこと。
Spring bootには他にもSpring data JpaやJPQLといったSQLを扱うライブラリやクエリ言語があるが、大きな違いとしては以下の通り。

>①SQLをガッツリ書く必要がある。
>②DBMSを意識する必要がある。（DBMSによってかけるSQLが異なるから）
>③①、②を意識するためにSQLの知識が必要。

MyBatisは完全なORMでは無いのでSQLを手書きする必要があるが、より複雑なSQLも実行することができる利点がある。

## なぜXMLに記入するの？
MyBatisを利用するだけでも、アノテーションを用いて複雑なSQLを記入することはできます。
しかし、複雑なSQLをアノテーションを用いて記入しようとすると以下のようなデメリットもあります。

>①可読性が悪くなる。
>②アノテーション固有の制限もあって若干使いづらくなる

用途に合わせて使い分けられれば強いですね✨

## 実際に書いてみた

今回の手順は以下の通りで進めていきます。

>１）プロジェクトの作成
>２）MyBatipseのインストール
>３）XMLファイルの作成
>４）各クラスの作成
>５）SQLの設定
>６）application.propertiesを編集
>７）schema.sqlファイルの作成

### プロジェクトの作成

新規作成　→ Springスタータープロジェクト　でプロジェクトを作成します。
設定は以下の通りです。

![スクリーンショット 2022-05-21 11.13.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754263/24375362-354b-80ac-f536-3b26c8bbacd2.png)

依存関係は以下を選択します。

![スクリーンショット 2022-05-21 11.22.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754263/d2e08bad-cabb-d7d1-33c6-aec8e66427f4.png)

これでプロジェクトの作成は完了です。


## MyBatipseのインストール

mybatipseは、XMLファイルの編集などを補助するプラグインです。

### インストール方法
メニュー「ヘルプ」　→ 「Eclipseマーケットプレース」をクリック。　→

検索欄で「Mybatipse」を検索 　→ インストールをクリック。

![スクリーンショット 2022-05-21 11.33.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754263/90d4bf3f-445c-2abc-d1b0-ba6865c91765.png)

その後、
「使用条件に同意」　→ 「完了」　→　「インストール」　→ 「今すぐ再起動」

ここまででMyBatipseのインストールは完了です。


## XMLファイルの作成。
「src/main/resources」ディレクトリ内にXMLファイルを作成。

### 作成方法
src/main/resourcesを右クリック　→ その他を選択

→MyBatis内の「MyBatis XML Mapper」を選択。

以下のように設定し、XMLファイルを作成します。
※親フォルダーを入力している点に注意！！

![スクリーンショット 2022-05-21 11.48.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754263/979d7d1d-f4bd-86aa-134c-03b40f9ad1a5.png)

## 各クラスの作成

### Model

```java
package dev.itboot.mb.Model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
@Entity
public class User {
	
	@Id
	@GeneratedValue
	private Long id;
	
	@NotBlank
	@Size(max = 50)
	private String name;

}
```

### Mapper

```java
package dev.itboot.mb.repository;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;

import dev.itboot.mb.Model.User;

@Mapper
public interface SampleMapper {
	
	//全件取得
	List<User> selectAll();
	
	//１件取得
	User selectByPrimaryKey(Long id);
	
	//登録
	int insert(User user);
	
	//更新
	int updateByPrimaryKey(User user);
	
	//削除
	int deleteByPrimaryKey(Long id);
}
```

#### 解説

@Mepper → マッパーであることを示すアノテーションです。

insert、update、deleteのメソッドには、引数をintになっています。
Mybatisの標準では、これらのメソッドは<font color="Red">処理した件数</font>を返すようになっているからです。
戻り値は他にも、なし「void」、真偽「true」を選ぶことができます。
```java
    //登録
	void insert(User user);

   //登録　（成功した場合、trueを返す)
   boolean insert(User user)
```

### Service

```java
package dev.itboot.mb.service;


import java.util.List;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import dev.itboot.mb.Model.User;
import dev.itboot.mb.repository.SampleMapper;
import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
@Transactional
public class SampleService {
	
	private final SampleMapper mapper;
	
	//全件取得
	public List<User> selectAll(){ 
		
		return mapper.selectAll();
	}
	
	//１件取得
	public User selectByPrimarykey(Long id) {
		
		return mapper.selectByPrimaryKey(id);
	}
	
	//登録
	public void save(User user) {
		
		if(user.getId() == null) {
			mapper.insert(user);
		}else {
			mapper.updateByPrimaryKey(user);
		}
	}
	
	//削除
	public void deletebyPrimaryKey(Long id) {
	
		mapper.deleteByPrimaryKey(id);
	}

}
```

#### 解説

@Service → クラスがServiceであることを示すアノテーションです。

サービスはビジネスロジック層を表します。
※ビジネスロジック　→ 業務に関わる処理を行う層。例えば、SQLで取得した値に応じてJava側何らかの処理を行いたい場合、このService層でその処理を記述するということ。

トランザクション処理にすると、DB処理をまとめて一貫性を持たせることができます。
サービス層ではその一貫性を持たせるために、@Transactional　アノテーションをつけることが主流です。

※トランザクション処理　→ 分割できない一連の処理、流れのこと。

### Controller
```java
package dev.itboot.mb.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;

import dev.itboot.mb.Model.User;
import dev.itboot.mb.service.SampleService;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Controller
public class SampleController {
	
	final private SampleService service;
	
	@GetMapping("/")
	public String top(Model model) {
		
		model.addAttribute("users" , service.selectAll());
		
		//トップページへ遷移
		return "index";
	}
	
	
	@GetMapping("/add")
	public String add(@ModelAttribute User user) {
		
		//登録用ページに遷移
		return "form";
	}
	
	@PostMapping("/add")
	public String insert(@Validated @ModelAttribute User user, BindingResult result) {
		
		if(result.hasErrors()) {
			return "form";
		}
		
		service.save(user);
		
		return "redilect:/";
	}
	
	@GetMapping("/edit/{id}")
	public String edit(@PathVariable Long id, Model model) {
		
		model.addAttribute("user", service.selectByPrimarykey(id));
		
		return "form";
	}
	
	@GetMapping("/delete/{id}")
	public String delete(@PathVariable Long id) {
		
		service.deletebyPrimaryKey(id);
		
		return "redilect:/";
	}

}
```

## SQLの設定
XMLファイルを以下のように設定していきます。

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="dev.itboot.mb.repository.SampleMapper">

<!-- 全件取得 -->
<select id="selectAll" resultType="User">
	select * from user;
</select>


<!-- １件取得 -->
<select id="selectByPrimaryKey" resultType="User">
	select * from user
	where id = #{id}
</select>


<!-- 登録 -->
<insert id="insert">
	insert into user(user_name)
	values(#{name})
</insert>


<!-- 更新 -->
<update id="updateByPrimaryKey">
	update user
	set name = #{name}
	where id = #{id}
</update>


<!-- 削除 -->
<delete id="deleteByPrimaryKey">
	delete from user
	where id = #{id}
</delete>

</mapper>
```
#### 解説
SQLはタグ内に記入します。このとき、
id → java側のメソッド名と同じものにします。
resultType → 戻り値の型を記入します。コレクションを返す場合、中のオブジェクトを指定します。

resultMapタグを使用すれば、resultMapを返すことも可能です。
```xml
<resultMap id="user" type="User">
  <id column ="id" property="id"/>
  <result column ="name" property="name"/>
</resultMap>


<select id="selectAll" resultType="user">
  select * from user;
</select>
```

## application.propertiesを編集
```properties
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.type-aliases-package=dev.itboot.mb.model

#Add
spring.datasource.url=jdbc:h2:mem:testdb
```

#### 解説
#### <font color="red">mybatis.configuration.map-underscore-to-camel-case</font>

Javaのフィールド名にDBのカラム名をマッピングします。（キャメルケースにアンダースコアをマップします。）

#### <font color="red">mybatis.type-aliases-package</font>
ここにはmodelのパッケージ名を記載します。
この設定を行うことで、XMLのresultTypeに記入するパッケージ名を省略することができます。

```xml
<!-- 設定あり -->
<select id="selectAll" resultType="User">

<!-- 設定なし -->
<select id="selectAll" resultType="dev.itboot.mb..model.User">
```



#### <font color="red">spring.datasource.url</font>
DBの接続先URLを設定します。
今回はH２を使用します。


## schema.sqlファイルの作成
schema.sqlでH2にDBを作成します。

```SQL
create table if not exists user (
	id bigint not null auto_increment primary key,
	name varchar(60) not null
);
```


以上で設定は終了になります！
Viewの設定は今回は省略します。

Mybatisとアノテーションだけを使用してSQLを実行することは可能ですが、SQL文の記入のしづらさがやはりネックになると思います。
個人的にもXMLに記入する方法がおすすめです！

## 参考文献

https://qiita.com/NagaokaKenichi/items/a279857cc2d22a35d0dd

https://wa3.i-3-i.info/word142.html

#### 前回投稿した参考記事

https://qiita.com/TaikiTkwkbysh/items/9f598ed01c363b59fd98