MyBatis系列第2篇:入門篇缺前,帶你感受一下mybatis獨(dú)特的魅力镀岛!

文章轉(zhuǎn)載自:http://www.itsoku.com/article/246
Mybatis系列目標(biāo):從入門開始開始掌握一個(gè)高級開發(fā)所需要的Mybatis技能霹粥。

這是mybatis系列第2篇坊饶。

本篇技術(shù)棧

  1. mysql5.7.25
  2. maven3.6.1
  3. jdk1.8
  4. idea

本篇主要內(nèi)容

  1. 通過一個(gè)案例感受一下mybatis的強(qiáng)大之處
  2. mybatis開發(fā)項(xiàng)目的具體步驟
  3. 介紹mybatis中主要的幾個(gè)對象

我們先來一個(gè)案例灾搏,讓大家感受一下mybatis是多么的牛逼挫望,我相信大家看了案例之后,會(huì)強(qiáng)烈的激發(fā)大家學(xué)習(xí)mybatis的興趣狂窑。

案例:原來ibatis是這么強(qiáng)大

下面的案例媳板,大家先不用關(guān)系代碼為什么這么寫,先感受一下效果泉哈,后面我們再來細(xì)說代碼拷肌,案例代碼文章尾部有獲取方式到旦。

準(zhǔn)備數(shù)據(jù)庫

mysql中運(yùn)行下面腳本:

/*創(chuàng)建數(shù)據(jù)庫javacode2018*/
DROP DATABASE IF EXISTS `javacode2018`;
CREATE DATABASE `javacode2018`;
USE `javacode2018`;

/*創(chuàng)建表結(jié)構(gòu)*/
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE t_user (
  id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主鍵,用戶id巨缘,自動(dòng)增長',
  `name` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '姓名',
  `age` SMALLINT NOT NULL DEFAULT 1 COMMENT '年齡',
  `salary` DECIMAL(12,2) NOT NULL DEFAULT 0 COMMENT '薪水'
) COMMENT '用戶表';

SELECT * FROM t_user;

上面腳本中添忘,創(chuàng)建了一個(gè)javacode2018數(shù)據(jù)庫,然后創(chuàng)建了一個(gè)用戶表若锁,里面有4個(gè)字段搁骑,id為主鍵自動(dòng)增長。

我們的需求

對t_user表又固,我們有以下這些需求:

  1. 實(shí)現(xiàn)一個(gè)通用的插入操作:支持動(dòng)態(tài)插入仲器,可以根據(jù)傳入的字段的值,動(dòng)態(tài)生成所需要的各種insert語句
  2. 批量插入功能
  3. 實(shí)現(xiàn)一個(gè)通用的更新操作:支持動(dòng)態(tài)更新操作仰冠,可以根據(jù)傳入的字段乏冀,動(dòng)態(tài)生成所需要的各種update語句
  4. 實(shí)現(xiàn)一個(gè)通用的查詢操作:支持各種組合條件查詢、支撐排序洋只、分頁辆沦、支持返回列的控制等各種復(fù)雜的查詢需求

下面我們就來一個(gè)案例,將上面這些需求通過mybatis實(shí)現(xiàn)识虚,先見證一下mybatis的強(qiáng)大之處肢扯。

創(chuàng)建maven項(xiàng)目

idea中創(chuàng)建maven項(xiàng)目,這個(gè)操作在maven系列中已經(jīng)說過很多次了担锤,以后大部分項(xiàng)目都是通過maven來玩的蔚晨,maven這方面玩的不是太溜的,可以跳到文章尾部去看一下maven系列的文章肛循。

項(xiàng)目采用maven中聚合及繼承的方式來管理铭腕。

創(chuàng)建父項(xiàng)目

先創(chuàng)建父項(xiàng)目mybatis-series,父項(xiàng)目的坐標(biāo)信息:

<groupId>com.javacode2018</groupId>
<artifactId>mybatis-series</artifactId>
<version>1.0-SNAPSHOT</version>

創(chuàng)建子項(xiàng)目

創(chuàng)建一個(gè)子模塊chat01多糠,子模塊的坐標(biāo)信息:

<groupId>com.javacode2018</groupId>
<artifactId>chat01</artifactId>
<version>1.0-SNAPSHOT</version>

項(xiàng)目結(jié)構(gòu)

如下圖:

引入mybatis依賴

mybatis-series/pom.xml內(nèi)容如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.javacode2018</groupId>
    <artifactId>mybatis-series</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>chat01</module>
    </modules>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!-- 配置maven編譯的時(shí)候采用的編譯器版本 -->
        <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
        <!-- 指定源代碼是什么版本的累舷,如果源碼和這個(gè)版本不符將報(bào)錯(cuò),maven中執(zhí)行編譯的時(shí)候會(huì)用到這個(gè)配置熬丧,默認(rèn)是1.5笋粟,這個(gè)相當(dāng)于javac命令后面的-source參數(shù) -->
        <maven.compiler.source>1.8</maven.compiler.source>
        <!-- 該命令用于指定生成的class文件將保證和哪個(gè)版本的虛擬機(jī)進(jìn)行兼容怀挠,maven中執(zhí)行編譯的時(shí)候會(huì)用到這個(gè)配置析蝴,默認(rèn)是1.5,這個(gè)相當(dāng)于javac命令后面的-target參數(shù) -->
        <maven.compiler.target>1.8</maven.compiler.target>
        <mybatis.version>3.5.3</mybatis.version>
        <mysql.version>5.1.47</mysql.version>
        <lombok.version>1.18.10</lombok.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>${mybatis.version}</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-classic</artifactId>
                <version>1.2.3</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

chat01/pom.xml內(nèi)容如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>mybatis-series</artifactId>
        <groupId>com.javacode2018</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>chat01</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
        </dependency>
    </dependencies>

</project>

上面我們引入了mybatis需要的包绿淋、mysql jdbc驅(qū)動(dòng)闷畸、lombok、單元測試需要的junit包吞滞、日志輸出需要的logback包佑菩。

這里lombok可能大家沒有用過盾沫,這個(gè)東西可以自動(dòng)幫我們生成javabean的一些代碼,比如get殿漠、set方法赴精,可以節(jié)省開發(fā)編寫代碼的量,這個(gè)以后有空了寫一篇文章來介紹绞幌。

配置logback

mybatis在運(yùn)行過程中會(huì)輸出一些日志蕾哟,比如sql信息、sql的參數(shù)信息莲蜘、執(zhí)行的結(jié)果等信息谭确,mybatis中會(huì)通過logback輸出出來。

chat01/src/main/resources目錄中新建文件logback.xml票渠,內(nèi)容如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <logger name="com.javacode2018" level="debug" additivity="false">
        <appender-ref ref="STDOUT" />
    </logger>
</configuration>

創(chuàng)建mybatis相關(guān)文件

user.xml

chat01/src/main/resources目錄中新建user.xml逐哈,內(nèi)容如下:

<?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.javacode2018.mybatis.chat01.UserMapper">

    <!-- 插入 -->
    <insert id="insert" parameterType="com.javacode2018.mybatis.chat01.UserModel" keyProperty="id" useGeneratedKeys="true">
        <![CDATA[ INSERT INTO `t_user` ]]>
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="id!=null">
                <![CDATA[ `id`, ]]>
            </if>
            <if test="name!=null">
                <![CDATA[ `name`, ]]>
            </if>
            <if test="age!=null">
                <![CDATA[ `age`, ]]>
            </if>
            <if test="salary!=null">
                <![CDATA[ `salary`, ]]>
            </if>
        </trim>
        <![CDATA[ VALUES ]]>
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="id!=null">
                <![CDATA[ #{id}, ]]>
            </if>
            <if test="name!=null">
                <![CDATA[ #{name}, ]]>
            </if>
            <if test="age!=null">
                <![CDATA[ #{age}, ]]>
            </if>
            <if test="salary!=null">
                <![CDATA[ #{salary}, ]]>
            </if>
        </trim>
    </insert>

    <!-- 批量插入 -->
    <insert id="insertBatch" parameterType="map">
        <![CDATA[ INSERT INTO `t_user` (`id`, `name`, `age`, `salary`) VALUES ]]>
        <foreach collection="list" separator="," item="item">
            (#{item.id}, #{item.name}, #{item.age}, #{item.salary})
        </foreach>
    </insert>

    <!-- 更新 -->
    <update id="update" parameterType="com.javacode2018.mybatis.chat01.UserModel">
        <![CDATA[ UPDATE `t_user` ]]>
        <set>
            <if test="name!=null">
                <![CDATA[ `name` = #{name}, ]]>
            </if>
            <if test="age!=null">
                <![CDATA[ `age` = #{age}, ]]>
            </if>
            <if test="salary!=null">
                <![CDATA[ `salary` = #{salary}, ]]>
            </if>
        </set>
        <where>
            <if test="id!=null">
                <![CDATA[ AND `id` = #{id} ]]>
            </if>
        </where>
    </update>

    <!-- 更新 -->
    <update id="updateByMap" parameterType="map">
        <![CDATA[ UPDATE `t_user` ]]>
        <set>
            <if test="name!=null">
                <![CDATA[ `name` = #{name}, ]]>
            </if>
            <if test="age!=null">
                <![CDATA[ `age` = #{age}, ]]>
            </if>
            <if test="salary!=null">
                <![CDATA[ `salary` = #{salary}, ]]>
            </if>
        </set>
        <where>
            <if test="id!=null">
                <![CDATA[ AND `id` = #{id} ]]>
            </if>
        </where>
    </update>

    <!-- 刪除 -->
    <delete id="delete" parameterType="map">
        <![CDATA[
            DELETE FROM `t_user`
        ]]>
        <where>
            <if test="id!=null">
                <![CDATA[ AND `id` = #{id} ]]>
            </if>
        </where>
    </delete>

    <!-- 查詢記錄 -->
    <select id="getModelList" parameterType="map" resultType="com.javacode2018.mybatis.chat01.UserModel">
        <![CDATA[
        SELECT
        ]]>
        <choose>
            <when test="tableColumnList!=null and tableColumnList.size() >= 1">
                <foreach collection="tableColumnList" item="item" separator=",">
                    <![CDATA[ ${item} ]]>
                </foreach>
            </when>
            <otherwise>
                <![CDATA[
                `id`,
                `name`,
                `age`,
                `salary`
                ]]>
            </otherwise>
        </choose>
        <![CDATA[
        FROM
        `t_user` a
        ]]>
        <where>
            <if test="id!=null and id.toString()!=''">
                <![CDATA[ AND a.`id` = #{id} ]]>
            </if>
            <if test="idList!=null and idList.size() >= 1">
                <![CDATA[ AND a.`id` IN ]]>
                <foreach collection="idList" item="item" open="(" separator="," close=")">
                    <![CDATA[ #{item} ]]>
                </foreach>
            </if>
            <if test="name!=null and name.toString()!=''">
                <![CDATA[ AND a.`name` = #{name} ]]>
            </if>
            <if test="age!=null and age.toString()!=''">
                <![CDATA[ AND a.`age` = #{age} ]]>
            </if>
            <if test="salary!=null and salary.toString()!=''">
                <![CDATA[ AND a.`salary` = #{salary} ]]>
            </if>
            <if test="nameLike!=null and nameLike.toString()!=''">
                <![CDATA[ AND a.`name` like '%${nameLike}%' ]]>
            </if>
            <if test="salaryGte!=null and salaryGte.toString()!=''">
                <![CDATA[ AND a.`salary` >= #{salaryGte} ]]>
            </if>
        </where>
        <if test="sort!=null and sort.toString()!=''">
            <![CDATA[ order by ${sort} ]]>
        </if>
        <if test="skip!=null and pageSize!=null">
            <![CDATA[ LIMIT #{skip},#{pageSize} ]]>
        </if>
    </select>

</mapper>

mybatis-config.xml

chat01/src/main/resources目錄中新建mybatis-config.xml,內(nèi)容如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <properties>
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/javacode2018?characterEncoding=UTF-8"/>
        <property name="username" value="root"/>
        <property name="password" value="root123"/>
    </properties>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/user.xml"/>
    </mappers>
</configuration>

UserMapper接口

package com.javacode2018.mybatis.chat01;

import java.util.List;
import java.util.Map;

/**
 * 公眾號:路人甲Java问顷,工作10年的前阿里P7分享Java昂秃、算法、數(shù)據(jù)庫方面的技術(shù)干貨择诈!堅(jiān)信用技術(shù)改變命運(yùn)械蹋,讓家人過上更體面的生活!
 */
public interface UserMapper {

    /**
     * 插入用戶信息
     *
     * @param userModel
     * @return
     */
    void insert(UserModel userModel);

    /**
     * 批量插入用戶信息
     *
     * @param userModelList
     */
    void insertBatch(List<UserModel> userModelList);

    /**
     * 更新用戶信息
     *
     * @param userModel
     * @return
     */
    int update(UserModel userModel);

    /**
     * 通過map來更新用戶記錄
     *
     * @param map
     * @return
     */
    int updateByMap(Map<String, Object> map);

    /**
     * 通過map來刪除用戶記錄
     *
     * @param map
     * @return
     */
    int delete(Map<String, Object> map);

    /**
     * 查詢用戶列表
     *
     * @param map
     * @return
     */
    List<UserModel> getModelList(Map<String, Object> map);

}

UserModel類

package com.javacode2018.mybatis.chat01;

import lombok.*;

/**
 * 公眾號:路人甲Java,工作10年的前阿里P7分享Java羞芍、算法哗戈、數(shù)據(jù)庫方面的技術(shù)干貨!堅(jiān)信用技術(shù)改變命運(yùn)荷科,讓家人過上更體面的生活!
 */
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ToString
public class UserModel {
    private Long id;
    private String name;
    private Integer age;
    private Double salary;
}

這個(gè)類上面的注解都是都是lombok中的唯咬,通過這些注解,lombok可以幫助我們自動(dòng)生成上面4個(gè)字段的get方法畏浆、set方法胆胰、無參構(gòu)造方法、有參有參構(gòu)造方法刻获、builder模式構(gòu)建對象的代碼蜀涨、重寫toString方法,這些都在代碼編譯為字節(jié)碼之前會(huì)寫進(jìn)去蝎毡,通過lombok代碼是不是精簡了很多厚柳,最后生成的代碼大家可以反編譯一下UserModel.class去看一下,感受一下沐兵,此處我們就不貼出來了别垮。

UserUtil類

package com.javacode2018.mybatis.chat01;

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;

/**
 * 公眾號:路人甲Java,工作10年的前阿里P7分享Java扎谎、算法碳想、數(shù)據(jù)庫方面的技術(shù)干貨烧董!堅(jiān)信用技術(shù)改變命運(yùn),讓家人過上更體面的生活!
 */
@Slf4j
public class UserUtil {
    private static SqlSessionFactory sqlSessionFactory = build();

    public static SqlSessionFactory build() {
        try {
            return new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
        } catch (IOException e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

    @FunctionalInterface
    public interface SessionCall<O> {
        O call(SqlSession session) throws Exception;
    }

    @FunctionalInterface
    public interface MapperCall<T, O> {
        O call(T mapper) throws Exception;
    }

    public static <T, O> O callMapper(Class<T> tClass, MapperCall<T, O> mapper) throws Exception {
        return call(session -> mapper.call(session.getMapper(tClass)));
    }

    public static <O> O call(SessionCall<O> sessionCall) throws Exception {
        try (SqlSession session = sqlSessionFactory.openSession(true);) {
            return sessionCall.call(session);
        }
    }
}

創(chuàng)建單元測試類UserMapperTest

chat01\src\test\java\com\javacode2018\mybatis\chat01中創(chuàng)建UserMapperTest胧奔,代碼如下:

package com.javacode2018.mybatis.chat01;

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 公眾號:路人甲Java逊移,工作10年的前阿里P7分享Java、算法龙填、數(shù)據(jù)庫方面的技術(shù)干貨螟左!堅(jiān)信用技術(shù)改變命運(yùn),讓家人過上更體面的生活!
 */
@Slf4j
public class UserMapperTest {

    //動(dòng)態(tài)插入
    @Test
    public void insert() throws Exception {
        UserModel userModel1 = UserModel.builder().name("路人甲Java").build();
        UserUtil.callMapper(UserMapper.class, mapper -> {
            mapper.insert(userModel1);
            return null;
        });
        log.info("插入結(jié)果:{}", this.getModelById(userModel1.getId()));
        log.info("---------------------");
        UserModel userModel2 = UserModel.builder().name("路人").age(30).salary(50000.00).build();
        UserUtil.callMapper(UserMapper.class, mapper -> {
            mapper.insert(userModel2);
            return null;
        });
        log.info("插入結(jié)果:{}", this.getModelById(userModel2.getId()));
    }

    //批量插入
    @Test
    public void insertBatch() throws Exception {
        List<UserModel> userModelList = new ArrayList<>();
        for (int i = 1; i <= 5; i++) {
            userModelList.add(UserModel.builder().name("路人甲Java-" + i).age(30 + i).salary(10000.00 * i).build());
            userModelList.add(UserModel.builder().name("javacode2018-" + i).age(30 + i).salary(10000.00 * i).build());
        }
        UserUtil.callMapper(UserMapper.class, mapper -> {
            mapper.insertBatch(userModelList);
            return null;
        });

        List<UserModel> userModelList1 = UserUtil.callMapper(UserMapper.class, mapper -> mapper.getModelList(null));
        log.info("結(jié)果:{}", userModelList1);
    }

    //根據(jù)用戶id刪除數(shù)據(jù)
    @Test
    public void delete() throws Exception {
        Map<String, Object> map = new HashMap<>();
        //需要?jiǎng)h除的用戶id
        map.put("id", 1);
        Integer count = UserUtil.callMapper(UserMapper.class, mapper -> mapper.delete(map));
        log.info("刪除行數(shù):{}", count);
    }

    //動(dòng)態(tài)更新
    @Test
    public void update() throws Exception {
        //將userId=2的name修改為:路人
        Long userId1 = 2L;
        Integer count = UserUtil.callMapper(UserMapper.class, mapper -> mapper.update(UserModel.builder().id(userId1).name("ready").build()));
        log.info("更新行數(shù):{}", count);

        log.info("---------------------");
        //將userId=3的name修改為:路人,薪水為:1000.88
        Long userId2 = 3L;
        count = UserUtil.callMapper(UserMapper.class, mapper -> mapper.update(UserModel.builder().id(userId2).name("ready").salary(1000.88D).build()));
        log.info("更新行數(shù):{}", count);
    }

    //按用戶id查詢
    public UserModel getModelById(Long userId) throws Exception {
        //查詢指定id的數(shù)據(jù)
        Map<String, Object> map = new HashMap<>();
        map.put("id", userId);
        return UserUtil.callMapper(UserMapper.class, mapper -> {
            List<UserModel> userModelList = mapper.getModelList(map);
            if (userModelList.size() == 1) {
                return userModelList.get(0);
            }
            return null;
        });
    }

    //查詢所有數(shù)據(jù)
    @Test
    public void getModelList1() throws Exception {
        List<UserModel> userModelList = UserUtil.callMapper(UserMapper.class, mapper -> mapper.getModelList(null));
        log.info("結(jié)果:{}", userModelList);
    }

    //查詢多個(gè)用戶id對應(yīng)的數(shù)據(jù)
    @Test
    public void getModelListByIds() throws Exception {
        List<Integer> idList = Arrays.asList(2, 3, 4).stream().collect(Collectors.toList());
        Map<String, Object> map = new HashMap<>();
        map.put("idList", idList);

        List<UserModel> userModelList = UserUtil.callMapper(UserMapper.class, mapper -> mapper.getModelList(map));
        log.info("結(jié)果:{}", userModelList);
    }

    //多條件 & 指定返回的列
    @Test
    public void getModelList2() throws Exception {
        //查詢姓名中包含路人甲java以及薪資大于3萬的用戶id觅够、姓名
        Map<String, Object> map = new HashMap<>();
        map.put("nameLike", "路人甲java");
        map.put("salaryGte", 30000.00D);
        //需要返回的列
        List<String> tableColumnList = new ArrayList<>();
        tableColumnList.add("id");
        tableColumnList.add("name");
        map.put("tableColumnList", tableColumnList);

        List<UserModel> userModelList = UserUtil.callMapper(UserMapper.class, mapper -> mapper.getModelList(map));
        log.info("結(jié)果:{}", userModelList);
    }

    //條件過濾 & 排序 & 分頁查詢數(shù)據(jù) & 只返回用戶id胶背、salary
    @Test
    public void getPage() throws Exception {
        //查詢姓名中包含路人甲java以及薪資大于3萬的用戶id,按照薪資倒敘喘先,每頁5條取第1頁
        Map<String, Object> map = new HashMap<>();
        map.put("nameLike", "路人甲java");
        map.put("salaryGte", 30000.00D);

        //加入排序參數(shù)
        map.put("sort", "salary desc");

        //加入分頁參數(shù)
        int page = 1;
        int pageSize = 5;
        map.put("skip", (page - 1) * pageSize);
        map.put("pageSize", pageSize);

        //加入需要返回的列
        List<String> tableColumnList = new ArrayList<>();
        tableColumnList.add("id");
        tableColumnList.add("salary");
        map.put("tableColumnList", tableColumnList);

        List<UserModel> userModelList = UserUtil.callMapper(UserMapper.class, mapper -> mapper.getModelList(map));
        log.info("結(jié)果:{}", userModelList);
    }
}

項(xiàng)目最終結(jié)構(gòu)如下

用例:動(dòng)態(tài)插入

運(yùn)行UserMapperTest#insert钳吟,輸出如下:

37:58.556 [main] DEBUG c.j.mybatis.chat01.UserMapper.insert - ==>  Preparing: INSERT INTO `t_user` ( `name` ) VALUES ( ? ) 
37:58.605 [main] DEBUG c.j.mybatis.chat01.UserMapper.insert - ==> Parameters: 路人甲Java(String)
37:58.613 [main] DEBUG c.j.mybatis.chat01.UserMapper.insert - <==    Updates: 1
37:58.641 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==>  Preparing: SELECT `id`, `name`, `age`, `salary` FROM `t_user` a WHERE a.`id` = ? 
37:58.641 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==> Parameters: 1(Long)
37:58.663 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - <==      Total: 1
37:58.664 [main] INFO  c.j.mybatis.chat01.UserMapperTest - 插入結(jié)果:UserModel(id=1, name=路人甲Java, age=1, salary=0.0)
37:58.667 [main] INFO  c.j.mybatis.chat01.UserMapperTest - ---------------------
37:58.668 [main] DEBUG c.j.mybatis.chat01.UserMapper.insert - ==>  Preparing: INSERT INTO `t_user` ( `name`, `age`, `salary` ) VALUES ( ?, ?, ? ) 
37:58.675 [main] DEBUG c.j.mybatis.chat01.UserMapper.insert - ==> Parameters: 路人(String), 30(Integer), 50000.0(Double)
37:58.679 [main] DEBUG c.j.mybatis.chat01.UserMapper.insert - <==    Updates: 1
37:58.681 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==>  Preparing: SELECT `id`, `name`, `age`, `salary` FROM `t_user` a WHERE a.`id` = ? 
37:58.681 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==> Parameters: 2(Long)
37:58.683 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - <==      Total: 1
37:58.683 [main] INFO  c.j.mybatis.chat01.UserMapperTest - 插入結(jié)果:UserModel(id=2, name=路人, age=30, salary=50000.0)

UserMapperTest#insert這個(gè)方法主要有4步操作:

步驟1:插入一條用戶記錄,用戶記錄只有name字段有值

步驟2:去db中查詢步驟1中插入的記錄

步驟3:插入一條用戶記錄窘拯,這次插入的記錄所有字段都指定了值

步驟4:去db中查詢步驟3中插入的記錄

重點(diǎn)來了:大家認(rèn)真看一下UserMapperTest#insert方法的代碼红且,兩個(gè)插入調(diào)用都是mapper.insert方法,傳入的都是UserModel對象涤姊,唯一不同的是這個(gè)對象構(gòu)建的時(shí)候字段的值不一樣暇番,最后再認(rèn)真看一下上面輸出的sql,產(chǎn)生的2個(gè)insert也是不一樣的思喊,這個(gè)mapper.insert方法可以根據(jù)UserModel對象字段是否有值來組裝我們需要的sql壁酬,是不是很牛逼,這就是動(dòng)態(tài)插入恨课。

用例:批量插入

運(yùn)行UserMapperTest#insertBatch舆乔,輸出如下:

38:12.425 [main] DEBUG c.j.m.chat01.UserMapper.insertBatch - ==>  Preparing: INSERT INTO `t_user` (`id`, `name`, `age`, `salary`) VALUES (?, ?, ?, ?) , (?, ?, ?, ?) , (?, ?, ?, ?) , (?, ?, ?, ?) , (?, ?, ?, ?) , (?, ?, ?, ?) , (?, ?, ?, ?) , (?, ?, ?, ?) , (?, ?, ?, ?) , (?, ?, ?, ?) 
38:12.476 [main] DEBUG c.j.m.chat01.UserMapper.insertBatch - ==> Parameters: null, 路人甲Java-1(String), 31(Integer), 10000.0(Double), null, javacode2018-1(String), 31(Integer), 10000.0(Double), null, 路人甲Java-2(String), 32(Integer), 20000.0(Double), null, javacode2018-2(String), 32(Integer), 20000.0(Double), null, 路人甲Java-3(String), 33(Integer), 30000.0(Double), null, javacode2018-3(String), 33(Integer), 30000.0(Double), null, 路人甲Java-4(String), 34(Integer), 40000.0(Double), null, javacode2018-4(String), 34(Integer), 40000.0(Double), null, 路人甲Java-5(String), 35(Integer), 50000.0(Double), null, javacode2018-5(String), 35(Integer), 50000.0(Double)
38:12.484 [main] DEBUG c.j.m.chat01.UserMapper.insertBatch - <==    Updates: 10
38:12.502 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==>  Preparing: SELECT `id`, `name`, `age`, `salary` FROM `t_user` a 
38:12.502 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==> Parameters: 
38:12.521 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - <==      Total: 12
38:12.521 [main] INFO  c.j.mybatis.chat01.UserMapperTest - 結(jié)果:[UserModel(id=1, name=路人甲Java, age=1, salary=0.0), UserModel(id=2, name=路人, age=30, salary=50000.0), UserModel(id=3, name=路人甲Java-1, age=31, salary=10000.0), UserModel(id=4, name=javacode2018-1, age=31, salary=10000.0), UserModel(id=5, name=路人甲Java-2, age=32, salary=20000.0), UserModel(id=6, name=javacode2018-2, age=32, salary=20000.0), UserModel(id=7, name=路人甲Java-3, age=33, salary=30000.0), UserModel(id=8, name=javacode2018-3, age=33, salary=30000.0), UserModel(id=9, name=路人甲Java-4, age=34, salary=40000.0), UserModel(id=10, name=javacode2018-4, age=34, salary=40000.0), UserModel(id=11, name=路人甲Java-5, age=35, salary=50000.0), UserModel(id=12, name=javacode2018-5, age=35, salary=50000.0)]

這次批量插入了10條用戶記錄,可以看到有這樣的輸出:

40:40.727 [main] DEBUG c.j.m.chat01.UserMapper.insertBatch - <==    Updates: 10

上面這個(gè)表示插入影響的行數(shù)剂公,10表示插入了10行希俩。

批量插入之后,又執(zhí)行了全表查詢纲辽,這次插入了10條颜武,加上前面的2個(gè)單條插入,表中總計(jì)12條記錄拖吼。

用例:根據(jù)用戶id刪除數(shù)據(jù)

運(yùn)行UserMapperTest#delete鳞上,輸出如下:

38:36.498 [main] DEBUG c.j.mybatis.chat01.UserMapper.delete - ==>  Preparing: DELETE FROM `t_user` WHERE `id` = ? 
38:36.551 [main] DEBUG c.j.mybatis.chat01.UserMapper.delete - ==> Parameters: 1(Integer)
38:36.560 [main] DEBUG c.j.mybatis.chat01.UserMapper.delete - <==    Updates: 1
38:36.561 [main] INFO  c.j.mybatis.chat01.UserMapperTest - 刪除行數(shù):1

用例:動(dòng)態(tài)更新

運(yùn)行UserMapperTest#update,輸出如下:

38:51.289 [main] DEBUG c.j.mybatis.chat01.UserMapper.update - ==>  Preparing: UPDATE `t_user` SET `name` = ? WHERE `id` = ? 
38:51.347 [main] DEBUG c.j.mybatis.chat01.UserMapper.update - ==> Parameters: ready(String), 2(Long)
38:51.355 [main] DEBUG c.j.mybatis.chat01.UserMapper.update - <==    Updates: 1
38:51.356 [main] INFO  c.j.mybatis.chat01.UserMapperTest - 更新行數(shù):1
38:51.358 [main] INFO  c.j.mybatis.chat01.UserMapperTest - ---------------------
38:51.359 [main] DEBUG c.j.mybatis.chat01.UserMapper.update - ==>  Preparing: UPDATE `t_user` SET `name` = ?, `salary` = ? WHERE `id` = ? 
38:51.360 [main] DEBUG c.j.mybatis.chat01.UserMapper.update - ==> Parameters: ready(String), 1000.88(Double), 3(Long)
38:51.363 [main] DEBUG c.j.mybatis.chat01.UserMapper.update - <==    Updates: 1
38:51.364 [main] INFO  c.j.mybatis.chat01.UserMapperTest - 更新行數(shù):1

UserMapperTest#update方法绿贞,大家也認(rèn)真看一下因块,2個(gè)更新橘原,調(diào)用都是mapper.update方法籍铁,傳入的都是UserModel類型的參數(shù)涡上,只是2個(gè)UserModel對象的字段值不一樣,最后產(chǎn)生的2個(gè)update語句也是不一樣的拒名,這個(gè)update語句是mybatis動(dòng)態(tài)組裝的吩愧,mybatis可以根據(jù)UserModel中字段是否為NULL,來拼裝sql增显,這個(gè)更新是不是很強(qiáng)大雁佳。

用例:動(dòng)態(tài)查詢

查詢所有數(shù)據(jù)

運(yùn)行UserMapperTest#getModelList1,輸出如下:

39:10.552 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==>  Preparing: SELECT `id`, `name`, `age`, `salary` FROM `t_user` a 
39:10.611 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==> Parameters: 
39:10.639 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - <==      Total: 11
39:10.639 [main] INFO  c.j.mybatis.chat01.UserMapperTest - 結(jié)果:[UserModel(id=2, name=ready, age=30, salary=50000.0), UserModel(id=3, name=ready, age=31, salary=1000.88), UserModel(id=4, name=javacode2018-1, age=31, salary=10000.0), UserModel(id=5, name=路人甲Java-2, age=32, salary=20000.0), UserModel(id=6, name=javacode2018-2, age=32, salary=20000.0), UserModel(id=7, name=路人甲Java-3, age=33, salary=30000.0), UserModel(id=8, name=javacode2018-3, age=33, salary=30000.0), UserModel(id=9, name=路人甲Java-4, age=34, salary=40000.0), UserModel(id=10, name=javacode2018-4, age=34, salary=40000.0), UserModel(id=11, name=路人甲Java-5, age=35, salary=50000.0), UserModel(id=12, name=javacode2018-5, age=35, salary=50000.0)]

可以看到sql是沒有查詢條件的同云。

查詢多個(gè)用戶id對應(yīng)的數(shù)據(jù)

運(yùn)行UserMapperTest#getModelListByIds糖权,輸出如下:

39:38.000 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==>  Preparing: SELECT `id`, `name`, `age`, `salary` FROM `t_user` a WHERE a.`id` IN ( ? , ? , ? ) 
39:38.064 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==> Parameters: 2(Integer), 3(Integer), 4(Integer)
39:38.096 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - <==      Total: 3
39:38.097 [main] INFO  c.j.mybatis.chat01.UserMapperTest - 結(jié)果:[UserModel(id=2, name=ready, age=30, salary=50000.0), UserModel(id=3, name=ready, age=31, salary=1000.88), UserModel(id=4, name=javacode2018-1, age=31, salary=10000.0)]

上面這個(gè)按照id列表查詢也是比較常用的,比如我們在電商中查詢訂單列表炸站,還需要查詢每個(gè)訂單對應(yīng)的商品星澳,此時(shí)可以先查詢訂單列表,然后在通過訂單列表拿到所有的商品id集合旱易,然后通過商品id集合去通過上面的方式檢索商品信息禁偎,只需要2次查詢就可以查詢出訂單及商品的信息了。

多條件 & 指定返回的列

運(yùn)行UserMapperTest#getModelList2阀坏,查詢姓名中包含路人甲java以及薪資大于3萬的用戶id如暖、姓名,輸出如下:

41:12.185 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==>  Preparing: SELECT id , name FROM `t_user` a WHERE a.`name` like '%路人甲java%' AND a.`salary` >= ? 
41:12.275 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==> Parameters: 30000.0(Double)
41:12.311 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - <==      Total: 3
41:12.312 [main] INFO  c.j.mybatis.chat01.UserMapperTest - 結(jié)果:[UserModel(id=7, name=路人甲Java-3, age=null, salary=null), UserModel(id=9, name=路人甲Java-4, age=null, salary=null), UserModel(id=11, name=路人甲Java-5, age=null, salary=null)]

看一下上面select語句忌堂,select后面只有id,name2個(gè)字段盒至,where后面有多個(gè)條件,這種查詢也是比較常用的士修,有些表可能有幾十個(gè)字段妄迁,可能我們只需要幾個(gè)字段,就可以使用上面這種查詢李命。

條件過濾 & 排序 & 分頁查詢數(shù)據(jù) & 只返回用戶id登淘、salary

運(yùn)行UserMapperTest#getModelList3,查詢姓名中包含路人甲java以及薪資大于3萬的用戶id封字,按照薪資倒敘黔州,每頁5條取第1頁,輸出如下:

44:00.719 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==>  Preparing: SELECT id , salary FROM `t_user` a WHERE a.`name` like '%路人甲java%' AND a.`salary` >= ? order by salary desc LIMIT ?,? 
44:00.775 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==> Parameters: 30000.0(Double), 0(Integer), 5(Integer)
44:00.805 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - <==      Total: 3
44:00.806 [main] INFO  c.j.mybatis.chat01.UserMapperTest - 結(jié)果:[UserModel(id=11, name=null, age=null, salary=50000.0), UserModel(id=9, name=null, age=null, salary=40000.0), UserModel(id=7, name=null, age=null, salary=30000.0)]

大家主要看一下輸出的sql阔籽,如下:

SELECT id , salary FROM `t_user` a WHERE a.`name` like '%路人甲java%' AND a.`salary` >= ? order by salary desc LIMIT ?,?

這個(gè)sql會(huì)根據(jù)查詢條件流妻,自動(dòng)構(gòu)建出我們需要的sql,這點(diǎn)上面是最厲害的笆制。

案例總結(jié)

上面列舉的一些用例基本上包含了我們對db所需的大部分操作绅这,動(dòng)態(tài)sql處理方面體現(xiàn)的最為強(qiáng)勁,如果讓我們自己寫在辆,我們需要寫很多判斷证薇,而用mybatis這么簡單就實(shí)現(xiàn)了度苔,我們在java代碼中沒有看到一個(gè)判斷拼接語句,而這些sql的判斷拼接都在一個(gè)文件中:user.xml中浑度,這個(gè)就是mybatis中核心的文件寇窑,我們需要寫的sql及判斷邏輯基本上都在這個(gè)xml中,大家可以認(rèn)真去看一下這個(gè)xml文件箩张。

mybatis開發(fā)項(xiàng)目的具體步驟

項(xiàng)目中引入mybatis maven配置

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>${mybatis.version}</version>
</dependency>

上面的mybatis.version版本甩骏,大家可以在maven社區(qū)中央倉庫中去查找最新的,目前最新的是3.5.3

創(chuàng)建mybatis配置文件

mybatis配置文件為xml格式先慷,可以放在resource目錄下面饮笛,如上面案例中的mybatis-config.xml,內(nèi)容如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <properties>
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/javacode2018?characterEncoding=UTF-8"/>
        <property name="username" value="root"/>
        <property name="password" value="root123"/>
    </properties>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/user.xml"/>
    </mappers>
</configuration>

這個(gè)文件主要是對mybatis進(jìn)行全局配置论熙,比如數(shù)據(jù)源缎浇、事務(wù)的配置,如上面的datasource元素用來配置數(shù)據(jù)源赴肚,數(shù)據(jù)源中就需要指定數(shù)據(jù)庫的一些配置信息素跺;還有其他更多的配置,此處先不做具體說明誉券,后面我們慢慢來指厌,整個(gè)系列完成之后,這些配置大家都會(huì)懂的踊跟。

創(chuàng)建mapper xml文件

如上面案例中的user.xml踩验,大家在打開看看,我們需要對t_user表所有操作sql就寫在這個(gè)文件中商玫,下一篇文章我們會(huì)詳細(xì)介紹mapper xml文件的各種寫法箕憾,user.xml文件是對t_user表的所有操作一般都會(huì)放在這個(gè)里面,mybatis如何使用到這個(gè)文件呢拳昌,我們需要在上面的mybatis配置文件中引入這個(gè)mapper文件袭异,如案例中在mybatis-config.xml有下面這樣的內(nèi)容:

<mappers>
    <mapper resource="mapper/user.xml"/>
</mappers>

mappers元素中可以有多個(gè)mapper文件,我們開發(fā)的項(xiàng)目中可能有很多表需要操作炬藤,那么對應(yīng)會(huì)有很多mapper xml文件御铃,我們都需要在mappers元素中進(jìn)行引入,然后mybatis才會(huì)使用到沈矿。

創(chuàng)建Mapper接口

開發(fā)者如何去調(diào)用user.xml中的各種操作去執(zhí)行sql呢上真,這時(shí)我們就需要一個(gè)Mapper接口了Mapper接口會(huì)和mapper xml建立映射關(guān)系羹膳,當(dāng)我們調(diào)用Mapper接口中的方法的時(shí)候睡互,會(huì)間接的調(diào)用到mapper xml中的各種數(shù)據(jù)的sql操作,Mapper接口如何和Mapper xml文件關(guān)聯(lián)的呢?

大家去看一下user.xml文件中有個(gè)這樣的一個(gè)配置:

<mapper namespace="com.javacode2018.mybatis.chat01.UserMapper">

注意上面的namespace的值就珠,對應(yīng)的是UserMapper這個(gè)接口完整的引用寇壳,通過這個(gè)namespace,UserMapper接口就可以user.xml建立了映射關(guān)系嗓违。

user.xml中又有很多db操作,這些操作會(huì)和UserMapper接口中的方法建立映射關(guān)系图贸,當(dāng)調(diào)用UserMapper中的方法的時(shí)候蹂季,間接的會(huì)調(diào)用到user.xml中對應(yīng)的操作。

user.xml中有下面一段配置:

<!-- 批量插入 -->
<insert id="insertBatch" parameterType="map">
    <![CDATA[ INSERT INTO `t_user` (`id`, `name`, `age`, `salary`) VALUES ]]>
    <foreach collection="list" separator="," item="item">
        (#{item.id}, #{item.name}, #{item.age}, #{item.salary})
    </foreach>
</insert>

UserMapper中有個(gè)insertBatch方法和上面這個(gè)insert批量插入對應(yīng)疏日,如下:

/**
 * 批量插入用戶信息
 *
 * @param userModelList
 */
void insertBatch(List<UserModel> userModelList);

所以當(dāng)我們調(diào)用UserMapper中的insertBatch方法的時(shí)候偿洁,會(huì)間接調(diào)用到user.xml中的 id="insertBatch"這個(gè)操作。

提示一下:接口和mapper xml映射起來間接調(diào)用沟优,是通過java動(dòng)態(tài)代理實(shí)現(xiàn)的涕滋,后面我們會(huì)詳解如何實(shí)現(xiàn)的。

下面我們就可以使用mybatis來操作db了挠阁。

通過mybatis獲取Mapper接口執(zhí)行對db的操作

上面我們說了宾肺,我們可以通過mapper接口來執(zhí)行對db的操作,獲取Mapper的主要代碼如下:

SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession sqlSession = sqlSessionFactory.openSession(true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);

上面代碼中使用到了mybatis中的核心組件侵俗,我們具體來看一下锨用。

Mybatis核心對象介紹

SqlSessionFactoryBuilder

這個(gè)是一個(gè)構(gòu)建器,通過名字大家也可以感覺到SqlSessionFactoryBuilder構(gòu)建器隘谣,是用來構(gòu)建SqlSessionFactory對象的增拥,SqlSessionFactoryBuilder可以通過讀取mybatis的配置文件,然后構(gòu)建一個(gè)SqlSessionFactory對象寻歧,一個(gè)項(xiàng)目中有很多mapper xml文件掌栅,如果每次操作都去重新解析是非常慢的,那么怎么辦码泛?

能不能第一次解析好然后放在內(nèi)存中猾封,以后直接使用,SqlSessionFactoryBuilder就是搞這個(gè)事情的噪珊,將mybatis配置文件忘衍、mapper xml文件、mapper xml文件和Mapper 接口的映射關(guān)系卿城,這些都先給解析好枚钓,然后放在java對象中,java對象存在于內(nèi)存中瑟押,內(nèi)存中訪問會(huì)非巢蠼荩快的,那么我們每次去用的時(shí)候就不需要重新去解析xml了,SqlSessionFactoryBuilder解析配置之后嫩舟,生成的對象就是SqlSessionFactory氢烘,這個(gè)是一個(gè)重量級的對象,創(chuàng)建他是比較耗時(shí)的家厌,所以一般一個(gè)db我們會(huì)創(chuàng)建一個(gè)SqlSessionFactory對象播玖,然后在系統(tǒng)運(yùn)行過程中會(huì)一直存在,而SqlSessionFactoryBuilder用完了就可以釋放了饭于。

SqlSessionFactory

通過名字可以知道蜀踏,這個(gè)是一個(gè)工廠,是用來創(chuàng)建SqlSession的工廠掰吕,SqlSessionFactory是一個(gè)重量級的對象果覆,一般一個(gè)db對應(yīng)一個(gè)SqlSessionFactory對象,系統(tǒng)運(yùn)行過程中會(huì)一直存在殖熟。

SqlSessionFactory是一個(gè)接口局待,這個(gè)接口有2個(gè)實(shí)現(xiàn)DefaultSqlSessionFactorySqlSessionManager,一般都是通過SqlSessionFactoryBuilder來創(chuàng)建SqlSessionFactory對象菱属。

通過SqlSessionFactoryBuilder來創(chuàng)建SqlSessionFactory對象主要有2種方式钳榨,一種通過讀取mybatis配置文件的方式,另外一種是硬編碼的方式纽门,這個(gè)后面會(huì)專門抽一篇文件介紹這塊重绷,springboot中會(huì)使用到硬編碼的方式,所以這塊會(huì)詳細(xì)介紹膜毁。

SqlSession

我們通過jdbc操作數(shù)據(jù)庫需要先獲取一個(gè)Connection連接昭卓,然后拿著這個(gè)連接去對db進(jìn)行操作,在mybatis中SqlSession就類似于jdbc中Connection連接對象瘟滨,在mybatis中叫做Sql會(huì)話對象候醒,一般我們一個(gè)db操作使用一個(gè)SqlSession對象,所以這個(gè)對象一般是方法級別的杂瘸,方法結(jié)束之后倒淫,這個(gè)對象就銷毀了,這個(gè)對象可以調(diào)用sqlSessionFactory.openSession的方法來進(jìn)行獲取败玉。

我們可以直接通過SqlSession對象來調(diào)用mapper xml中各種db操作敌土,需要指定具體的操作的id,id的格式為namespace.操作的id运翼。

Mapper接口

我們可以通過SqlSession直接調(diào)用mapper xml中的db操作返干,不過更簡單的以及推薦的方式是使用Mapper接口,Mapper接口中的方法和mapper xml文件中的各種db操作建立了映射關(guān)系血淌,是通過Mapper接口完整名稱+方法名稱mapper xml中的namespace+具體操作的id來進(jìn)行關(guān)聯(lián)的矩欠,然后我們直接調(diào)用Mapper接口中的方法就可以間接的操作db了财剖,使用相當(dāng)方便,Mapper接口需要通過SqlSession獲取癌淮,傳入Mapper接口對應(yīng)的Class對象躺坟,然后會(huì)返回這個(gè)接口的實(shí)例,如:

UserMapper mapper = sqlSession.getMapper(UserMapper.class);

總結(jié)

本篇文章主要通過一個(gè)案例來感受一下mybatis可以干什么乳蓄,以及他的強(qiáng)大之處咪橙,還需要大家掌握mybatis開發(fā)項(xiàng)目的具體步驟,后面的文章將對mybatis中具體的知識點(diǎn)做詳細(xì)介紹虚倒,讓大家成為mybatis高手美侦。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市裹刮,隨后出現(xiàn)的幾起案子音榜,更是在濱河造成了極大的恐慌庞瘸,老刑警劉巖捧弃,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異擦囊,居然都是意外死亡违霞,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進(jìn)店門瞬场,熙熙樓的掌柜王于貴愁眉苦臉地迎上來买鸽,“玉大人,你說我怎么就攤上這事贯被⊙畚澹” “怎么了?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵彤灶,是天一觀的道長看幼。 經(jīng)常有香客問我,道長幌陕,這世上最難降的妖魔是什么诵姜? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮搏熄,結(jié)果婚禮上棚唆,老公的妹妹穿的比我還像新娘。我一直安慰自己心例,他們只是感情好宵凌,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著止后,像睡著了一般摆寄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天微饥,我揣著相機(jī)與錄音逗扒,去河邊找鬼。 笑死欠橘,一個(gè)胖子當(dāng)著我的面吹牛矩肩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播肃续,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼黍檩,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了始锚?” 一聲冷哼從身側(cè)響起刽酱,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瞧捌,沒想到半個(gè)月后棵里,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡姐呐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年殿怜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片曙砂。...
    茶點(diǎn)故事閱讀 40,852評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡头谜,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鸠澈,到底是詐尸還是另有隱情柱告,我是刑警寧澤,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布笑陈,位于F島的核電站际度,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏新锈。R本人自食惡果不足惜甲脏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望妹笆。 院中可真熱鬧块请,春花似錦、人聲如沸拳缠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽窟坐。三九已至海渊,卻和暖如春绵疲,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背臣疑。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工盔憨, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人讯沈。 一個(gè)月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓郁岩,卻偏偏與公主長得像,于是被迫代替她去往敵國和親缺狠。 傳聞我的和親對象是個(gè)殘疾皇子问慎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評論 2 361