Mybatis最佳教學教程入門筆記

一、Mybatis簡介

1、Mybatis執(zhí)行步驟

  • 讀取配置文件mybatis-config.xml,主要是獲取數(shù)據(jù)庫連接和運行環(huán)境信息
  • 加載映射文件mapper.xml,也就是sql映射文件,需要在mybatis-config.xml中加載才能被執(zhí)行。
  • 創(chuàng)建SqlSessionFactory
  • 根據(jù)SqlSessionFactory創(chuàng)建SqlSession
  • 使用SqlSession對象操作數(shù)據(jù)庫,包括增刪改查和事務(wù)提交
  • 關(guān)閉SqlSession

二、Mybatis與Maven整合

1、Maven 依賴

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.9</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.27</version>
        </dependency>

2、mybatis配置文件

src/man/resources/mybatis-config.xml

<?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>
    <!--數(shù)據(jù)庫環(huán)境-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/淄礦大數(shù)據(jù)平臺?characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!--每一個Mapper都需要在此注冊,一下三種方式都可以-->
    <mappers>
        <mapper resource="Mapper.xml/SjddSjsctzMapper.xml"/>
        <!--一下兩種方式要注意,存xml和存接口的文件夾名字要相同-->
        <mapper class="ore.example.mapper.SjddSjsctzMapper"/>
        <mapper package name="ore.example.mapper"/>
    </mappers>
</configuration>

3、工具類

package org.example.utils;

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;
import java.io.InputStream;

public class MybatisUtils {

    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            // 獲取sqlSessionFactory對象
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 獲取SqlSession實例,SqlSession包含了面向數(shù)據(jù)庫執(zhí)行SQL命令所需的所有方法
    public static SqlSession getSqlSession() {
        return sqlSessionFactory.openSession(true);
    }
}

4、Mapper接口

package org.example.mapper;

import org.apache.ibatis.annotations.Mapper;
import org.example.model.SjddSjsctz;
import java.util.List;

@Mapper
public interface SjddSjsctzMapper {

    List<SjddSjsctz> selectAll();

}

5、Mapper.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" >
    <!--namespace綁定對應(yīng)的Mapper接口-->
    <mapper namespace="org.example.mapper.SjddSjsctzMapper">

    <select id="selectAll" resultType="org.example.model.SjddSjsctz">
        select * from sjdd_sjsctz;
    </select>

</mapper>

6、mapper讀取數(shù)據(jù)

    @Test
    public void testMybatis() {

        // 第一步:獲得SqlSession對象
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        // 第二部:getMapper
        SjddSjsctzMapper sjddSjsctzMapper = sqlSession.getMapper(SjddSjsctzMapper.class);

        for (SjddSjsctz sjddSjsctz : sjddSjsctzMapper.selectAll()) {

            System.out.println(sjddSjsctz);
        }
        
        // 第三步:關(guān)閉SslSession
        sqlSession.close();
    }

三、簡單CURD操作

1、增、刪、改、查 示例


    // 一、查詢:可以傳bean、map、@param修飾的一個或多個參數(shù)、順序傳的單個或多個參數(shù)
    List<SjddSjsctz> selectAll();


    // 二、插入:可以傳bean、map、@param修飾的一個或多個參數(shù)、順序傳的單個或多個參數(shù)
    // id自增,可以手動指定一個id傳進去,也可以不傳
    int insertOne(Map<String,Object> map);

2、模糊查詢

兩種方式

// Java代碼里的模糊查詢參數(shù),傳遞通配符%%
List<User> userList = mapper.getUserLike("%李%");
select * from user where username like '#{username}';


List<User> userList = mapper.getUserLike("李");
select * from user where username like concat('%',#{username},'%');

3、批量插入

    @Test
    public void testInsert() throws Exception {

        SqlSession sqlSession = MybatisUtils.sqlSessionFactory.openSession(ExecutorType.BATCH);
        SjddSjsctzMapper mapper = sqlSession.getMapper(SjddSjsctzMapper.class);

        for (int i = 0; i < 10; i++) {
            User user = new User();
            user.setUsername(UUID.randomUUID().toString());
            user.setPassword(UUID.randomUUID().toString());
            mapper.insertMany(user);

        }

        sqlSession.commit();

    }

4、返回自增主鍵

當使用insert或update語句時,返回語句影響記錄的自增主鍵值。

  • useGenerateKeys="true/false"這回讓MyBatis使用JDBC的getGenerateKeys方法,來取出由數(shù)據(jù)庫內(nèi)部生成的主鍵,默認false。如果設(shè)置為 true,將強制使用自動生成主鍵。
  • keyProperty="id",指定返回自增主鍵的值,將自增主鍵值賦予入?yún)⒅祵嶓w類的id屬性。
        User user = new User();
        user.setUsername("username");
        user.setPassword("password");
        user.setRoles("roles");
        user.setEnable((byte) 1);

        int i = mapper.insertOne(user);

        System.out.println(i);
        System.out.println(user.getId());  // 得到返回的主鍵
    
        int insertOne(User user);

    
    -- 將主鍵返回給傳來的user對象的id屬性
    <insert id="insertOne" parameterType="User" useGeneratedKeys="true" keyProperty="id">
        insert into user(username, password,enable, roles)
        values (#{username}, #{password}, #{enable}, #{roles});
    </insert>

5、SQL執(zhí)行結(jié)束的返回值

  1. insert、delete、update語句:

用int返回類型,返回執(zhí)行的SQL語句影響的記錄條數(shù),若果是0則表示沒有做更改。

  1. select語句的返回值類型如下:

使用查詢語句執(zhí)行后,數(shù)據(jù)庫返回的實際類型。

  • List/map
  • javabean
  • resultMap

6、mapper.xml接收的參數(shù)類型

(1)parameterType

  1. 接收單個參數(shù),參數(shù)類型為基本類型/包裝類型時,mapper.xml里的參數(shù)名可以隨便寫都能取到值:#{xx}
  2. 接收多個參數(shù),參數(shù)類型為基本類型/包裝類型時,寫入對應(yīng)的參數(shù)名;或者按照順序?qū)?{0}...#{n}
  1. 接收map、或?qū)嶓w類,mapper.xml里的參數(shù)名要和map的key或?qū)嶓w類里的屬性名相對應(yīng)。
int addUser(Map<String, Object>);

<insert id="addUser" parameterType="map">
    insert into sjdd_sjsctz (id, name, password) values(#{name},#{password}) ;
</insert>

Map<String, Object> map = new HashMap<String, Object>();
map.put("name", "admin");
map.put("password", "123456");

mapper.addUser(map);

(2)parameterMap

用的比較少

7、mapper.xml返回的參數(shù)類型

這里的返回參數(shù),一般是select語句用到的返回數(shù)據(jù)的參數(shù)類型。

(1)resultType

  1. 返回實體類
  1. 返回map
  1. 單字段返回基礎(chǔ)類型

(2)resultMap

簡單用法是解決表字段與實體類屬性不一致的問題。

  1. 方式一:查詢語句起別名
    <select id="selectAll" resultType="User">
        select id, name, pwd as password from user;
    </select>
  1. 方式二:返回值類型設(shè)置成:resultMap
    <!--只需要將不一致的字段進行對應(yīng),相當于返回了User,但修改了不一致的字段-->
    <resultMap id="resultMap" type="User">
        <result column="password" property="pwd"/>  
    </resultMap>

    <select id="selectAll" resultMap="resultMap">
        select id, name, pwd  from user;
    </select>

四、復(fù)雜查詢

1、動態(tài)SQL

(1)if

<select id="select" resultType="Blog">
  SELECT * FROM BLOG WHERE state = 'ACTIVE'
  <if test="title != null">
    AND title like #{title}
  </if>
  <if test="author != null and author.name != null">
    AND author_name like #{author.name}
  </if>
</select>

(2)foreach

  • 查詢
<select id="selectPostIn" resultType="domain.blog.Post">
  SELECT * FROM POST P WHERE ID in
  <foreach item="item" index="index" collection="list" open="(" separator="," close=")">
        #{item}
  </foreach>
</select>
  • 批量插入
        ArrayList<Object> users = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            User user = new User();
            user.setUsername(UUID.randomUUID().toString());
            user.setPassword(UUID.randomUUID().toString());
            users.add(user);
        }

        int i = mapper.insertMany(users);
        System.out.println(i);
    int insertMany(List list);
    <insert id="insertMany">
        insert into user(username, password) values
        <foreach collection="list" item="item" separator=",">
            (#{item.username}, #{item.password})
        </foreach>
    </insert>

(3)choose、when、otherwise

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null and author.name != null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = 1
    </otherwise>
  </choose>
</select>

(4)set

待補充。。。。

2、多表查詢

多表查詢,xml里返回類型需要用resultMap,自定義返回的字段,對一使用association,對多使用collection。實體類里要加入對一的屬性。

  • 關(guān)聯(lián)-association【對一】
  • 集合-collection 【對多】

javaType 用來指定實體類中屬性的類型
ofType 用來指定映射到List或集合中的pojo類型,泛型中的約束類型

(1)一對一

一對一的,使用resultMap和association。可以對javabean添加屬性也可以

  1. 假設(shè)一個Article對應(yīng)一個Author,Article里存放Author的id。在Article的實體類里,增加Author。
@Data
public class Article {

    private String articleId;
    private String title;
    private Integer authorId;

    // 加入需要關(guān)聯(lián)的實體類
    private Author author;
}
  1. 編寫resultMap
    <resultMap id="resultMap" type="Article">
        <!-- 一下三條不能省略 -->
        <id property="articleId" column="article_id"/>
        <result property="title" column="title"/>
        <result property="authorId" column="author_id"/>
        
        <!-- 關(guān)聯(lián)的實體類屬性 -->
        <association property="author">
            <id property="id" column="id"/>
            <result property="author" column="author"/>
        </association>
    </resultMap>
  1. 編寫查詢語句
    <select id="selectOneToOne" resultMap="resultMap">
        select a.author_id, a.title, a.article_id, b.id, b.author
        from article a, author b where a.author_id = b.id;
    </select>

(2)一對多

  1. 一的實體類
@Data
public class Article {

    private String articleId;
    private String title;
    private Integer authorId;

    // 加入需要關(guān)聯(lián)的實體類
    private Author author;

    // 需要關(guān)聯(lián)的一對多的評論
    private List<Remark> remarks;
}


  1. resultMap
    <resultMap id="resultMap" type="Article">
        <id property="articleId" column="article_id"/>
        <result property="title" column="title"/>
        <result property="authorId" column="author_id"/>

        <association property="author">
            <id property="id" column="id"/>
            <result property="author" column="author"/>
        </association>

        <collection property="remarks" ofType="Remark">
            <id column="id" property="id"/>
            <result property="cont" column="cont"/>
            <result property="articleId" column="article_id"/>
        </collection>
    </resultMap>
  1. SQL語句
    <select id="selectOneToMany" resultMap="resultMap">
        select a.author_id, a.title, a.article_id, b.id, b.author, c.cont
        from article a join author b on a.author_id = b.id join remark c on c.article_id = a.article_id
        where a.article_id = #{id};
    </select>
  1. 查詢結(jié)果

[Article(articleId=1, title=葵花寶典, authorId=1, author=Author(id=1, author=黃藥師), remarks=[Remark(id=1, cont=良心教程, articleId=1)])]

除了使用resultMap + collection外,也可以在程序中進行多次查詢。

(3)多對一

待補充。。。。

五、mybatis-config.xml 配置

1、屬性(properties)

這些屬性可以在外部進行配置,并可以進行動態(tài)替換。既可以在典型的 Java 屬性文件中配置這些屬性,也可以在 properties 元素的子元素中設(shè)置。例如:

mybatis-config.xml

    <!--替換屬性-->
    <properties resource="database.properties"/>

<!--    <properties resource="org/mybatis/example/config.properties">-->
<!--        <property name="username" value="dev_user"/>-->
<!--        <property name="password" value="F2Fa3!33TYyg"/>-->
<!--    </properties>-->


    <!--數(shù)據(jù)庫環(huán)境-->
    <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>

database.properties (注意,數(shù)據(jù)庫名用中文報錯)

driver = "com.mysql.cj.jdbc.Driver"
url = "jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8"
username = "root"
password = "root"

2、類型別名(typeAliases)

類型別名可為 Java 類型設(shè)置一個縮寫名字。 它僅用于 XML 配置,意在降低冗余的全限定類名書寫,例如:

  1. 單個別名分別配置:
<typeAliases>
  <typeAlias alias="Author" type="com.example.Modle.Author"/>
  <typeAlias alias="Blog" type="com.example.Modle.Blog"/>
</typeAliases>
  1. 掃描包整個model包

會使用包內(nèi) Bean 的首字母小寫的非限定類名來作為它的別名,首字母大寫也支持。有注解則優(yōu)先使用注解

    <typeAliases>
        <typeAlias alias="User" type="org.example.model.User"/>
        <package name="org.example.model"/>
    </typeAliases>
  1. 注解:@Alias("xxx")
@Alias("author")
public class Author{
    ...
}

配置完別名之后,才能將resultType="com.example.Modle.Author" 變?yōu)?resultType="Author"

3、設(shè)置(settings)

(1)駝峰命名轉(zhuǎn)換

默認false,不進行轉(zhuǎn)換。開啟后將數(shù)據(jù)庫字段的column_table與實體類的columnTable進行自動對應(yīng),這樣查出來的數(shù)據(jù)才能賦給實體類。

    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

(2)日志打印

  1. STDOUT_LOGGING
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
image.png

image.png
  1. LOG4J

(3)字段為null時處理

默認false,當查詢一條記錄,某個字段為null時,是否調(diào)用映射對象的 setter(map 對象時為 put)方法,默認mybatis不會處理這一字段,也就是不會調(diào)用null賦值給返回的對象。

    <settings>
        <setting name="callSettersOnNulls" value="true"/>
    </settings>

(4)返回null的處理

默認false,當查詢到記錄,但返回行的所有列都是null時,MyBatis默認返回 null對象,而不會創(chuàng)建返回對象,當調(diào)用返回對象的方法時,容易導(dǎo)致空指針錯誤。
當開啟這個設(shè)置時,MyBatis會創(chuàng)建返回對象,但對象是一個null實例,返回的實體類對象的所有屬性都是null。

    <settings>
        <setting name="returnInstanceForEmptyRow" value="true"/>
    </settings>

注意:如果表為空,或者根據(jù)條件查找不到記錄,必定會返回null或空列表[]
上述設(shè)置只適用于,當mybatis查找到了表記錄,但是返回的列全是null的時候。如果返回的列,不是全部為null,則會正常創(chuàng)建返回對象。

六、緩存

1、一級緩存:

默認開啟,存在于SqlSession的生命周期中,什么是SqlSession的生命周期呢,簡單的來說,只有同一個請求才會是同一個SqlSession,那么就是說只有同一個請求我查詢第二次這個緩存才會生效。

2、二級緩存:

也稱為全局緩存,存在于SqlSessionFactory 的生命周期中,可以理解為跨sqlSession;緩存是以namespace為單位的,不同namespace下的操作互不影響,但是在多人開發(fā)的環(huán)境下,我的不同的namespace完全是有可能操作同一張表的,那么會導(dǎo)致一個namespace的數(shù)據(jù)修改了一張表,但是另一個namespace的那張表的數(shù)據(jù)緩存沒被修改,這樣查詢的數(shù)據(jù)就會錯誤。

  • 開啟方式:在Mapper.xml里添加<cache/>即可

七、使用注解開發(fā)

@select("select * frome user")
List<User> getUsers();

@select("select * from user where id = #{id}")
User findById(@Param("id") long id);

@Insert("insert into user(id,name,password) values(#{id},#{name},#{password})")
int addUser(User user);

@Update("update user set name=#{name},password=#{password} where id = #{id}")
int updateUser(User user);

@Delete("delete from user where id = #{id}")
int delete(@Param("uid") int id);

mybatis-config.xml

<!--注解沒有xml文件,所以綁定Mapper接口-->
<mappers>
  <mapper class="org.example.model.UserMapper"/>
</mappers>

八、Mybatis與Spring整合

待補充。。。。

九、Mybatis與SpringBoot整合

待補充。。。。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 1、MyBatis簡介 MyBatis 是一款優(yōu)秀的持久層框架 中文官網(wǎng):https://mybatis.org/...
    CHeng_c0e9閱讀 432評論 0 0
  • 之前學習MyBatis整理了一些筆記,筆記分為四個部分:1.MyBatis應(yīng)用分析與實踐[https://www....
    javacoo閱讀 1,021評論 0 2
  • 小感悟: 自學Java也有一年了,基本上都是學習基礎(chǔ)的教程,Java水很深,前面學習新知識后面忘了老知識,我也不知...
    賣流量的小嗨閱讀 1,039評論 0 1
  • 一、重點知識 git 監(jiān)視的是文件內(nèi)容的修改 $ git checkout -- abc.txt : 其實是用版本...
    一花一世界yu閱讀 900評論 0 2
  • 目錄 1-3.持久層(名詞,概念) 1-4.為啥需要Mybatis? 5、解決屬性名和字段名不一致的問題 10-1...
    Java架構(gòu)師頂頂閱讀 1,350評論 0 0