Skip to content

自定义SQL ​

如果MybatisPlus的BaseMapper中提供的方法无法满足我们的业务需求,我们也可以自定义SQL语句实现对数据库的操作,这里的SQL可以使用两种方式书写

  • 注解方式:适合比较简单的SQL书写
  • XML方式:适合比较复杂的SQL书写

注解方式(了解) ​

注解方式自定义SQL需要在Mapper接口中自定义方法,然后再使用Mybatis提供注解(@Insert、@Select、@Delete、@Update)声明SQL

创建UserMapper ​

java
package com.itheima.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.entity.User;
import org.apache.ibatis.annotations.*;

import java.util.List;

@Mapper
public interface UserMapper extends BaseMapper<User> {

    @Insert("insert into user values (null,#{username},#{password},#{name},#{age})")
    Integer addUser(User user);

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

    @Delete("delete from user where id = #{id}")
    Integer deleteUser(Integer id);

    @Select("select * from user")
    List<User> findAll();

    @Select("select * from user where username = #{username} and password = #{password}")
    User findByUsernameAndPassword(@Param("username") String username, @Param("password") String password);
}

代码测试 ​

java
package com.itheima.mapper;

import com.itheima.entity.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class UserMapperTest6 {

    @Autowired
    private UserMapper userMapper;

    @Test
    void addUser() {
        userMapper.addUser(new User(null, "yangguo", "123456", "杨过", 20));
    }

    @Test
    void updateUser() {
        User user = userMapper.selectById(4);
        user.setPassword("123456");
        user.setAge(30);
        userMapper.updateUser(user);
    }

    @Test
    void deleteUser() {
        userMapper.deleteUser(4);
    }

    @Test
    void findAll() {
        List<User> userList = userMapper.findAll();
        userList.forEach(user -> System.out.println(user));
    }

    @Test
    void findByUsernameAndPassword() {
        User user = userMapper.findByUsernameAndPassword("yangguo", "123456");
        System.out.println(user);
    }
}

XML方式(重要) ​

如果要定义的SQL比较复杂,使用XML方式更加合适一些。

创建UserMapper ​

自定义SQL实现用户表的CRUD操作。上面的注解方式中的@Insert这样的代码就可以不用写在Mapper中了。

这里以自定义的多表联合查询结合Mybatisplus本身提供的分页功能进行代码示例:

IPage<UserVo>表示Mybatisplus默认提供的分页功能,我们只需要查询分页中的列表数据这块功能即可。

java
package com.cghbh.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cghbh.dto.UserPageDto;
import com.cghbh.entity.User;
import com.cghbh.vo.UserVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

@Mapper
public interface UserMapper extends BaseMapper<User> {
    // 第一个参数是跟userMappper.selectPage(new Page<>())一样的功能,第二个参数则是分页需要的参数
    // @Param不写的情况下,传递给对应UserMapper.xml文件的变量名称就是dto1!!!
    // 如果写了@Param的话,则传入到UserMapper.xml的变量名称就是dto2!!!
    IPage<UserVo> getUsersByPage(IPage<UserVo> page, @Param("dto2") UserPageDto dto1);
}

创建UserMapper.xml ​

在resources目录下创建一个mapper目录,然后将资料中提供的UserMapper.xml文件复制到此目录

(官方推荐在和Mapper接口同层级的文件夹中创建xml文件)

请注意

在MybatisPlus中使用XML映射文件方式开发,需要符合一定的规范:

  1. XML映射文件中namespace的值必须跟Mapper接口全限定名一致
  2. XML映射文件中sql语句的id必须与Mapper接口中的方法名一致
  3. XML映射文件中sql语句的idresultType必须跟接口中的方法返回值中实体类类型一致
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!-- 引入mybatis的xml方式编写sql的约束 -->
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- mapper跟标签的namespace属性的值必须是接口的完全限定路由 -->
<mapper namespace="com.cghbh.mapper.UserMapper">
    特别提示一下:resultType决定了返回的字段,不在这个UserVo里面的字段,即便你在SQL中查询到了也会被过滤掉
    <select id="getUsersByPage" resultType="com.cghbh.vo.UserVo">
        SELECT
        u.*,
        d.name AS dept_name,
        r.name AS role_name,
        r.label AS role_label
        FROM `user` u
        LEFT JOIN `dept` d ON u.dept_id = d.id
        LEFT JOIN `role` r ON u.role_id = r.id
        <where>
            <if test="dto.status != null">
                u.status = #{dto.status}
            </if>
            <if test="dto.deptId != null">
                u.dept_id = #{dto.deptId}
            </if>
            <if test="dto.name != null and dto.name != ''">
                u.name LIKE CONCAT('%',#{dto.name},'%')
            </if>
            <if test="dto.phone != null and dto.phone != ''">
                u.phone LIKE CONCAT('%',#{dto.phone},'%')
            </if>
        </where>
        ORDER BY u.update_time DESC
    </select>
</mapper>

!!!

在xml文件中写的SQL查询语句禁止加分号,因为在分页处理的时候Mybatisplus会帮我们拦截SQL增加分页的语句,加了分号运行代码会报错。

如何快速创建MyBatisMapper ​

打开File → Settings → Editor → File and Code Templates,

填写模板的名称、类型和填充的内容:

模板内容如下:

xml
<?xml version="1.0" encoding="UTF-8" ?>
<!-- 引入mybatis的xml方式编写sql的约束 -->
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="">
    <!-- namespace表示对应的mapper包文件地址,例如com.cghbh.mapper.UserMapper,这个Mapper就是你之前在mapper文件夹下创建的-->
</mapper>

然后创建文件的时候,鼠标右键选择如下即可使用:

修改配置文件 ​

在SpringBoot的配置文件application.yaml中配置xml文件所在的位置。

yml
# 配置MyBatis-Plus
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    
  mapper-locations: classpath:mapper/*.xml # 注意我们刚才把mapper接口对应的xml放到了mapper目录中 , 所以这里需要配置一下

代码测试 ​

java
/**
 * 测试查询年龄姓张并且年龄大于18的用户方法
 */
@Test
public void testSelectByNameAndAge() {
    List<User> list = userMapper.selectByNameAndAge("张",18);
    System.out.println(list);
}