我的编程空间,编程开发者的网络收藏夹
学习永远不晚

SpringBoot使用Mybatis注解实现分页动态sql开发教程

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

SpringBoot使用Mybatis注解实现分页动态sql开发教程

一、环境配置

1.引入mybatis依赖

    compile(
            //SpringMVC
            'org.springframework.boot:spring-boot-starter-web',
            "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.3",
            //Mybatis依赖及分页插件
            "org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.1",
            "com.github.pagehelper:pagehelper:4.1.0",
            'mysql:mysql-connector-java'
    )

2.数据源配置

spring:
  datasource:
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql:///mybatis?characterEncoding=utf8&useSSL=false
    //根据resources目录下的schema.sql自动建表,可省略
    schema: classpath:schema.sql
    //根据resources目录下的data.sql自动插入假数据,可省略
    data: classpath:data.sql

3.分页插件配置

@Configuration
public class CommonConfiguration {

    
    @Bean
    public PageHelper pageHelper() {
        PageHelper pageHelper = new PageHelper();
        Properties p = new Properties();
        p.setProperty("offsetAsPageNum", "true");
        p.setProperty("rowBoundsWithCount", "true");
        p.setProperty("reasonable", "true");
        pageHelper.setProperties(p);
        return pageHelper;
    }

}

4.配置SpringBoot扫描Mybatis仓储,有两种配置方式

在启动类上加入@MapperScan,填写Mapper接口所在的包名,SpringBoot就会自动将该包中的Mapper接口进行加载

@MapperScan(basePackages = "com.kingboy.repository")
@SpringBootApplication
public class KingboySpringbootDataApplication {
    public static void main(String[] args) {
        SpringApplication.run(KingboySpringbootDataApplication.class, args);
    }
}

在Mapper接口上加上@Mapper注解,SpringBoot就会自动夹在该Mapper接口

@Mapper
public interface UserMapper {
        @Insert("INSERT INTO `user` VALUES (#{id}, #{nickName}, #{phoneNumber}, #{sex}, #{age}, #{birthday}, #{status})")
        @Options(useGeneratedKeys = true, keyColumn = "id", keyProperty = "id")
        void saveUser(User user);
        
}

这两种方式都可以,根据项目结构进行选择即可,也可以结合私用。

5.配置驼峰属性自动映射

mybatis:
  configuration:
    map-underscore-to-camel-case: true

例如实体中属性为phoneNumber,数据库属性为phone_number,Mybatis默认是不能自动转换的,通常我们要自定义以下结果集映射

@Result(column = "phone_number", property = "phoneNumber")

然而这样很不方便,当我们加上以上配置之后,Mybatis在映射结果时,会自动转换,去掉下划线,变n为大写N。

6.设置mybatis日志打印,在配置文件中加入如下配置

logging: level: #Mapper所在的包 com.kingboy.repository: debug

开启日志有三种方式,可以参考我的另一篇博客

logback中显示mybatis查询日志文件并写入的方法

二、Mybatis注解

Mybatis提供了四个注解,先简单了解一下,后面的完整示例中演示了相应的实例

@Insert(“sql”) 增
@Delete(“sql”) 删
@Update(“sql”) 改
@Select(“sql”) 查

三、方法参数读取

1.普通参数读取

在方法参数前使用@Param注解对参数进行标记,在sql中使用#{属性名}来读取属性。

示例

    //删除用户,根据用户ID和名称删除用户
    @Delete("DELETE FROM `user` WHERE id = #{id} AND nick_name = #{nickName}")
    void delete(@Param(value = "id") Long id, @Param(value = "nickName") String nickName);

2.对象参数读取

直接在sql中使用#{属性名}来读取属性

示例

    @Insert("INSERT INTO `user` VALUES (#{id}, #{nickName}, #{phoneNumber}, #{sex}, #{age}, #{birthday}, #{status})")
    @Options(useGeneratedKeys = true, keyColumn = "id", keyProperty = "id")
    void saveUser(User user);

这里补充一点,@Options注解和@Insert注解结合使用,可以将保存后的主键设置到user实体中。也就是说保存前user的id是没值的,
保存后mybatis会自动将数据库中的主键设置到user的id属性上,keyColumn = "id"为数据库主键名,keyProperty = "id"为实体的主键属性名。

四、分页插件的使用

分页插件单独拿出来说,是因为项目实战中发现很多同学都使用错了,所以着重强调一下。

分页插件的核心类是PageHelper,这个类提供了很多的静态方法,其中我们最常用的是PageHelper.startPage(int page, int size)这个方法,返回com.github.pagehelper.Page对象,
该对象包含了包含了查询结果result, 当前页pageNum,每页大小pageSize, 总条数total等信息,可以获取这些信息返回给前端。需要注意的是,PageHelper的页数是从1开始的。

我们来看一段实际的代码操作,这里就不写service层了。

//controller
RestController
@RequestMapping(value = "/user")
public class UserController {
    @Resource
    UserRepository userRepository;
    @GetMapping
    @Transactional(readOnly = true)
    public Page get(@RequestParam Integer page, @RequestParam Integer size) {
        //分页并查询
        Page<User> pageInfo = PageHelper.startPage(page, size);
        List<User> users = userRepository.listUser();
        //获取分页信息演示, 实际项目中一般会封装为自己的返回体。
        int pageNum = pageInfo.getPageNum();
        int pageSize = pageInfo.getPageSize();
        long total = pageInfo.getTotal();
        List<User> result = pageInfo.getResult();//和上面的users结果相同
        return pageInfo;
    }
}
//repository
@Mapper
public interface UserRepository {
    //分页查询用户
    @Select("SELECT * FROM `user`")
    List<User> listUser();
}

五、动态标签

熟悉Mybatis的同学一定对Mybatis的动态SQL很了解,解决了我们编写动态SQL的很多痛点。接下来介绍以下Mybatis常用的动态sql的注解写法,其实和xml是几乎完全一致的。

首先在注解中使用动态sql时,我们需要为sql加上<script></script>标签,这时候mybatis才会解析里面的标签。

1.<if test="条件判断">sql</if>

用来对参数进行判断,若为真,则包裹的sql语句生效。条件中可以使用and作连接

    //分页查询用户,如果sex有值,则查询相应sex的所有用户,sex没值则查询所有
    @Select("<script>SELECT * FROM `user` <if test='sex != null'>where sex = #{sex}</if><script>")
    List<User> listUser(Sex sex);//sex是一个枚举类型,值为BOY,GIRL

2.<foreach item = 'item' index = 'index' collection='list' separator=',', open='(', close=')'>sql</foreach>

循环参数中的集合参数进行操作,和java中的for循环比较类似,不过多了open/close/separator三个参数。

open是在操作之前加上一个"("

close是在操作之后加上一个")"

separator是每个元素间的分割符

需要注意的是,collection的值只能是list或者collection

示例

    @Select("<script>"
            + "SELECT * FROM `user` WHERE id in "
            + "<foreach item='item' collection='list' open='(' close=')' separator=','>"
            + "#{item}"
            + "</foreach>"
            + "</script>")
    List<User> listUserByIds(List<Long> ids);

例如传入的ids为[2,4,6]生成的sql如下:

SELECT * FROM `user` WHERE id in ( 2 , 4, 6 ) 

3.<set></set>

更新实体属性要用到的标签,一般我们使用动态sql更新用户信息 update user set username = ?, age = ?,时要处理最后一个逗号的问题,那么使用set标签就可以自动帮我们处理这个逗号。

示例

    //使用set标签进行动态set,要注意条件判断:没被删除的用户才可以更新数据
    @Update("<script>"
            + "UPDATE `user` "
            + "<set>"
            + "<if test='nickName != null'>nick_name = #{nickName}, </if>"
            + "<if test='age != null'>age = #{age}, </if>"
            + "<if test='phoneNumber != null'>phone_number = #{phoneNumber}, </if>"
            + "<if test='birthday != null'>birthday = #{birthday}, </if>"
            + "<if test='status != null'>status = #{status}, </if>"
            + "<if test='sex != null'>sex = #{sex}, </if>"
            + "</set>"
            + "WHERE id = #{id} AND status != 'DELETE';"
            + "</script>")
    void updateUser(User user);

4.<where></where>

和更新数据时遇到的问题一样,我们在动态查询时也要动态拼接查询条件,最前边一个查询条件是没有AND或者OR的,以前通常使用1 = 1避开这个问题,那么现在可以使用标签自动帮我们处理。

示例

    
    @Select("<script>"
            + "SELECT * FROM `user`"
            + "<where>"
            + "<bind name='nickName' value=\"'%' + nickName + '%'\" />"
            + "<if test='nickName != null'>AND nick_name like #{nickName}</if>"
            + "<if test='phoneNumber !=null'>AND phone_number = #{phoneNumber}</if>"
            + "<if test='sex !=null'>AND sex = #{sex}</if>"
            + "<if test='age !=null'>AND age = #{age}</if>"
            + "<if test='fromBirthday !=null'>AND birthday &gt; #{fromBirthday}</if>"
            + "<if test='toBirthday !=null'>AND birthday &lt; #{toBirthday}</if>"
            + "<if test='status !=null'>AND status = #{status}</if>"
            + "</where>"
            + "</script>")
    List<User> queryByCondition(UserQueryDTO userQueryDTO);

5.<bind name='新属性' value="'%' + 原属性 + '%'" />

在模糊查询时,我们通常使用 where name like %金% 这样的方式来进行查询(当然这样效率很低,不推荐),但是在mybatis里面我们直接写 where name like %#{name}% 是不行的,
会生成 where name like %'金'% 这样的sql, 很明显是不行的。有两种方式可以处理。

1)、传入的属性上加上%号,例如传入的name就为  %金% ,这样可以解决,但是不方便。

2)、使用bind标签,我们可以在sql中加入一行赋值操作

<bind name='newName' value="'%' + name + '%'" />

示例:参照上一个示例。

6.<choose><when test='条件1'></when><when test='条件2'></when><otherwise></otherwise></choose>

这个java中的switch比较像,如果条件1成立,就执行条件1中的语句,剩下的不执行。条件1不成立就判断条件2,如果条件2还不成立就执行otherwise中的sql。

示例

    
    @Select("<script>"
            + "SELECT * FROM `user`"
            + "<where>"
            + "<choose>"
            + "<when test='age != null'>AND age = #{age}</when>"
            + "<when test='sex != null'>AND sex = #{sex}</when>"
            + "<otherwise>AND status = 'UNLOCK'</otherwise>"
            + "</choose>"
            + "</where>"
            + "</script>")
    List<User> getByOrderCondition(@Param("age") Integer age, @Param("sex") Sex sex);

六、完整示例

其中的用户实体等没有贴出来,太乱了,完整示例代码可以参考文章开头的github项目。

UserController

package com.kingboy.controller.user;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.kingboy.common.utils.page.PageParam;
import com.kingboy.common.utils.page.PageResult;
import com.kingboy.common.utils.page.PageResultFactory;
import com.kingboy.common.utils.result.ApiResult;
import com.kingboy.domain.user.Sex;
import com.kingboy.domain.user.Status;
import com.kingboy.domain.user.User;
import com.kingboy.dto.user.UserQueryDTO;
import com.kingboy.repository.user.UserRepository;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;

@RestController
@RequestMapping(value = "/user")
public class UserController {
    @Resource
    UserRepository userRepository;
    @Resource
    PageResultFactory pageResultFactory;
    
    @PostMapping
    public ApiResult save(@RequestBody User user) {
        userRepository.saveUser(user);
        return ApiResult.success(user);
    }
    
    @PostMapping(value = "/list")
    public ApiResult save(@RequestBody List<User> users) {
        userRepository.saveUserList(users);
        return ApiResult.success(users);
    }
    
    @PutMapping
    public ApiResult update(@RequestBody User user) {
        userRepository.updateUser(user);
        return ApiResult.success("success");
    }
    
    @DeleteMapping("/{id}")
    public ApiResult remove(@PathVariable Long id) {
        //软删除
        userRepository.remove(id, Status.DELETE);
        //硬删除
        //userRepository.delete(id);
        return ApiResult.success("success");
    }
    
    @GetMapping("/{id}")
    public ApiResult get(@PathVariable Long id) {
        User user = userRepository.get(id);
        return ApiResult.success(user);
    }
    
    @GetMapping
    @Transactional(readOnly = true)
    public ApiResult get(@ModelAttribute PageParam pageParam) {
        //分页并查询
        Page<User> pageInfo = PageHelper.startPage(pageParam.getPage(), pageParam.getSize());
        List<User> users = userRepository.listUser();
        //实际使用时,最后一个参数传入要转换的类型DTO
        PageResult<User> result = pageResultFactory.createAndConvert(pageParam.getMybatisPage(), pageInfo.getTotal(), users, User.class);
        return ApiResult.success(result);
    }
    
    @PostMapping("/ids")
    public ApiResult getUserByIds(@RequestBody List<Long> ids) {
        List<User> users = userRepository.listUserByIds(ids);
        return ApiResult.success(users);
    }
    
    @PostMapping("/query")
    public ApiResult queryUser(@RequestBody UserQueryDTO userQueryDTO) {
        List<User> users = userRepository.queryByCondition(userQueryDTO);
        return ApiResult.success(users);
    }
    
    @GetMapping("/query")
    public ApiResult findUserByOrderCondition(@RequestParam(required = false) Integer age, @RequestParam(required = false) Sex sex) {
        List<User> users = userRepository.getByOrderCondition(age, sex);
        return ApiResult.success(users);
    }
}

UserRepository

package com.kingboy.repository.user;
import com.kingboy.domain.user.Sex;
import com.kingboy.domain.user.Status;
import com.kingboy.domain.user.User;
import com.kingboy.dto.user.UserQueryDTO;
import org.apache.ibatis.annotations.*;
import java.util.List;

public interface UserRepository {
    
    @Insert("INSERT INTO `user` VALUES (#{id}, #{nickName}, #{phoneNumber}, #{sex}, #{age}, #{birthday}, #{status})")
    @Options(useGeneratedKeys = true, keyColumn = "id", keyProperty = "id")
    void saveUser(User user);
    
    @Insert("<script>" +
            "INSERT INTO `user` VALUES " +
            "<foreach item = 'item' index = 'index' collection='list' separator=','>" +
            "(#{item.id}, #{item.nickName}, #{item.phoneNumber}, #{item.sex}, #{item.age}, #{item.birthday}, #{item.status})" +
            "</foreach>" +
            "</script>")
    @Options(useGeneratedKeys = true)
    void saveUserList(List<User> users);
    //使用set标签进行动态set,要注意条件判断:没被删除的用户才可以更新数据
    @Update("<script>"
            + "UPDATE `user` "
            + "<set>"
            + "<if test='nickName != null'>nick_name = #{nickName}, </if>"
            + "<if test='age != null'>age = #{age}, </if>"
            + "<if test='phoneNumber != null'>phone_number = #{phoneNumber}, </if>"
            + "<if test='birthday != null'>birthday = #{birthday}, </if>"
            + "<if test='status != null'>status = #{status}, </if>"
            + "<if test='sex != null'>sex = #{sex}, </if>"
            + "</set>"
            + "WHERE id = #{id} AND status != 'DELETE';"
            + "</script>")
    void updateUser(User user);
    //删除用户,软删除
    @Update("UPDATE `user` SET status = #{status} WHERE id = #{id}")
    void remove(@Param(value = "id") Long id, @Param(value = "status") Status status);
    //删除用户,硬删除
    @Delete("DELETE FROM `user` WHERE id = #{id}")
    void delete(@Param(value = "id") Long id);
    
    @Select("SELECT * FROM `user` WHERE id = #{id}")
    @Results({
            @Result(column = "nick_name", property = "nickName"),
            @Result(column = "phone_number", property = "phoneNumber")
    })
    User get(Long id);
    //分页查询用户
    @Select("SELECT * FROM `user`")
    List<User> listUser();
    
    @Select("<script>"
            + "SELECT * FROM `user` WHERE id in "
            + "<foreach item='item' collection='list' open='(' close=')' separator=','>"
            + "#{item}"
            + "</foreach>"
            + "</script>")
    List<User> listUserByIds(List<Long> ids);
    
    @Select("<script>"
            + "SELECT * FROM `user`"
            + "<where>"
            + "<bind name='nickName' value=\"'%' + nickName + '%'\" />"
            + "<if test='nickName != null'>AND nick_name like #{nickName}</if>"
            + "<if test='phoneNumber !=null'>AND phone_number = #{phoneNumber}</if>"
            + "<if test='sex !=null'>AND sex = #{sex}</if>"
            + "<if test='age !=null'>AND age = #{age}</if>"
            + "<if test='fromBirthday !=null'>AND birthday &gt; #{fromBirthday}</if>"
            + "<if test='toBirthday !=null'>AND birthday &lt; #{toBirthday}</if>"
            + "<if test='status !=null'>AND status = #{status}</if>"
            + "</where>"
            + "</script>")
    List<User> queryByCondition(UserQueryDTO userQueryDTO);
    
    @Select("<script>"
            + "SELECT * FROM `user`"
            + "<where>"
            + "<choose>"
            + "<when test='age != null'>AND age = #{age}</when>"
            + "<when test='sex != null'>AND sex = #{sex}</when>"
            + "<otherwise>AND status = 'UNLOCK'</otherwise>"
            + "</choose>"
            + "</where>"
            + "</script>")
    List<User> getByOrderCondition(@Param("age") Integer age, @Param("sex") Sex sex);
}

以上就是SpringBoot使用Mybatis注解实现分页动态sql开发教程的详细内容,更多关于SpringBoot Mybatis注解分页动态sql教程的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

SpringBoot使用Mybatis注解实现分页动态sql开发教程

下载Word文档到电脑,方便收藏和打印~

下载Word文档

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录