網頁

2019/2/7

使用SpringBoot打造記帳簿專案(二十)MyBatis測試

本篇會寫一支簡單的測試程式來測試MyBatis。

在前一篇使用SpringBoot打造記帳簿專案(十九)MyBatis設定中已經完成了MyBatis的設定,接著寫一支測試程式來試看看是否能正常工作。


開啟idv.matt.dao.MemberMapper.java,然後新增一個查詢方法selectByNaturalKey()如下:

package idv.matt.dao;

import idv.matt.entity.Member;
import java.util.List;

public interface MemberMapper {

    int deleteByPrimaryKey(Long memberId);

    int insert(Member record);

    Member selectByPrimaryKey(Long memberId);

    Member selectByNaturalKey(String memberAccount); // <-- 新增此方法

    List selectAll();

    int updateByPrimaryKey(Member record);
}

接著開啟idv.matt.mapper.MemberMapper.xml,將MyBatis Generator(MBG)自動產生的<insert id="insert">中的新增SQL修改如下:

<insert id="insert" parameterType="idv.matt.entity.Member">
    insert into member (member_account, member_password,
        member_name, member_status)
    values (#{memberAccount,jdbcType=VARCHAR},
        #{memberPassword,jdbcType=VARCHAR},
        #{memberName,jdbcType=VARCHAR},
        #{memberStatus,jdbcType=VARCHAR})
</insert>

因為先前的資料表設計中,資料表的主鍵id欄位為自動遞增(AUTO_INCREMENT),且create_timeupdate_time欄位預設為新增一筆資料時設為當下時間CURRENT_TIMESTAMP,因此要將MBG自動產生的insert條件中的這些欄位移除。


另外新增一個新的查詢SQL如下,此即為對應剛剛新增的selectByNaturalKey()

<select id="selectByNaturalKey" parameterType="java.lang.String" resultMap="BaseResultMap">
    select member_id, member_account, member_password, member_name,
        member_status, create_time, update_time
    from member
    where member_account = #{memberAccount,jdbcType=VARCHAR}
</select>

因為先前的資料表設計中,資料表的真正主鍵為代理鍵(Surrogate key),其為沒有業務意義的自動累加編號而已,MBG幫我們產生的mapper的selectByPrimaryKey()是以代理鍵為查詢條件,所以沒什麼用處,所以這邊才會新增一個以業務鍵(Natural key)來查詢的方法。


修改完後的idv.matt.mapper.MemberMapper.xml如下:

MemberMapper.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="idv.matt.dao.MemberMapper">
    <resultMap id="BaseResultMap"
        type="idv.matt.entity.Member">
        <id column="member_id" jdbcType="BIGINT" property="memberId" />
        <result column="member_account" jdbcType="VARCHAR"
            property="memberAccount" />
        <result column="member_password" jdbcType="VARCHAR"
            property="memberPassword" />
        <result column="member_name" jdbcType="VARCHAR"
            property="memberName" />
        <result column="member_status" jdbcType="VARCHAR"
            property="memberStatus" />
        <result column="create_time" jdbcType="TIMESTAMP"
            property="createTime" />
        <result column="update_time" jdbcType="TIMESTAMP"
            property="updateTime" />
    </resultMap>
    <delete id="deleteByPrimaryKey"
        parameterType="java.lang.Long">
        delete from member
        where member_id = #{memberId,jdbcType=BIGINT}
    </delete>
    <!-- 修改這個 -->
    <insert id="insert" parameterType="idv.matt.entity.Member">
        insert into member (member_account, member_password,
            member_name, member_status)
        values (#{memberAccount,jdbcType=VARCHAR},
            #{memberPassword,jdbcType=VARCHAR},
            #{memberName,jdbcType=VARCHAR},
            #{memberStatus,jdbcType=VARCHAR})
    </insert>
    <update id="updateByPrimaryKey"
        parameterType="idv.matt.entity.Member">
        update member
        set member_account = #{memberAccount,jdbcType=VARCHAR},
            member_password = #{memberPassword,jdbcType=VARCHAR},
            member_name = #{memberName,jdbcType=VARCHAR},
            member_status = #{memberStatus,jdbcType=VARCHAR},
            create_time = #{createTime,jdbcType=TIMESTAMP},
            update_time = #{updateTime,jdbcType=TIMESTAMP}
            where member_id = #{memberId,jdbcType=BIGINT}
    </update>
    <select id="selectByPrimaryKey"
        parameterType="java.lang.Long" resultMap="BaseResultMap">
        select member_id, member_account, member_password, member_name,
            member_status, create_time,
        update_time
        from member
        where member_id = #{memberId,jdbcType=BIGINT}
    </select>
    <!-- 新增這個 -->
    <select id="selectByNaturalKey"
        parameterType="java.lang.String" resultMap="BaseResultMap">
        select member_id, member_account, member_password, member_name,
            member_status, create_time,
        update_time
        from member
        where member_account = #{memberAccount,jdbcType=VARCHAR}
    </select>
    <select id="selectAll" resultMap="BaseResultMap">
        select member_id, member_account, member_password, member_name,
            member_status, create_time,
        update_time
        from member
    </select>
</mapper>

完成以上修改後,在專案的src/test/java下建立測試程式idv.matt.dao.MemberMapperTest測試類別,用來測試src/main/java下的idv.matt.dao.MemberMapper

MemberMapperTest.java

package idv.matt.dao;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;

import idv.matt.application.MoneynoteApplication;
import idv.matt.entity.Member;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = { MoneynoteApplication.class })
@Transactional
public class MemberMapperTest {

    @Autowired
    private MemberMapper mapper;

    @Test
    @Rollback
    public void testInsert() {
        Member member = new Member();
        member.setMemberAccount("john@abc.com");
        member.setMemberName("John");
        member.setMemberPassword("12345");
        member.setMemberStatus("1");

        mapper.insert(member); // 新增member
        Member result = mapper.selectByNaturalKey(member.getMemberAccount()); // 查詢member
        Assert.assertEquals(result.getMemberAccount(), member.getMemberAccount()); // 斷言相同
    }

}

在測試程式testInsert()上按滑鼠右鍵 -> Run As -> JUnit Test來執行測試程式。

上面的testInsert()做了以下動作:

  • 新增一個Member的物件member
  • 設定member物件的內容。
  • 呼叫MamberMapper.insert()來將此member物件的內容新增至資料庫。
  • 以剛新增的member物件的業務主鍵(Natural key)memberAccount的值查詢moneynote.member資料表。
  • 斷言(Assert)member.memberAccount與查詢出的result.memberAccount的值相同,相同代表通過測試。
  • 交易回滾(rollback)。

測試成功可以在Eclipse的[JUnit]視窗看到以下結果。



此時去觀察資料庫的moneynote.member資料表會發現並沒有資料,因為剛才的新增動作已經被rollback了。這是因為設定Spring的@Transactional搭配@Rollback annotation的效果。

這邊MyBatis的交易是由Spring來管理。

你可試著把@Transactional拿掉,便會發現交易不會被rollback,因此在資料表中可以看到新增的資料。

另外雖然資料回滾了,但如果用上面的方法或在MySQL Workbench手動在member資料表新增一筆資料,你會發現member_id的值是累加後的狀態,也就是說AUTO_INCREMENT欄位並不會rollback。

若要清空資料表,請參考MySQL 如何TRUNCATE有外鍵限制的資料表TRUNCATE後的AUTO_INCREMENT欄位值會重設回1。

或是執行下面指令重設AUTO_INCREMENT

ALTER TABLE `moneynote`.`member` 
AUTO_INCREMENT = 1 ;

接著請參考使用SpringBoot打造記帳簿專案(二十一)打包Spring Boot專案為可執行的jar檔


參考:

沒有留言:

張貼留言