程序员书籍笔记 程序员书籍笔记
  • HTML
  • CSS
  • JavaScript
  • 前端知识
  • Vue
  • MarkDown
  • git
  • Node.js
  • Linux
  • 51单片机
  • 四级
  • 第一学期课程
  • 操作系统
  • 计算机网络
  • 数据结构
  • 计算机组成原理
  • HTML5
  • Electron
  • 日记便签
  • 前端导航
GitHub (opens new window)
  • HTML
  • CSS
  • JavaScript
  • 前端知识
  • Vue
  • MarkDown
  • git
  • Node.js
  • Linux
  • 51单片机
  • 四级
  • 第一学期课程
  • 操作系统
  • 计算机网络
  • 数据结构
  • 计算机组成原理
  • HTML5
  • Electron
  • 日记便签
  • 前端导航
GitHub (opens new window)
  • Vue

  • Nuxt

  • Echarts

  • Node

  • git

  • express

  • 微信小程序

  • Spring

    • Spring基础01
    • Spring基础02
    • Spring基础03
    • SpringMVC基础01
    • SpringMVC基础02
    • Mybatis基础01
      • Mybatis
      • 快速开始
      • Mapper代理
      • 使用mybatisX工具
      • 起别名问题
      • 条件查询
        • 多条件查询
      • 动态SQL标签
      • 添加数据
      • 修改数据
      • 删除数据
        • 删除一行
        • 批量删除
      • 参数传递
        • 多参数传递
      • 注解开发
    • MybatisPlus基础01
    • SpringBoot快速开始
  • 后端知识

  • Markdown

  • project

  • 自用文档查询

  • 框架和软件
  • Spring
yuadh
2022-09-23
目录

Mybatis基础01

# Mybatis

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

# 快速开始

设置配置文件 resources/mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <package name="com.yuadh.user"/>
    </typeAliases>
    <environments default="defaultContMySql">
        <environment id="defaultContMySql">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/yuadh/mapper/mapper-user.xml"/>
    </mappers>
</configuration>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  • typeAliases : 设置 mapper 的 resultType 路径别名
  • <enviroments> : 主要配置内容,可以配置多个连接
  • mappers : 导入 mapper 映射文件

设置映射文件 resources/com/yuadh/mapper/mapper-user.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapperUser">
<!--  此处的resultType配置了别名,且只在select查询语句中使用  -->
    <select id="checkAll" resultType="User">
        select *
        from tb_user;
    </select>
</mapper>
1
2
3
4
5
6
7
8
9
10
11
  • namespace mapper文件的别名,文件名作用区别不同mapper文件
  • id 区别同一文件下的,执行语句

使用文件 index.java

public class Index {
    public static void main(String[] args) throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        User a = (User) sqlSession.selectList("mapperUser.checkAll").get(0);
        System.out.println(a);
        sqlSession.close();
    }
}
1
2
3
4
5
6
7
8
9
10
11
  • 根据配置文件获取到 InputStream ,根据名字利用类加载器从源码目录加载核心配置文件并生成一个输入流对象
  • sqlSessionFactory 从工厂中解析核心配置文件中的内容,并将解析出来的所有内容保存到一个容器中,在映射配置文件中配置方法 id 当成 map 的 key
  • sqlSession 是 mybatis 的核心对象,即能控制事物也能执行sql

# Mapper代理

Mapper代理开发可以有效解决映射配置文件中 namespace.id硬编码的问题

List<User> users = sqlSession.selectList("mapperUser.checkAll");
1

转换为

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> users = userMapper.checkAll();
1
2

使用 Mapper 代理必须满足以下4点要求

  • SQL映射文件和Mapper接口同名
  • SQL映射文件和Mapper接口在同一目录
  • SQL映射文件的 namespace 为Mapper接口的全限定名
  • SQL映射文件的SQL语句 id与Mapper接口的方法名、参数名、返回值名一致

可以使用包扫描的方式,将所有的Mapper文件加载到核心配置文件中

<mappers>
	<package name="com.yuadh.mapper"/>
</mappers>
1
2
3

示例

在 com\yuadh\mapper 包下创建接口 UserMapper ,同时在资源目录下创建同路径同名文件 UserMapper.xml 代理

interface

package com.yuadh.mapper;

import com.yuadh.user.User;

import java.util.List;

public interface UserMapper {
    List<User> selectAll();
    User selectById();
}

1
2
3
4
5
6
7
8
9
10
11

xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yuadh.mapper.UserMapper">
    <!--  此处的resultType配置了别名,且只在select查询语句中使用  -->
    <select id="selectAll" resultType="User">
        select *
        from tb_user;
    </select>
</mapper>
1
2
3
4
5
6
7
8
9
10
11

核心配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <package name="com.yuadh.user"/>
        <package name="com.yuadh.mapper"/>
    </typeAliases>
    <environments default="defaultContMySql">
        <environment id="defaultContMySql">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
<!--        <mapper resource="com/yuadh/mapper/mapper-user.xml"/>-->
        <package name="com.yuadh.mapper"/>
    </mappers>
</configuration>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

测试类

public static void main(String[] args) throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获取Mapper的代理对象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = userMapper.selectAll();
        System.out.println(users);
    }
1
2
3
4
5
6
7
8
9
10

# 使用mybatisX工具

IDEA安装 mybatisX 插件可以实现 mybatis 的高效开发

  • 跳转
  • 自动生成 xml
  • 自动构建 构造函数
  • 等等...

# 起别名问题

解决数据库和 java 类名字不一致的问题

方式一:

 <select id="selectAll" resultType="com.yuadh.pojo.Brand">
        select
        id, brand_name as brandName, company_name as companyName, ordered, description, status
        from tb_brand
    </select>
1
2
3
4
5

方式二:

使用 sql 片段

 <sql id="brand_column">
        id, brand_name as brandName, company_name as companyName, ordered, description, status
    </sql>
    <select id="selectAll" resultType="com.yuadh.pojo.Brand">
        select
        <include refid="brand_column" />
        from tb_brand
    </select>
1
2
3
4
5
6
7
8

方式三:使用别名配置

<mapper namespace="com.yuadh.mapper.BrandMapper">
    <resultMap id="brandResultMap" type="com.yuadh.pojo.Brand">
        <!--
               id:完成主键字段的映射
                   column:表的列名
                   property:实体类的属性名
               result:完成一般字段的映射
                   column:表的列名
                   property:实体类的属性名
           -->
        <result column="brand_name" property="brandName"/>
        <result column="company_name" property="companyName"/>
    </resultMap>
    <select id="selectAll" resultMap="brandResultMap">
        select * from tb_brand
    </select>
</mapper>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 条件查询

补充参数传递的两种方式

  • #{}:执行 SQL 时,会将 #{} 占位符替换为 ?
  • ${}:执行 SQL 时,会将 ${} 拼接为字符串

推荐使用 #{} , 拼接字符串容易有 SQL 注入的问题

在对参数进行传递时,需要使用 parameterType 对传递的参数类型进行定义,但是基本数据类型可以省略

<select id="selectById" parameterType="int" resultMap="brandResultMap">
    select *
    from tb_brand where id = ${id};
</select>
1
2
3
4

SQL 语句的特殊字符

  • 可以使用 &lt 转义字符
  • 可以使用 <![CDATA[....]]> 包裹多特殊字符的内容

示例

<select id="selectById" parameterType="int" resultMap="brandResultMap">
    select *
    from tb_brand where id = ${id};
</select>
1
2
3
4

mapper

public interface BrandMapper {
    List<Brand> selectAll();
    Brand selectById(int id);
}
1
2
3
4
Brand brand = brandMapper.selectById(1);
1

# 多条件查询

多中方式查询

mapper类

//多条件查询方式一
List<Brand> selectByCondition(@Param("status") int status, @Param("companyName") String companyName, @Param("brandName") String brandName);
//多条件查询方式二
List<Brand> selectByCondition(Brand brand);
//多条件查询方式三
List<Brand> selectByCondition(Map map);
1
2
3
4
5
6

mapper

 <!-- 多条件查询   -->
    <select id="selectByCondition" parameterType="com.yuadh.pojo.Brand" resultMap="brandResultMap">
        select *
        from tb_brand
        where status = #{status}
          and company_name like #{companyName}
          and brand_name like #{brandName};
    </select>
1
2
3
4
5
6
7
8

测试类

public static void main(String[] args) throws IOException {
        int status = 1;
        String companyName = "华为";
        String brandName = "华为";
        companyName = "%" + companyName + "%";
        brandName = "%" + brandName + "%";

        //1. 获取SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2. 获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //3. 获取Mapper接口的代理对象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
        //多条件查询方式一:
        //List<Brand> brands = brandMapper.selectByCondition(status,companyName,brandName);
        //System.out.println(brands);
        //多条件查询方式二:
        Brand brand = new Brand();
        brand.setStatus(status);
        brand.setBrandName(brandName);
        brand.setCompanyName(companyName);
  			//多条件查询方式三:
        Map map = new HashMap();
        map.put("status",status);
        map.put("companyName",companyName);
        map.put("brandName",brandName);
        System.out.println(brand);
        List<Brand> brands = brandMapper.selectByCondition(map);
        System.out.println(brands);
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

# 动态SQL标签

用户输入的查询条件不会每次都固定,为了解决这类问题, Mybatis 对动态 SQL 提供了强大的支持

  • if
  • choose(when,otherwise)
  • trim(where,set)
  • foreach

if标签

test 逻辑表达式

<select id="selectByCondition" resultMap="brandResultMap">
    select *
    from tb_brand
    where
    <if test="status != null">
        status = #{status}
    </if>
    <if test="companyName != null and companyName != '' ">
        and company_name like #{companyName}
    </if>
    <if test="brandName != null and brandName != '' ">
        and brand_name like #{brandName}
    </if>
</select>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

这样的写法存在问题,如果 status 为空, SQL 语句就变成了

select * from tb_brand where and company_name like ? and brand_name like ?
1

这类清空可以使用 where 标签来解决

where标签

<select id="selectByCondition" resultMap="brandResultMap">
    select *
    from tb_brand
    <where>
        <if test="status != null">
            and status = #{status}
        </if>
        <if test="companyName != null and companyName != '' ">
            and company_name like #{companyName}
        </if>
        <if test="brandName != null and brandName != '' ">
            and brand_name like #{brandName}
        </if>
    </where>
</select>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

where标签会动态的去掉第一个条件前的 and

choose标签

<select id="selectByConditionSingle" resultMap="brandResultMap">
    select *
    from tb_brand
    <where>
        <choose><!--相当于switch-->
            <when test="status != null"><!--相当于case-->
                status = #{status}
            </when>
            <when test="companyName != null and companyName != '' "><!--相当于case-->
                company_name like #{companyName}
            </when>
            <when test="brandName != null and brandName != ''"><!--相当于case-->
                brand_name like #{brandName}
            </when>
        </choose>
    </where>
</select>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

按条件在when中选择执行

foreach标签

可以用来迭代对象

  • collection :将数组参数,封装为一个 Map 集合
    • 默认:array = 数组
    • 使用 @Param 注解改变map集合的默认key的名称
  • item:本次迭代获取到的元素
  • separator:集合项迭代之间的分割符,不会在最后的结尾添加多余的分割符
  • open:在拼接SQL语句之前拼接的语句,只会拼接一次
  • close:在拼接SQL语句拼接后拼接的语句,只会拼接一次
<delete id="deleteByIds">
    delete from tb_brand where id
    in
    <foreach collection="array" item="id" separator="," open="(" close=")">
        #{id}
    </foreach>
    ;
</delete>
1
2
3
4
5
6
7
8

得到的 SQL 语句是

delete from tb_brand where id in (1,2,3);
1

# 添加数据

接口类

void add(Brand brand);
1

mapper

<insert id="add" useGeneratedKeys="true" keyProperty="id">
    insert into tb_brand (brand_name, company_name, ordered, description, status)
    values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
</insert>
1
2
3
4
  • useGeneratedKeys:是够获取自动增长的主键值。true表示获取
  • keyProperty :指定将获取到的主键值封装到哪儿个属性里

测试类

public static void main(String[] args) throws IOException {
    //接收参数
    int status = 0;
    String companyName = "xx手机";
    String brandName = "xx";
    String description = "手机中的战斗机";
    int ordered = 200;

    //封装对象
    Brand brand = new Brand();
    brand.setStatus(status);
    brand.setCompanyName(companyName);
    brand.setBrandName(brandName);
    brand.setDescription(description);
    brand.setOrdered(ordered);
    //1. 获取SqlSessionFactory
    String resource = "mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

    //2. 获取SqlSession对象
    SqlSession sqlSession = sqlSessionFactory.openSession();

    //3. 获取Mapper接口的代理对象
    BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);

    brandMapper.add(brand);
    sqlSession.commit();
    System.out.println(brand);
    sqlSession.close();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 修改数据

接口类

void update(Brand brand);
1

mapper

<update id="update">
    update tb_brand
    <set>
        <if test="brandName != null and brandName != ''">
            brand_name = #{brandName},
        </if>
        <if test="companyName != null and companyName != ''">
            company_name = #{companyName},
        </if>
        <if test="ordered != null">
            ordered = #{ordered},
        </if>
        <if test="description != null and description != ''">
            description = #{description},
        </if>
        <if test="status != null">
            status = #{status}
        </if>
    </set>
    where id = #{id};
</update>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

测试类

public void testUpdate() throws IOException {
    //接收参数
    int status = 0;
    String companyName = "波导手机";
    String brandName = "波导";
    String description = "波导手机,手机中的战斗机";
    int ordered = 200;
    int id = 6;

    //封装对象
    Brand brand = new Brand();
    brand.setStatus(status);
    //        brand.setCompanyName(companyName);
    //        brand.setBrandName(brandName);
    //        brand.setDescription(description);
    //        brand.setOrdered(ordered);
    brand.setId(id);

    //1. 获取SqlSessionFactory
    String resource = "mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    //2. 获取SqlSession对象
    SqlSession sqlSession = sqlSessionFactory.openSession();
    //SqlSession sqlSession = sqlSessionFactory.openSession(true);
    //3. 获取Mapper接口的代理对象
    BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
    //4. 执行方法
    int count = brandMapper.update(brand);
    System.out.println(count);
    //提交事务
    sqlSession.commit();
    //5. 释放资源
    sqlSession.close();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# 删除数据

# 删除一行

接口类

void deleteById(int id);
1

mapper

<delete id="deleteById">
    delete from tb_brand where id = #{id};
</delete>
1
2
3

测试类

 @Test
public void testDeleteById() throws IOException {
    //接收参数
    int id = 6;

    //1. 获取SqlSessionFactory
    String resource = "mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    //2. 获取SqlSession对象
    SqlSession sqlSession = sqlSessionFactory.openSession();
    //SqlSession sqlSession = sqlSessionFactory.openSession(true);
    //3. 获取Mapper接口的代理对象
    BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
    //4. 执行方法
    brandMapper.deleteById(id);
    //提交事务
    sqlSession.commit();
    //5. 释放资源
    sqlSession.close();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 批量删除

测试类

void deleteByIds(int[] ids);
1

mapper

<delete id="deleteByIds">
    delete from tb_brand where id
    in
    <foreach collection="array" item="id" separator="," open="(" close=")">
        #{id}
    </foreach>
    ;
</delete>
1
2
3
4
5
6
7
8

测试类

@Test
public void testDeleteByIds() throws IOException {
    //接收参数
    int[] ids = {5,7,8};

    //1. 获取SqlSessionFactory
    String resource = "mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    //2. 获取SqlSession对象
    SqlSession sqlSession = sqlSessionFactory.openSession();
    //SqlSession sqlSession = sqlSessionFactory.openSession(true);
    //3. 获取Mapper接口的代理对象
    BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
    //4. 执行方法
    brandMapper.deleteByIds(ids);
    //提交事务
    sqlSession.commit();
    //5. 释放资源
    sqlSession.close();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 参数传递

# 多参数传递

<select id="select" resultType="user">
	select *
    from tb_user
    where 
    	username=#{username}
    	and password=#{password}
</select>
1
2
3
4
5
6
7

接口类

User select(@Param("username") String username,@Param("password") String password);
1

接收多个参数需要使用 @Param 注解

在接口中定义多个参数,Mybatis 会将这些参数封装为 Map 集合对象,值就是参数值,而键没有使用 @Param 注解时有一下命名规则

以 arg 开头 :第一个参数就叫 arg0,第二个参数就叫 arg1,以此类推。如:

map.put("arg0",参数值1);

map.put("arg1",参数值2);

以 param 开头 : 第一个参数就叫 param1,第二个参数就叫 param2,依次类推。如:

map.put("param1",参数值1);

map.put("param2",参数值2);

验证

<select id="select" resultType="user">
	select *
    from tb_user
    where 
    	username=#{arg0}
    	and password=#{arg1}
</select>
1
2
3
4
5
6
7

这样的书写,代码可读性差。为了解决这类问题 使用 @Param 注解

# 单参数传递

  • POJO类型:属性名和参数占位符名称一致
  • Map 集合类型:map集合的键名和参数占位符名一致
  • Collection 集合类型、List 集合类型、Array 数组类型 使用 @Param 注解
  • 简单类型,参数名占位符随意

# 注解开发

示例

@Select(value = "select * from tb_user where id = #{id}")
public User select(int id);
1
2
  • 查询 :@Select
  • 添加 :@Insert
  • 修改 :@Update
  • 删除 :@Delete
编辑 (opens new window)
上次更新: 2023/02/07, 14:51:48
SpringMVC基础02
MybatisPlus基础01

← SpringMVC基础02 MybatisPlus基础01→

Theme by Vdoing | Copyright © 2021-2023 yuadh
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×