SpringBoot Mybatis マッピング方法


ディレクトリをそろえる


Serviceクラス

ShoppingListService.java
package com.example.householdAccountBook.application.service;
//import 省略

@Service
public class ShoppingListService {
    @Autowired
    ShoppingListMapper shoppingListMapper;
    //買い物リスト全件表示
    public List<ShoppingList>findAll(){
        return this.shoppingListMapper.showShoppingList();
    }
}
ポイント 説明
@Service ビジネスロジックを記載するソース。
mapper(自動生成)を「@Autowired」で宣言し、MyBatisを利用したDBアクセスを行う。
https://www.jcsc.co.jp/tech_blog/archives/21
ビジネスロジック 処理をして、その結果をデータベースに登録するシステム。
https://wa3.i-3-i.info/word13666.html
interfaceとインスタンス化 Mapper.javaにはinterfaceを記述するが、interfaceはインスタンス化できないので、@Autowiredを使う。

Mapperインターフェース

ShoppingListMapper.java
package com.example.householdAccountBook.domain.repository;
import com.example.householdAccountBook.domain.entity.ShoppingList;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;

@Mapper
public interface ShoppingListMapper {
    List<ShoppingList> showShoppingList();
  
  void insertShoppingList(ShoppingList shoppinglist)

    void deleteShoppingList(ShoppingList shoppinglist)
}

Mapper.xml

ShoppingListMapper.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="マッピングするjavaクラスの場所">

        SELECT
            A.history_id,
            CASE WHEN DATE_ADD(A.lasttime_housework_date, INTERVAL(B.interval_day)DAY) = CURRENT_DATE() THEN "本日"
                WHEN DATE_ADD(A.lasttime_housework_date, INTERVAL(B.interval_day)DAY) <![CDATA[ < ]]> CURRENT_DATE() THEN "超過"
                WHEN DATE_ADD(A.lasttime_housework_date, INTERVAL(B.interval_day)DAY) <![CDATA[ > ]]> CURRENT_DATE() THEN ""
            END AS nexttime_schedule_label,
            C.category_name,
            B.housework_name,
            DATE_ADD(A.lasttime_housework_date, INTERVAL(B.interval_day)DAY) AS nexttime_houosework_date,
            DATEDIFF(CURRENT_DATE,DATE_ADD(A.lasttime_housework_date, INTERVAL(B.interval_day)DAY))*-1 AS nexttime_schedule_numerical,
            D.user_name AS lasttime_user
        FROM
            housework_history AS A 
            INNER JOIN housework_works AS B 
                ON A.works_id = B.works_id 
            INNER JOIN housework_category AS C 
                ON B.category_id = C.category_id 
            INNER JOIN housework_users AS D 
                ON A.user_id = D.user_id
        WHERE 
            A.history_id=#{historyId};

    <insert id="insertShoppingList">
        INSERT INTO ShoppingList(
          place,
          category,
          itemName,
          created_at,
          updated_at
        ) value (
          #{place},
          #{category},
          #{itemName},
          now(),
          now(),
        )
    </insert> 

    <delete id="deleteShoppingList">
    DELETE FROM shopping WHERE id = #{id}
    </delete>

</mapper>
項目 説明 記入例
mapper namespace マッピングするjavaクラスの場所 com.example.householdAccountBook.domain.repository.ShoppingListMapper
resultType 結果を詰める箱 com.example.householdAccountBook.domain.entity.ShoppingList
不等式 MyBatisで不当式を書く場合は右記のようにする。 <![CDATA[ < ]]>
<![CDATA[ > ]]>
変数 #{変数名} #{historyId}

【公式】https://mybatis.org/mybatis-3/ja/sqlmap-xml.html

うまくいかない時 insertの戻り値をvoidにしなかった例

エラー 説明 備考
insertMemberInfo' has an unsupported return type insert分をマッピングする際は、戻り値をvoidにしないとエラーとなる。

うまくいかない時 Mapperクラス 二つ以上の引数には@Param

エラー
void insertNewHistory(Integer worksId,Integer userId);
エラー解消
void insertNewHistory(@Param("worksId") Integer worksId,@Param("userId")Integer userId);
エラー内容 原因
org.apache.ibatis.binding.BindingException: Parameter 'worksId' not found. Available parameters are [arg3, arg2, param5, arg4, arg1, arg0, param3, param4, param1, param2] 引数が2つ以上の場合は@Paramが必要

うまくいかない時 戻り値の注意点

例えばSQLでSELECTで抽出したIDなどの数値を戻したい場合でも、戻り値の型をInteger等にするとキャストエラーになる。戻り値は、xmlファイルのresultTypeで指定したEntityクラスの型にしないといけない。(下の例ではHouseworkList型)
下の例ではSELECTで抽出したcategoryIDはあくまでHouseworkListクラスのメンバー変数へ入るので、
戻り値の型はHouseworkList型にして、getter等で取り出して使用する必要がある。

エラー内容 原因
class com.example.householdAccountBook.entity.HouseworkList cannot be cast to class java.lang.Integer HouseworkListをIntegerにキャストできない。

entityクラス

HogeEntity.java
中略
import lombok.Data;

@Data
public class HogeEntity{
  private Integer hogehogeId;
  private String hogehogeName;
}

うまくいかない時

xmlで指定したネームスペースとファイル名が不一致だった例

エラー内容 原因
org.apache.ibatis.builder.BuilderException:
Wrong namespace. Expected 'com.example.demo.mapper.Demomapper' but found 'com.example.demo.mapper.DemoMapper'.
xmlファイルのネームスペースにはDemoMapperと指定しているが、ファイル名がDemomapperになっている

コントローラー→サービスクラス→マッパークラスにアクセスしようとしてもNullPointerExceptionが返ってくる

エラー内容 原因
java.lang.NullPointerException サービスクラスへアクセスする場合は「@AutoWired」でアクセスしなければならない

Listの中身をデバッグする

System.out.println(worksContentsList.get(0).toString());
項目 説明
get(0) Listの要素を指定するにはget(i)を使う
toString() メンバー変数の中身を一気に見ることができる