※当サイトの記事には、広告・プロモーションが含まれます。

Spring BootでMyBatisを使えるMyBatis-Spring-Boot-Starterを使ってみる

nazology.net

⇧ amazing...

MyBatisとは?

GitHubで公開されてるドキュメントによると、

github.com

The MyBatis SQL mapper framework makes it easier to use a relational database with object-oriented applications. MyBatis couples objects with stored procedures or SQL statements using an XML descriptor or annotations. Simplicity is the biggest advantage of the MyBatis data mapper over object relational mapping tools.

https://github.com/mybatis/mybatis-3

Java向けの「ORM(Object-relational mapping)」の1つかと。

「ORM(Object-relational mapping)」と言うと、

オブジェクト関係マッピングObject-relational mappingO/RMORM)とは、データベースオブジェクト指向プログラミング言語の間の非互換なデータを変換するプログラミング技法である。オブジェクト関連マッピングとも呼ぶ。

オブジェクト関係マッピング - Wikipedia

⇧ ということらしい。

mybatis.org

MyBatis はカスタム SQL、ストアドプロシージャ、高度なマッピング処理に対応した優れた永続化フレームワークです。 MyBatisを使うことで、直接 JDBC を扱うコードを書いたり、クエリ引数やクエリ結果を手動で設定する必要がほとんどなくなります。 MyBatis の設定やデータベースレコードと Java オブジェクトの関連付けは、XML またはアノテーションを使って行うことができます。

MyBatis – MyBatis 3 | イントロダクション

XML以外にもアノテーションでも使えるんですね、XMLを使ってる例が多いイメージがあるけど。

qiita.com

以前は iBATIS という名前で Apache プロジェクトの1つとして開発されていた。
しかし、 2010年6月に Apache ソフトウェア財団での開発が中止され、現在は MyBatis という名前で開発されている。

MyBatis 使い方メモ - Qiita

Apacheソフトウェア財団の手を離れても開発は継続されているようですかね。

MyBatis-Springとは?

公式のドキュメントによると、

mybatis.org

MyBatis-Spring integrates MyBatis seamlessly with Spring. This library allows MyBatis to participate in Spring transactions, takes care of building MyBatis mappers and SqlSessions and inject them into other beans, translates MyBatis exceptions into Spring DataAccessExceptions, and finally, it lets you build your application code free of dependencies on MyBatis, Spring or MyBatis-Spring.

https://mybatis.org/spring/index.html

Spring Frameworkとの連携に特化してるってことなんですかね?

github.com

MyBatis-Spring adapter is an easy-to-use Spring bridge for MyBatis sql mapping framework.

GitHub - mybatis/spring: Spring integration for MyBatis 3

⇧ う~む、分からん...

Spring Frameworkに特化ということなんだろうか?

MyBatis-Spring-Boot-Starterとは?

GitHubで公開してるドキュメントによりますと、

github.com

MyBatis Spring-Boot-Starter will help you to use MyBatis with Spring Boot

GitHub - mybatis/spring: Spring integration for MyBatis 3

⇧ Spring BootでMyBatisを使う用途に特化したものらしい。

何か、

github.com

Apacheソフトウェア財団の手を離れたからなのかは分からないですが、様々なプロジェクトが入り乱れてる感があるよね...

Spring BootでMyBatisを使えるMyBatis-Spring-Boot-Starterを使ってみる

というわけで、

github.com

qiita.com

medium-company.com

⇧ 上記サイト様を参考に使ってみる。

まぁ、公式のドキュメントの情報の足りないことこの上ない...

データベースはPostgreSQLを使っていきます。

テーブルなどは、

ts0818.hatenablog.com

⇧ 上記の記事と同じものを利用していきます。

EclipseでSpring Bootなプロジェクトを作成で。

ビルドツールは、Gradleを使いたいので、「タイプ:」を「Gradle Project」で。

依存関係で「Spring Data JPA」は外します。

Spring Bootなプロジェクトが作成されました。

build.gradleにmybatis-spring-boot-starterの依存関係を追加。

plugins {
	id 'org.springframework.boot' version '2.7.5'
	id 'io.spring.dependency-management' version '1.0.15.RELEASE'
	id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	// https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter
    implementation group: 'org.mybatis.spring.boot', name: 'mybatis-spring-boot-starter', version: '2.2.2'
	compileOnly 'org.projectlombok:lombok'
	developmentOnly 'org.springframework.boot:spring-boot-devtools'
	runtimeOnly 'org.postgresql:postgresql'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
	useJUnitPlatform()
}

で、application.propertiesにデータベースの接続設定を追記。

# データベース接続
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5434/test
spring.datasource.username=postgres
spring.datasource.password=postgres

# MyBatisでEntityクラスのフィールド名とデータベースのテーブルのカラム名の対応
mybatis.configuration.map-underscore-to-camel-case=true

⇧ 接続情報をご自分の環境に合わせてください。

まずは、Entityクラスを作成。

■/mybatis-example/src/main/java/com/example/demo/entity/ShikokuOhenro.java

package com.example.demo.entity;

import lombok.Data;

@Data
public class ShikokuOhenro {

  private Long id;
  
  private String nameFudasyo;
  
  private String kanaNameFudasyo;
  
  private String romeNameFudasyo;
  
  private String nameTemple;
  
  private String kanaNameTemple;
  
  private String romeNameTemple;
  
  private Long prefecturesId;
  
}

JPAJava Persistence API)の時とは違い、@Entityアノテーションは不要。

続いてRepositoryインターフェイスを作成。MyBatisではMapperになるらしい。

■/mybatis-example/src/main/java/com/example/demo/repository/ShikokuOhenroMapper.java

package com.example.demo.repository;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import com.example.demo.entity.ShikokuOhenro;

@Mapper
public interface ShikokuOhenroMapper {

	@Select("select * from shikoku_ohenro where id = #{id}")
	ShikokuOhenro findById(@Param("id") Long id);
	
	@Select("select * from shikoku_ohenro")
	List<ShikokuOhenro> findAll();
}    

続いてServiceクラスを作成

package com.example.demo.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.demo.entity.ShikokuOhenro;
import com.example.demo.repository.ShikokuOhenroMapper;

@Service
public class ShikokuOhenroServiceImpl {

	@Autowired
	private ShikokuOhenroMapper shikokuOhenroMapper;
	
	public ShikokuOhenro findById(Long id) {
		return shikokuOhenroMapper.findById(id);
	}
	
	public List<ShikokuOhenro> findAll() {
		return shikokuOhenroMapper.findAll();
	}
}

RestControllerを作成

■/mybatis-example/src/main/java/com/example/demo/controller/ShikokuOhenroController.java

package com.example.demo.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import com.example.demo.entity.ShikokuOhenro;
import com.example.demo.service.ShikokuOhenroServiceImpl;

@RestController
public class ShikokuOhenroController {

	@Autowired
	private ShikokuOhenroServiceImpl shikokuOhenroServiceImpl;
	
	@GetMapping("find/{id}")
	public ShikokuOhenro findById(@PathVariable("id") Long id) {
		return shikokuOhenroServiceImpl.findById(id);
	}
	
	@GetMapping("find-all")
	public List<ShikokuOhenro> findAll() {
		return shikokuOhenroServiceImpl.findAll();
	}
}

で保存。

追加、追記したファイルは以下のような感じ。

諸々、用意できたら、アプリケーションを実行してみる。

ブラウザから、ControllerクラスのメソッドのURLにアクセスすると、

⇧ データベースのテーブルからデータが取得できてます。

XMLを使わなくてもMyBatisでデータ取得できるのは知らなんだけど、MyBatisもJPAJava Persistence API)に劣らず使い方が複雑な気がしますかね...

XML使う方法だと、MyBatis流の記述で覚えることが多そうなのよね...

Spring BootでMyBatis使う場合、XMLアノテーションのどっちが主流派なんですかね?

一応、

stackoverflow.com

アノテーションでも、JOINとか使えるみたいだけど、JPAJava Persistence API)のnativeQueryみたいに、普通のSQLに対応できるなら、一層、XML使いたくない気はするけども、ネットの情報が圧倒的にXMLを利用してるのが多いんよね...。

2022年11月9日(水)追記:↓ ここから

JOINを試してみます。areaテーブル作成

create table public.area (
  id integer not null
  , name_area character varying(20) not null
  , kana_name_area character varying(50) not null
  , rome_name_area character varying(50) not null
  , created timestamp(6) with time zone default CURRENT_TIMESTAMP
  , updated timestamp(6) with time zone
  , is_deleted boolean default false
  , primary key (id)
);

areaテーブルにデータ追加

-- エリアデータ
INSERT INTO area (id, name_area, kana_name_area, rome_name_area)
 VALUES(1, '北海道地方', 'ほっかいどうちほう', 'hokkaido chihou')
 ,(2, '東北地方', 'とうほくちほう', 'touhoku chihou')
 ,(3, '関東地方', 'かんとうちほう', 'kantou chihou')
 ,(4, '中部地方', 'ちゅうぶちほう', 'chubu chihou')
 ,(5, '近畿地方', 'きんきちほう', 'kinki chihou')
 ,(6, '中国・四国地方', 'ちゅうごく・しこくちほう', 'chugoku sikoku chihou')
 ,(7, '九州地方', 'きゅうしゅうちほう', 'kyushu chihou');    

で、Entityクラス作成

■/mybatis-example/src/main/java/com/example/demo/entity/Area.java

package com.example.demo.entity;

import lombok.Data;

@Data
public class Area {
  private Long id;
  
  private String nameArea;
  
  private String kanaNameArea;
  
  private String romeNameArea;
  
}
    

前に作っていたテーブルのEntityクラスも追加。

■/mybatis-example/src/main/java/com/example/demo/entity/Prefectures.java

package com.example.demo.entity;

import lombok.Data;
@Data
public class Prefectures {
	private Long id;
	
	private String namePrefecture;
	
	private String kanaNamePrefecture;
	
	private String romeNamePrefecture;
	
	private String namePrefecturalCapital;
	
	private String kanaNamePrefecturalCapital;
	
	private String romeNamePrefecturalCapital;
	
	private Long areaId;
}
    

JOINした時のEntityクラスを作成。

■/mybatis-example/src/main/java/com/example/demo/entity/custom/CustomShikokuOhenro.java

package com.example.demo.entity.custom;

import lombok.Data;

@Data
public class CustomShikokuOhenro {
	private Long id;

	private String namePrefecture;

	private String kanaNamePrefecture;

	private String romeNamePrefecture;

	private String namePrefecturalCapital;

	private String kanaNamePrefecturalCapital;

	private String romeNamePrefecturalCapital;

	private Long areaId;

	private String nameFudasyo;

	private String kanaNameFudasyo;

	private String romeNameFudasyo;

	private String nameTemple;

	private String kanaNameTemple;

	private String romeNameTemple;

	private Long prefecturesId;

	private String nameArea;

	private String kanaNameArea;

	private String romeNameArea;
}
    

Repositoryクラスの作成

■/mybatis-example/src/main/java/com/example/demo/repository/CustomShikokuOhenroMapper.java

package com.example.demo.repository;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import com.example.demo.entity.custom.CustomShikokuOhenro;

@Mapper
public interface CustomShikokuOhenroMapper {

	@Select("SELECT "
			+ "so.id "
			+ ",so.name_fudasyo "
			+ ",so.kana_name_fudasyo "
			+ ",so.rome_name_fudasyo "
			+ ",so.name_temple "
			+ ",so.kana_name_temple "
			+ ",so.rome_name_temple "
			+ ",so.prefectures_id "
			+ ",ps.name_prefecture "
			+ ",ps.kana_name_prefecture "
			+ ",ps.rome_name_prefecture "
			+ ",ps.name_prefectural_capital "
			+ ",ps.kana_name_prefectural_capital "
			+ ",ps.rome_name_prefectural_capital "
			+ ",ps.area_id "
			+ ",a.name_area "
			+ ",a.kana_name_area "
			+ ",a.rome_name_area "
			+ "FROM shikoku_ohenro so "
			+ "LEFT JOIN prefectures ps "
			+ "ON so.prefectures_id = ps.id "
			+ "LEFT JOIN area a "
			+ "ON ps.area_id = a.id")
	List<CustomShikokuOhenro> findShikokuOhenroAndPrefecture();
}

Serviceクラスの追加。

■/mybatis-example/src/main/java/com/example/demo/service/CustomShikokuOhenroServiceImpl.java

package com.example.demo.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.demo.entity.custom.CustomShikokuOhenro;
import com.example.demo.repository.CustomShikokuOhenroMapper;

@Service
public class CustomShikokuOhenroServiceImpl {

	@Autowired
	private CustomShikokuOhenroMapper customShikokuOhenroMapper;
	
	public List<CustomShikokuOhenro> findShikokuOhenroAndPrefectures() {
		return customShikokuOhenroMapper.findShikokuOhenroAndPrefecture();
	}
	
}

Controllerクラスに追記

■/mybatis-example/src/main/java/com/example/demo/controller/ShikokuOhenroController.java

package com.example.demo.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import com.example.demo.entity.ShikokuOhenro;
import com.example.demo.entity.custom.CustomShikokuOhenro;
import com.example.demo.service.CustomShikokuOhenroServiceImpl;
import com.example.demo.service.ShikokuOhenroServiceImpl;

@RestController
public class ShikokuOhenroController {

	@Autowired
	private ShikokuOhenroServiceImpl shikokuOhenroServiceImpl;
	
	@Autowired
	private CustomShikokuOhenroServiceImpl customShikokuOhenroServiceImpl;
	
	@GetMapping("find/{id}")
	public ShikokuOhenro findById(@PathVariable("id") Long id) {
		return shikokuOhenroServiceImpl.findById(id);
	}
	
	@GetMapping("find-all")
	public List<ShikokuOhenro> findAll() {
		return shikokuOhenroServiceImpl.findAll();
	}
	
	@GetMapping("find-shikoku-ohenro-and-prefectures")
	public List<CustomShikokuOhenro> findShikokOhenroAndPrefectures() {
		return customShikokuOhenroServiceImpl.findShikokuOhenroAndPrefectures();
	}
}
    

で、ファイルの構成とかは以下になりました。

アプリケーションを起動して確認してみる。

⇧ テーブルの情報が取得できました。

MyBatisでアノテーションを使った場合でも通常のSQLのようにJOINとか使えるみたいですね。

2022年11月9日(水)追記:↑ ここまで

毎度モヤモヤ感が半端ない...

今回はこのへんで。