likes
comments
collection
share

什么是 MyBatis ?如何使用 MyBatis ?

作者站长头像
站长
· 阅读数 15

1. MyBatis 是什么?

  MyBatis 是一个开源的 Java 持久化框架,它用于简化数据库访问和操作的过程。它提供了一种将数据库操作与 Java 对象之间进行映射的方式,使得开发人员可以使用简单的 XML 配置或注解来定义 SQL 查询、插入、更新和删除等操作。

  MyBatis 的核心思想是将 SQL 语句与 Java 代码解耦,通过将 SQL 语句和参数绑定到预定义的查询语句或存储过程中,使得开发人员可以通过调用简单的方法来执行数据库操作,而无需编写冗长的 JDBC 代码。

2. 创建数据库和表

  这里先创建一个数据库,以方便后面的测试。

-- 创建数据库
drop database if exists mycnblog;
create database mycnblog DEFAULT CHARACTER SET utf8mb4;

-- 使用数据数据
use mycnblog;

-- 创建表[用户表]
drop table if exists  userinfo;
create table userinfo(
    id int primary key auto_increment,
    username varchar(100) not null,
    password varchar(32) not null,
    photo varchar(500) default '',
    createtime timestamp default current_timestamp,
    updatetime timestamp default current_timestamp,
    `state` int default 1
) default charset 'utf8mb4';

-- 创建文章表
drop table if exists  articleinfo;
create table articleinfo(
    id int primary key auto_increment,
    title varchar(100) not null,
    content text not null,
    createtime timestamp default current_timestamp,
    updatetime timestamp default current_timestamp,
    uid int not null,
    rcount int not null default 1,
    `state` int default 1
)default charset 'utf8mb4';

-- 创建视频表
drop table if exists videoinfo;
create table videoinfo(
  	vid int primary key,
  	`title` varchar(250),
  	`url` varchar(1000),
		createtime timestamp default current_timestamp,
		updatetime timestamp default current_timestamp,
  	uid int
)default charset 'utf8mb4';

-- 添加用户信息

INSERT INTO `mycnblog`.`userinfo` (`id`, `username`, `password`, `photo`, `createtime`, `updatetime`, `state`) VALUES
(1, 'admin', 'admin', '', '2021-12-06 17:10:48', '2021-12-06 17:10:48', 1),(2,'小明','12345','','2022-12-06 17:10:48', '2022-12-06 17:10:48', 1);


-- 文章添加测试数据
insert into articleinfo(title,content,uid)
    values('Java','Java正文',1);
    
-- 添加视频
insert into videoinfo(vid,title,url,uid) values(1,'java title','http://www.baidu.com',1);

3. 添加 MyBatis 框架

3.1 创建新项目

  在创建 Spring Boot 的时候,添加MyBatis FrameworkMySQL Driver

什么是 MyBatis ?如何使用 MyBatis ?

3.2 在老项目上添加

  当在老项目上添加时,这就要借助EditStarters插件(IDEA插件商店下载),下载过后在pom.xml中鼠标右键:

什么是 MyBatis ?如何使用 MyBatis ?

什么是 MyBatis ?如何使用 MyBatis ?

什么是 MyBatis ?如何使用 MyBatis ?

什么是 MyBatis ?如何使用 MyBatis ?

3.3 配置连接

3.3.1 配置连接字符串

  在application.properties中配置如下信息(设置自己的数据库与密码):

    spring.datasource.url=jdbc:mysql://127.0.0.1:3306/自己数据库名称?characterEncoding=utf8&useSSL=false
    spring.datasource.username=root
    # 设置密码
    spring.datasource.password=自己的密码
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

    # 设置 Mybatis 的 xml 保存路径
    mybatis.mapper-locations=classpath:/mybatis/*Mapper.xml

  在 MyBatis 中,Mapper 文件用于定义数据库操作的 SQL 语句和映射关系。每个 Mapper 文件通常对应一个数据访问接口(DAO 接口),其中包含了一组与数据库相关的方法。

  mybatis.mapper-locations=classpath:/mybatis/*Mapper.xml 的意思是告诉 MyBatis 在类路径下的 mybatis 目录中查找所有以 Mapper.xml 结尾的文件作为 Mapper 文件。classpath: 表示在类路径下搜索,/mybatis/ 表示 mybatis 目录的路径,*Mapper.xml 表示匹配任意名称以 Mapper.xml 结尾的文件。

  然后打开数据库服务,之后开始运行程序,如果没有报错就算成功(废话)。

什么是 MyBatis ?如何使用 MyBatis ?

4. 使用 MyBatis

4.1 使用前准备

  一般是用下⾯的流程来实现 MyBatis 操作的。

什么是 MyBatis ?如何使用 MyBatis ?

  1. resources下创建mybatis目录。

什么是 MyBatis ?如何使用 MyBatis ?

  1. 创建一个实体类UserEntity以及一个Mapper接口。

什么是 MyBatis ?如何使用 MyBatis ?

@Data //自动生成set、get、toString
public class UserEntity {
    //与表的属性一一对应
    private Integer id;
    private String username;
    private String password;
    private String photo;
    private LocalDateTime createtime;
    private LocalDateTime updatetime;
    private Integer state;
}
@Mapper //表示
public interface UserMapper {
    //查询所用的 User
    List<UserEntity> getAll();
}

  @Mapper 注解用于在 MyBatis 中标识一个接口类作为 Mapper 接口。Mapper 接口是定义数据库操作的接口,通过该接口可以调用 MyBatis 提供的 SQL 查询、插入、更新和删除等操作。

  使用 @Mapper 注解标注接口后,MyBatis 将会自动为该接口生成实现类,并将其注册到 MyBatis 的上下文中,从而可以在应用程序中直接使用该接口进行数据库操作

  1. 添加.xml文件

什么是 MyBatis ?如何使用 MyBatis ?

填如下代码:

<?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.example.demo.mapper.UserMapper">

</mapper>

  namespace 属性的值应该与对应的 Mapper 接口的全限定名(包括包路径)一致。通过指定 namespace,MyBatis 将会把该 Mapper XML 文件与对应的 Mapper 接口关联起来。

  这样,MyBatis 将会将该 Mapper XML 文件与 com.example.demo.mapper.UserMapper 接口关联起来,使得接口中的方法可以与 XML 文件中定义的 SQL 语句进行映射。

  1. 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.example.demo.mapper.UserMapper">
        <select id="getAll" resultType="com.example.demo.entity.UserEntity">
            select * from userinfo
        </select>
    </mapper>

  resultType 用于指定 SQL 查询结果的类型。它定义了查询结果应该映射到的实体类或其他数据类型。

  <select>查询标签:是用来执行数据库的查询操作的

  id:是和 Interface(接口)中定义的方法名称⼀样的,表示对接口的具体实现方法。

  1. 按照分层来查询数据

什么是 MyBatis ?如何使用 MyBatis ?

@Service
public class UserService {
    @Autowired //注入对像,注意这里是userMapper接口的代理对象
    private UserMapper userMapper;

    public List<UserEntity> getAll(){
        //这个方法在 .xml 文件中已经实现了
        return userMapper.getAll();
    }
}
@RestController
@RequestMapping("/user")
public class UserController {
 
    @Autowired //注入 UserService 对象
    private UserService userService;

    @RequestMapping("/getall")
    public List<UserEntity> getAll(){
        return userService.getAll();
    }
}

  Mapper 接口的实现类是由 MyBatis 在运行时动态生成的。该实现类会根据 Mapper 接口中定义的方法及相应的 SQL 映射关系,自动生成对应的数据库操作代码。

什么是 MyBatis ?如何使用 MyBatis ?

4.2 通过参数来查询数据

加一个方法:传入一个id,通过id来查询User

@Mapper
public interface UserMapper {
    //查询所用的 User
    List<UserEntity> getAll();

    //根据 id 查询用户对象
    UserEntity getUserById(@Param("id") Integer id);
}

  在UserMapper.xml中:

什么是 MyBatis ?如何使用 MyBatis ?

  ${}匹配传进来的参数,${} 是一种占位符语法,用于在 SQL 语句中动态地替换参数。

  @Param() 注解用于指定方法参数的名称(就是重命名),并在SQL语句中引用这些参数。它的主要作用是为了解决方法中存在多个参数时,MyBatis无法确定参数的名称而导致的问题。

(1)通过 url 来测试

  在UserService、UserController 中添加方法:

什么是 MyBatis ?如何使用 MyBatis ?

什么是 MyBatis ?如何使用 MyBatis ?

什么是 MyBatis ?如何使用 MyBatis ?

(2)通过单元测试的方式

Spring Boot 的单元测试 - 掘金 (juejin.cn)

什么是 MyBatis ?如何使用 MyBatis ?

什么是 MyBatis ?如何使用 MyBatis ?

什么是 MyBatis ?如何使用 MyBatis ?

什么是 MyBatis ?如何使用 MyBatis ?

  添加后,补充代码(就当作 main 方法):

@SpringBootTest  //表示当前单元测试类是运行在 Spring  Boot 环境中的
class UserMapperTest {

    @Autowired
    private  UserMapper userMapper;

    @Test
    void getUserById() {
        UserEntity user = userMapper.getUserById(1);
        System.out.println(user);
    }
}

  运行结果: 什么是 MyBatis ?如何使用 MyBatis ?

4.3 占位符 ${} 与 #{}

  ${}#{}都是用于占位的特殊符号,为了演示它们的区别,这里需要输出执行的 SQL 语句,要想输出 SQL 语句还要得进行一些配置:

application.properties配置文件中添加如下代码:

        # 打印 MyBatis 执行的 SQL 语句
        mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
        # 设置日志等级
        logging.level.com.example.demo=debug
  1. ${} 占位符:

    • ${} 是用于动态拼接查询语句中的参数占位符。
    • ${} 会将传入的值直接插入到查询语句中,不会进行安全处理。
    • ${} 占位符主要用于拼接静态的SQL语句片段或引用已定义的变量或属性。

  这里还是执行上面单元测试中的getUserById()方法。

什么是 MyBatis ?如何使用 MyBatis ?

  1. #{} 占位符:

    • #{} 是用于预编译查询语句中的参数占位符。
    • #{} 会将传入的值进行安全处理,防止SQL注入攻击。
    • #{} 占位符会将参数值转义并插入到查询语句中,使用占位符时,参数值会被当做预编译语句的参数传递给数据库,从而提供更好的安全性。

什么是 MyBatis ?如何使用 MyBatis ?

什么是 MyBatis ?如何使用 MyBatis ?

4.3.1 ${} 与 #{} 替换字符串的情况

  添加一个方法:通过名字来查询用户。

(1) ${} 替换字符串

UserMapper:

//同过姓名来查询 用户
UserEntity getUserByName(@Param("username") String name);

UserMapper.xml:

    <select id="getUserByName" resultType="com.example.demo.entity.UserEntity" >
        select * from userinfo where username=${username}
    </select>

UserMapperTest:

    @Test
    void getUserByName() {
        UserEntity user = userMapper.getUserByName("小明");
        System.out.println(user);
    }

结果:报错了

什么是 MyBatis ?如何使用 MyBatis ?

  解决办法:

  1. 方法一:
@Test
void getUserByName() {
    UserEntity user = userMapper.getUserByName("\'小明\'");
    System.out.println(user);
}
  1. 方法二:
        <select id="getUserByName" resultType="com.example.demo.entity.UserEntity" >
            select * from userinfo where username='${username}' 
        </select>

(2) #{} 替换字符串

    <select id="getUserByName" resultType="com.example.demo.entity.UserEntity" >
        select * from userinfo where username=#{username}
    </select>

结果:成功 什么是 MyBatis ?如何使用 MyBatis ?

4.3.2 SQL 注入

   ${} 可能会被 SQL 注入,#{}则是防止SQL注入攻击,这里演示一下什么是SQL注入。

添加一个方法:登录,传入一个对象,判断用户名与密码是否正确。

UserMapper:

    //登录的方法
    UserEntity login(UserEntity user);

UserMapper.xml:

    <select id="login" resultType="com.example.demo.entity.UserEntity">
        select * from userinfo where username = '${username}' and password = '${password}'
    </select>

username = '${username}'中的username属性框架已经自动加载好了。(user.username在这里是错误的)

UserMapperTest:

@Test
void login() {
    UserEntity user = new UserEntity();
    user.setUsername("小明");
    user.setPassword("");//不知道密码
    UserEntity user2 = userMapper.login(user);
    System.out.println(user2);
}

  如果我只知道“小明”这个用户名,不知道密码,可以用SQL注入的方式获取所用的数据:

(ps:本博客的目的是为了提供学习和研究的参考,介绍了 SQL 注入等安全漏洞和攻击的概念。请注意,这些内容仅供学习和了解安全领域的知识,不应用于非法活动或恶意目的。)

@Test
void login() {
    UserEntity user = new UserEntity();
    user.setUsername("' OR username = '小明' LIMIT 1 -- ");
    user.setPassword("");
    UserEntity user2 = userMapper.login(user);
    System.out.println(user2);
}

  我们只需要将用户名输入为:' OR username = '小明' LIMIT 1 -- ,就能获取到数据。为什么呢?

    SELECT * FROM userinfo WHERE username = '' OR username = '小明' LIMIT 1 -- ' AND password = ''

  这个查询语句中的 LIMIT 1 限制了结果集只返回一条记录,而注释符号 -- 则注释掉了原本的密码验证部分。

结果:

什么是 MyBatis ?如何使用 MyBatis ?

(1)预防 SQL 注入

  使用 ${}易被 SQL 注入,而 #{} 则可以避免SQL注入:

同样的代码,改一下.xml里的${}


    <select id="login" resultType="com.example.demo.entity.UserEntity">
        select * from userinfo where username = #{username} and password = #{password}
    </select>

结果:

什么是 MyBatis ?如何使用 MyBatis ?

查找失败,返回null

4.3.3 ${} 的优点

  我们想排序的时候,${} 就发挥它的优势了,就比如下面的场景:

什么是 MyBatis ?如何使用 MyBatis ?

    select * from userinfo order by id ${sort}

  使⽤ ${sort} 可以实现排序查询,而使用#{sort} 就不能实现排序查询了,因为当使用 #{sort} 查询时,如果传递的值为 String 则会加单引号,就会导致sql错误。

4.4 增、删、改操作

4.4.1 修改数据

  修改密码:


    //修改密码
    Integer updatePassword(@Param("id") Integer id,@Param("passWord") String passWord,@Param("newPassWord") String newPassWord);
    <update id="updatePassword">
        update userinfo set password=#{newPassWord}
        where id=#{id} and password=#{passWord}
    </update>

返回的值为修改的行数。

@Transactional //事务,不会污染数据库
@Test
void updatePassword() {
    Integer n = userMapper.updatePassword(2,"12345","000000");
    System.out.println("修改的行数:" + n);
}

结果:

什么是 MyBatis ?如何使用 MyBatis ?

4.4.2 删除数据

  删除用户:

    //删除用户
    Integer dalById(@Param("id") Integer id);
        <delete id="dalById">
            delete from userinfo where id = #{id}
        </delete>
@Transactional
@Test
void dalById() {
    Integer n = userMapper.dalById(1);
    System.out.println("删除的行数:" + n);
}

  当一个方法被标记为 @Transactional 时,Spring 框架会在方法开始之前启动一个事务,并在方法结束时自动提交或回滚事务。

4.4.3 增加数据

(1)返回添加的行数

    //添加用户
    Integer addUser(UserEntity user);
    <insert id="addUser">
        insert into userinfo(username,password) values(#{username},#{password})
    </insert>
@Test
void addUser() {
    UserEntity user = new UserEntity();
    user.setUsername("王五");
    user.setPassword("12346789");
    Integer n = userMapper.addUser(user);
    System.out.println("添加的行数:" + n);
    System.out.println(user);
}

什么是 MyBatis ?如何使用 MyBatis ?

(2)返回自动生成的主键

    //添加用户,返回自增的主键
    Integer addUserGetKey(UserEntity user);
    <insert id="addUserGetKey" useGeneratedKeys="true" keyProperty="id">
        insert into userinfo(username,password) values(#{username},#{password})
    </insert>
@Test
void addUserGetKey() {
    UserEntity user = new UserEntity();
    user.setUsername("李四");
    user.setPassword("12346789");
    Integer n = userMapper.addUserGetKey(user);
    System.out.println("变动的行数:" + n);
    System.out.println(user);
}

什么是 MyBatis ?如何使用 MyBatis ?

  useGeneratedKeys是一个布尔类型的属性,用于指示是否使用自动生成的主键keyProperty是一个字符串类型的属性,用于指定主键值应该存储在哪个Java对象的属性中。

4.5 like 模糊查询

    //like 模糊查询
    List<UserEntity> getListByName(@Param("username") String username);
    <select id="getListByName" resultType="com.example.demo.entity.UserEntity">
        select * from userinfo where username like '%#{username}%'
    </select>
@Test
void getListByName() {
    String username = "张";
    List<UserEntity> list = userMapper.getListByName(username);
    for(UserEntity user:list){
        System.out.println(user);
    }
}

结果:报错了

什么是 MyBatis ?如何使用 MyBatis ?

  为什么报错了呢?因为${}占位符会自动加单引号,就变为了:like '%'username'%';

修改后的代码:

    <select id="getListByName" resultType="com.example.demo.entity.UserEntity">
        select * from userinfo where username like concat('%',#{username},'%')
    </select>

  在MySQL中,使用CONCAT函数可以将两个或多个字符串连接在一起。

什么是 MyBatis ?如何使用 MyBatis ?

4.6 返回类型 resultMap

  如果实体类与数据库表中的属性不一致的时候,用resultType类型就行不通了:

什么是 MyBatis ?如何使用 MyBatis ?

什么是 MyBatis ?如何使用 MyBatis ?

    <select id="getUserById" resultType="com.example.demo.entity.UserEntity">
        select * from userinfo where id = #{id}
    </select>
@Test
void getUserById() {
    UserEntity user = userMapper.getUserById(1);
    System.out.println(user);
}

结果:

什么是 MyBatis ?如何使用 MyBatis ?

  发现name映射不到对象的属性上,这时候有两种方法可以解决:

(1)直接在 SQL 中换名:

    <select id="getUserById" resultType="com.example.demo.entity.UserEntity">
        select id, username as name, password, photo, ...... from userinfo where id = #{id}
    </select>

(2) 使用resultMap:

    <resultMap id="BaseMap" type="com.example.demo.entity.UserEntity">
        <!-- 标识主键的映射 -->
        <id property="id" column="id"></id>
        <!-- 其它属性的映射 -->
        <result property="name" column="username"></result>
        <result property="password" column="password"></result>
        <result property="createtime" column="createtime"></result>
        <result property="updatetime" column="updatetime"></result>
        <result property="photo" column="photo"></result>
        <result property="state" column="state"></result>
    </resultMap>

    <select id="getUserById" resultMap="BaseMap">
        select * from userinfo where id = #{id}
    </select>

  <resultMap>元素用于定义查询结果的映射规则,将查询结果映射到Java对象上。下面是对<resultMap>元素的解释:

  • id: 指定了结果映射的唯一标识符,这里是"BaseMap"。
  • type: 指定了映射结果的Java对象类型,这里是com.example.demo.entity.UserEntity。在这个示例中,查询结果将映射到UserEntity类的实例上。
//根据 id 查询用户对象
UserEntity getUserById(@Param("id") Integer id);
@Test
void getUserById() {
    UserEntity user = userMapper.getUserById(1);
    System.out.println(user);
}

结果:

什么是 MyBatis ?如何使用 MyBatis ?

(后面把name改回username)

4.6 多表查询

  我们的数据库表有:

userinfo: 什么是 MyBatis ?如何使用 MyBatis ?

articleinfo: 什么是 MyBatis ?如何使用 MyBatis ?

  这时候我想查询Java这篇文章,要求要有作者的名字,这时候得多表连接查询了。

  1. 创建实体类以及对应的接口

什么是 MyBatis ?如何使用 MyBatis ?

  在 MyBatis 中,VO 是指值对象(Value Object)。值对象是一种轻量级的对象,用于封装多个属性或字段的数据。它主要用于数据传输和封装,而不包含业务逻辑。在 MyBatis 中, VO 通常用于封装查询结果或传递参数。 下面就是用来返回多表查询的结果的。

@Data
public class ArticleInfo {
    private Integer id;
    private String title;
    private String content;
    private LocalDateTime createtime;
    private LocalDateTime updatetime;
    private Integer uid;
    private Integer rcount;
    private Integer state;
}
@Data
public class ArticleInfoVO extends ArticleInfo {
    private String username;

    @Override
    public String toString() {
        return "ArticleInfoVO{" +
                "username='" + username + '\'' +
                "} " + super.toString();
    }
}
@Mapper
public interface ArticleMapper {
    //查询文章详情
    ArticleInfoVO getDetail(@Param("id") Integer id);
}
  1. 配置 .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">

<mapper namespace="com.example.demo.mapper.ArticleMapper">
    <select id="getDetail" resultType="com.example.demo.entity.vo.ArticleInfoVO">
        select a.*,u.username from articleinfo a
        left join userinfo u on u.id = a.uid
        where a.id = #{id}
    </select>
</mapper>
  1. 单元测试
@SpringBootTest
class ArticleMapperTest {
    @Autowired
    private ArticleMapper articleMapper;
    
    @Test
    void getDetail() {
        ArticleInfoVO articleInfoVO = articleMapper.getDetail(1);
        System.out.println(articleInfoVO);
    }
}

结果:

什么是 MyBatis ?如何使用 MyBatis ?

5. 动态 SQL

  动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。—— mybatis – MyBatis 3 | 动态 SQL

用一句话总结就是在 .xml 中用判断语句。

5.1 <if> 标签

  在注册⽤户的时候,可能会有这样⼀个问题:

什么是 MyBatis ?如何使用 MyBatis ?

  注册分为两种字段:必填字段和⾮必填字段,那如果在添加用户的时候有不确定的字段传入,程序应该如何实现呢?

    //添加用户
    Integer addUser2(UserEntity user);
    <insert id="addUser2">
        insert into userinfo(
            username,
            password
            <if test="photo!=null and photo !='' ">
                ,photo
            </if>
        ) values(
            #{username},
            #{password}
            <if test="photo != null and photo !='' ">
                ,#{photo}
            </if>
        )
    </insert>
    @Transactional
    @Test
    void addUser2() {
        String username = "老王";
        String password = "123456";
        UserEntity user = new UserEntity();
        user.setUsername(username);注意 test 中的 sex,是传⼊对象中的属性,不是数据库字段
        user.setPassword(password);
        int result = userMapper.addUser2(user);
        System.out.println("添加:" + result);
    }

  如果条件为真,则 <if> 标签包含的 SQL 语句将被执行(拼接);否则,将被忽略。

  注意 test 中的 sex,是传入对象中的属性,不是数据库字段。

什么是 MyBatis ?如何使用 MyBatis ?

5.2 <trim> 标签

  虽然用<if>可以解决很多问题,但是它也有局限性,比如极端情况下,当所有的属性都是非必填的时候,xmlSQL语句的逗号不好处理,这时候用 <trim>就比较方便了。

  <trim> 标签是用于处理 SQL 查询语句中多余空白和动态拼接的元素之一。它可以用来去除不必要的空白字符,并在需要时动态添加或移除 SQL 语句的部分

//添加用户
Integer addUser3(UserEntity user);
<insert id="addUser3">
    insert into userinfo
    <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test="username != null and username != '' ">
            username,
        </if>
        <if test="password != null and password != '' ">
            password,
        </if>
        <if test="photo != null and photo != '' ">
            photo,
        </if>
    </trim>
    <trim prefix="values(" suffix=")" suffixOverrides=",">
        <if test="username != null and username != '' ">
            #{username},
        </if>
        <if test="password != null and password != '' ">
            #{password},
        </if>
        <if test="photo != null and photo != '' ">
            #{photo},
        </if>
    </trim>
</insert>
@Transactional
@Test
void addUser3() {
    String username = "老王";
    String password = "123456";
    UserEntity user = new UserEntity();
    user.setUsername(username);
    user.setPassword(password);
    int result = userMapper.addUser2(user);
    System.out.println("添加:" + result);
}

<trim> 标签具有以下属性:

  • prefix:在 <trim> 标签包含的 SQL 语句之前添加的字符串。
  • suffix:在 <trim> 标签包含的 SQL 语句之后添加的字符串。
  • prefixOverrides:如果 SQL 语句以指定的字符串开头,则将其从 SQL 语句中移除。
  • suffixOverrides:如果 SQL 语句以指定的字符串结尾,则将其从 SQL 语句中移除。

结果:

什么是 MyBatis ?如何使用 MyBatis ?

5.3 <where> 标签

  有如下场景:根据 id 或 文章名(title)来查询文章,如果都为空则返回全部文章,并且id、title都是非必传的,这里需要处理xml中的where

//通过 id 或 标题 来查询文章
List<ArticleInfoVO> getListByIdOrTitle(@Param("id") Integer id, @Param("title") String title);
@Test
void getListByIdOrTitle() {
    List<ArticleInfoVO> list = articleMapper.getListByIdOrTitle(null,"Java");
    System.out.println(list.size());
}

对于 .xml 文件中的写法有三种:

  1. 第一种:
<select id="getListByIdOrTitle" resultType="com.example.demo.entity.vo.ArticleInfoVO">
    select * from articleinfo
    where 1=1
    <if test="id!=null and id>0">
        and id=#{id}
    </if>
    <if test="title!=null and title!='' ">
        and title like concat('%',#{title},'%')
    </if>
</select>

结果:

什么是 MyBatis ?如何使用 MyBatis ?

  1. 第二种:
<select id="getListByIdOrTitle" resultType="com.example.demo.entity.vo.ArticleInfoVO">
    select * from articleinfo
    <trim ="where" suffixOverrides="and">
        <if test="id!=null and id>0">
            id=#{id} and
        </if>
        <if test="title!=null and title!='' ">
            title like concat('%',#{title},'%')
        </if>
    </trim>
</select>

  当idtitle都为null的时候,refix不会执行。

什么是 MyBatis ?如何使用 MyBatis ?

  1. 第三种:<where>标签
<select id="getListByIdOrTitle" resultType="com.example.demo.entity.vo.ArticleInfoVO">
    select * from articleinfo
    <where>
        <if test="id!=null and id>0">
            id=#{id}
        </if>
        <if test="title!=null and title!='' ">
            and title like concat('%',#{title},'%')
        </if>
    </where>
</select>

  <where>标签,当有至少一个条件发生的时候,它会自动生成 where;并且,<where>标签会自动移除前导的(后导不行)连接符(and 或者 or),确保生成的SQL语句语法正确。

结果:

什么是 MyBatis ?如何使用 MyBatis ?

5.4 <set>标签

  根据传入的用户对象属性来更新用户数据:

//根据传入的用户对象属性来更新用户数据
Integer update(UserEntity user);
<update id="update">
    update userinfo
    <set>
        id = #{id},
        <if test="username!=null">
            username=#{username},
        </if>
        <if test="password!=null">
            password=#{password},
        </if>
        <if test="photo!=null">
            photo=#{photo},
        </if>
        <if test="createtime!=null">
            createtime=#{createtime},
        </if>
        <if test="updatetime!=null">
            updatetime=#{updatetime},
        </if>
        <if test="state!=null">
            state=#{state}
        </if>
    </set>
    where id = #{id}
</update>
@Transactional
@Test
void update() {
    UserEntity user = new UserEntity();
    user.setId(2);
    user.setPassword("99999");
    user.setUsername("小明");
    userMapper.update(user);
}

结果:

什么是 MyBatis ?如何使用 MyBatis ?

  <set><where>是一样的,可以自动添加<set>,以上<set>标签也可以使用 <trim prefix="set" suffixOverrides=","> 替换,需要注意的是<set>移除的是后导逗号。

5.5 <foreach>标签

  对集合进行遍历时可以使用该标签。<foreach>标签有如下属性:

  • collection:指定要迭代的集合或数组的表达式。
  • item:遍历时的每⼀个对象。
  • open:循环开始时生成的字符串。
  • close:循环结束时生成的字符串。
  • separator:每次循环迭代之间生成的分隔符。
//根据文章id集合批量删除文章
Integer delByIdList(List<Integer> list);
<delete id="delByIdList">
    delete from articleinfo
    where id in
    <foreach collection="list" open="(" close=")" item="userid" separator=",">
        #{userid}
    </foreach>
</delete>
@Transactional
@Test
void delByIdList() {
    List<Integer> list = new ArrayList<>();
    list.add(1);
    list.add(2);
    list.add(3);
    articleMapper.delByIdList(list);
}

什么是 MyBatis ?如何使用 MyBatis ?

  在批量删除数据的时候可以使用这个。