Mybatis最佳教学教程入门笔记

一、Mybatis简介

1、Mybatis执行步骤

  • 读取配置文件mybatis-config.xml,主要是获取数据库连接和运行环境信息
  • 加载映射文件mapper.xml,也就是sql映射文件,需要在mybatis-config.xml中加载才能被执行。
  • 创建SqlSessionFactory
  • 根据SqlSessionFactory创建SqlSession
  • 使用SqlSession对象操作数据库,包括增删改查和事务提交
  • 关闭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>
    <!--数据库环境-->
    <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/淄矿大数据平台?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包含了面向数据库执行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绑定对应的Mapper接口-->
    <mapper namespace="org.example.mapper.SjddSjsctzMapper">

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

</mapper>

6、mapper读取数据

    @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);
        }
        
        // 第三步:关闭SslSession
        sqlSession.close();
    }

三、简单CURD操作

1、增、删、改、查 示例


    // 一、查询:可以传bean、map、@param修饰的一个或多个参数、顺序传的单个或多个参数
    List<SjddSjsctz> selectAll();


    // 二、插入:可以传bean、map、@param修饰的一个或多个参数、顺序传的单个或多个参数
    // id自增,可以手动指定一个id传进去,也可以不传
    int insertOne(Map<String,Object> map);

2、模糊查询

两种方式

// Java代码里的模糊查询参数,传递通配符%%
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方法,来取出由数据库内部生成的主键,默认false。如果设置为 true,将强制使用自动生成主键。
  • keyProperty="id",指定返回自增主键的值,将自增主键值赋予入参值实体类的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执行结束的返回值

  1. insert、delete、update语句:

用int返回类型,返回执行的SQL语句影响的记录条数,若果是0则表示没有做更改。

  1. select语句的返回值类型如下:

使用查询语句执行后,数据库返回的实际类型。

  • List/map
  • javabean
  • resultMap

6、mapper.xml接收的参数类型

(1)parameterType

  1. 接收单个参数,参数类型为基本类型/包装类型时,mapper.xml里的参数名可以随便写都能取到值:#{xx}
  2. 接收多个参数,参数类型为基本类型/包装类型时,写入对应的参数名;或者按照顺序写#{0}...#{n}
  1. 接收map、或实体类,mapper.xml里的参数名要和map的key或实体类里的属性名相对应。
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返回的参数类型

这里的返回参数,一般是select语句用到的返回数据的参数类型。

(1)resultType

  1. 返回实体类
  1. 返回map
  1. 单字段返回基础类型

(2)resultMap

简单用法是解决表字段与实体类属性不一致的问题。

  1. 方式一:查询语句起别名
    <select id="selectAll" resultType="User">
        select id, name, pwd as password from user;
    </select>
  1. 方式二:返回值类型设置成:resultMap
    <!--只需要将不一致的字段进行对应,相当于返回了User,但修改了不一致的字段-->
    <resultMap id="resultMap" type="User">
        <result column="password" property="pwd"/>  
    </resultMap>

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

四、复杂查询

1、动态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。实体类里要加入对一的属性。

  • 关联-association【对一】
  • 集合-collection 【对多】

javaType 用来指定实体类中属性的类型
ofType 用来指定映射到List或集合中的pojo类型,泛型中的约束类型

(1)一对一

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

  1. 假设一个Article对应一个Author,Article里存放Author的id。在Article的实体类里,增加Author。
@Data
public class Article {

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

    // 加入需要关联的实体类
    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"/>
        
        <!-- 关联的实体类属性 -->
        <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;

    // 加入需要关联的实体类
    private Author author;

    // 需要关联的一对多的评论
    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. 查询结果

[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)

这些属性可以在外部进行配置,并可以进行动态替换。既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。例如:

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>-->


    <!--数据库环境-->
    <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 (注意,数据库名用中文报错)

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

2、类型别名(typeAliases)

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写,例如:

  1. 单个别名分别配置:
<typeAliases>
  <typeAlias alias="Author" type="com.example.Modle.Author"/>
  <typeAlias alias="Blog" type="com.example.Modle.Blog"/>
</typeAliases>
  1. 扫描包整个model包

会使用包内 Bean 的首字母小写的非限定类名来作为它的别名,首字母大写也支持。有注解则优先使用注解

    <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" 变为 resultType="Author"

3、设置(settings)

(1)驼峰命名转换

默认false,不进行转换。开启后将数据库字段的column_table与实体类的columnTable进行自动对应,这样查出来的数据才能赋给实体类。

    <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时,是否调用映射对象的 setter(map 对象时为 put)方法,默认mybatis不会处理这一字段,也就是不会调用null赋值给返回的对象。

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

(4)返回null的处理

默认false,当查询到记录,但返回行的所有列都是null时,MyBatis默认返回 null对象,而不会创建返回对象,当调用返回对象的方法时,容易导致空指针错误。
当开启这个设置时,MyBatis会创建返回对象,但对象是一个null实例,返回的实体类对象的所有属性都是null。

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

注意:如果表为空,或者根据条件查找不到记录,必定会返回null或空列表[]
上述设置只适用于,当mybatis查找到了表记录,但是返回的列全是null的时候。如果返回的列,不是全部为null,则会正常创建返回对象。

六、缓存

1、一级缓存:

默认开启,存在于SqlSession的生命周期中,什么是SqlSession的生命周期呢,简单的来说,只有同一个请求才会是同一个SqlSession,那么就是说只有同一个请求我查询第二次这个缓存才会生效。

2、二级缓存:

也称为全局缓存,存在于SqlSessionFactory 的生命周期中,可以理解为跨sqlSession;缓存是以namespace为单位的,不同namespace下的操作互不影响,但是在多人开发的环境下,我的不同的namespace完全是有可能操作同一张表的,那么会导致一个namespace的数据修改了一张表,但是另一个namespace的那张表的数据缓存没被修改,这样查询的数据就会错误。

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

七、使用注解开发

@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整合

待补充。。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,377评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,390评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,967评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,344评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,441评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,492评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,497评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,274评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,732评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,008评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,184评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,837评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,520评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,156评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,407评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,056评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,074评论 2 352

推荐阅读更多精彩内容

  • 1、MyBatis简介 MyBatis 是一款优秀的持久层框架 中文官网:https://mybatis.org/...
    CHeng_c0e9阅读 404评论 0 0
  • 之前学习MyBatis整理了一些笔记,笔记分为四个部分:1.MyBatis应用分析与实践[https://www....
    javacoo阅读 970评论 0 2
  • 小感悟: 自学Java也有一年了,基本上都是学习基础的教程,Java水很深,前面学习新知识后面忘了老知识,我也不知...
    卖流量的小嗨阅读 1,005评论 0 1
  • 一、重点知识 git 监视的是文件内容的修改 $ git checkout -- abc.txt : 其实是用版本...
    一花一世界yu阅读 887评论 0 2
  • 目录 1-3.持久层(名词,概念) 1-4.为啥需要Mybatis? 5、解决属性名和字段名不一致的问题 10-1...
    Java架构师顶顶阅读 1,320评论 0 0