Mybatis源碼分析之代碼先行【一條命途多舛的SQL】

前兩篇我們已經學習了JDBC的執行流程,我們也嘗試了抽取公共方法的方式,減少代碼冗餘和複雜度,但是還是很不滿意,那麼今天我們就學習一下Mybatis,看看他是怎麼封裝,怎麼運行,怎麼實現的。學習之前,我們先來體驗一把,就好比你買了一輛跑車,肯定是先飈幾下,然後好奇它是怎麼運作的,每個組件之間又是怎麼協作的,再其次就要考慮怎麼去改裝它,所以我們今天的任務就是先結合Springboot把Mybatis運行起來,看看效果。

我們看定義配置文件,主要是數據的配置和 mybatis的簡單配置,後期mybatis的複雜配置會一一道來

# 配置服務器信息
server:
  port: 8080

# 配置數據庫相關信息
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 123456
    url: jdbc:mysql://192.168.31.33:3306/test?useUnicode=true&characterEncoding=utf-8

# 配置mybatis
mybatis:
  # 設置別稱
  type-aliases-package: com.lwl.mybatis.day**
  # 配置mapper文件
  mapper-locations: classpath:mapper/**/*.xml

我們再定義一個Role類,來實現數據庫映射,BaseModel類在之前已經有複用了,如果不清楚可以查看前一篇

/**
 * @description: 角色信息
 * @author     :lwl
 * @date       :2020/6/25 11:12
 * @version:     1.0.0
 */
@Data
@Accessors(chain = true)
public class Role extends BaseModel {

    private String name;

    private String remark;

    @Override
    public String toString() {
        return "Role{" +
                "name='" + name + '\'' +
                ", remark='" + remark + '\'' +
                "} " + super.toString();
    }
}

有了角色類之後,我們要定義接口,及它的實現類,都是比較簡單的增刪改查

import java.util.List;

public interface IRoleService {

    int insert(Role role);

    int update(Role role);

    int delOne(long id);

    Role findOne(long id);

    List<Role> list();

}
@Service
public class RoleServiceImpl implements IRoleService {

    @Resource
    private RoleMapper roleMapper;

    @Override
    public int insert(Role role) {
        return roleMapper.insert(role);
    }

    @Override
    public int update(Role role) {
        return roleMapper.update(role);
    }

    @Override
    public int delOne(long id) {
        return roleMapper.delOne(id);
    }

    @Override
    public Role findOne(long id) {
        return roleMapper.findOne(id);
    }

    @Override
    public List<Role> list() {
        return roleMapper.list();
    }
}

Role的接口實現類中有一個RoleMapper接口類,這個類就是會操作數據庫的關鍵,是通過代理模式,具體我們後期慢慢講


public interface RoleMapper {

    int insert(Role role);

    int update(Role role);

    int delOne(long id);

    Role findOne(long id);

    List<Role> list();


}

代碼都已經寫完了,我們就要再寫一個sql語句的mapper.xml文件,將我們要運行的sql寫在裏面,通過註解的方式也可以實現,不過爲了後期維護和優化,複雜的sql建議還是寫在mapper.xml中,比如動態SQL、多表級聯查詢。

<?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="com.lwl.mybatis.day2.mapper.RoleMapper">
    <resultMap id="BaseResultMap" type="com.lwl.mybatis.day2.domain.Role">
        <id column="id" property="id"/>
        <result column="create_user"  property="createUser"/>
        <result column="create_time"  property="createTime"/>
        <result column="modify_user"  property="modifyUser"/>
        <result column="modify_time"  property="modifyTime"/>


        <result column="name"  property="name"/>
        <result column="remark"  property="remark"/>
    </resultMap>

    <insert id="insert" parameterType="com.lwl.mybatis.day2.domain.Role">
        insert into role (name, remark, create_time) value (#{name}, #{remark}, now())
    </insert>

    <delete id="delOne" parameterType="long">
        delete from role where  id = #{id}
    </delete>

    <select id="findOne" parameterType="long" resultMap="BaseResultMap">
         select * from role where  id = #{id}
    </select>

    <select id="list" resultMap="BaseResultMap">
         select * from role
    </select>

    <update id="update" parameterType="Role">
        update role set name = #{name} , remark = #{remark}, modify_time = now()
            where id = #{id}
    </update>

</mapper>

好了,一切準備就緒了,我們再寫一個測試類,讓他們運行起來,看看效果

package com.lwl.mybatis.day2;

import com.lwl.mybatis.day2.domain.Role;
import com.lwl.mybatis.day2.service.IRoleService;
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.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@WebAppConfiguration
public class RoleTest {

    @Autowired
    private IRoleService roleService;

    @Test
    public void addTest() {
        Arrays.stream(new int[]{1, 2, 3, 4}).forEach(r->{
            Role role = new Role();
            role.setName("lwl"+r).setRemark("哈哈哈哈哈 => " + r);
            roleService.insert(role);
        });

        /**
         * 運行結果:
         * 2020-06-26 12:10:17 | DEBUG | main | com.lwl.mybatis.day2.mapper.RoleMapper.insert | ==>
         *      Preparing: insert into role (name, remark, create_time) value (?, ?, now())
         *
         * 2020-06-26 12:10:17 | DEBUG | HikariPool-1 housekeeper | com.zaxxer.hikari.pool.HikariPool |
         *  HikariPool-1 - Pool stats (total=1, active=1, idle=0, waiting=0)
         *
         * 2020-06-26 12:10:17 | DEBUG | main | com.lwl.mybatis.day2.mapper.RoleMapper.insert | ==>
         *      Parameters: lwl1(String), 哈哈哈哈哈 => 1(String)
         * 2020-06-26 12:10:17 | DEBUG | main | com.lwl.mybatis.day2.mapper.RoleMapper.insert | <==
         *
         *  Updates: 1
         */
    }

    @Test
    public void  delOne() {
        int i = roleService.delOne(2);
        System.out.println("運行結果:" + (i!=0));
    }

    @Test
    public void  update() {
        Role role = new Role();
        role.setName("噢噢噢噢").setRemark("12311415").setId(3L);
        int i = roleService.update(role);
        System.out.println("運行結果:" + (i!=0));
    }

    @Test
    public void findOneTest() {
        Role one = roleService.findOne(1);
        System.out.println(Optional.ofNullable(one).toString());
    }

    @Test
    public void list() {
        List<Role> list = roleService.list();
        System.out.println("運行結果:");
        list.forEach(System.out::println);
        /**
         * Role{name='lwl1', remark='哈哈哈哈哈 => 1'}
         *      BaseModel(id=5, createUser=null,createTime=Fri Jun 26 12:10:16 CST 2020, modifyUser=null,modifyTime=null)
         * Role{name='lwl2', remark='哈哈哈哈哈 => 2'}
         *      BaseModel(id=6, createUser=null,createTime=Fri Jun 26 12:10:16 CST 2020, modifyUser=null,modifyTime=null)
         * Role{name='lwl3', remark='哈哈哈哈哈 => 3'}
         *      BaseModel(id=7, createUser=null,createTime=Fri Jun 26 12:10:16 CST 2020, modifyUser=null,modifyTime=null)
         * Role{name='lwl4', remark='哈哈哈哈哈 => 4'}
         *      BaseModel(id=8, createUser=null,createTime=Fri Jun 26 12:10:16 CST 2020, modifyUser=null,modifyTime=null)
         *
         */
    }

}

如果運行過程中出現找不到RoleMapper這類的時候,請在啓動類上加上mapper的掃描註解,其中@MapperScan 掃描包的範圍不能太大,太大的話會到期其他類被多次注入,這樣又會出去其他問題,比如測試類中的 private IRoleService roleService; 會出現多個

@SpringBootApplication
@MapperScan("com.lwl.mybatis.day2.mapper")
public class LwlMybatisApplication {

	public static void main(String[] args) {
		SpringApplication.run(LwlMybatisApplication.class, args);
	}

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章