<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Mybatis-plus,真香!

          共 19910字,需瀏覽 40分鐘

           ·

          2021-07-08 01:07

          前言

          mybatis相信都不陌生,目前互聯(lián)網(wǎng)公司大部分都使用mybatis作為持久層框架,無他,因為可以直接在xml文件中編寫SQL語句操作數(shù)據(jù)庫,靈活。但是我們在使用的時候,也會發(fā)現(xiàn)有很多增刪改查的SQL是每個表都會有的基本操作,如果每個表都寫一套增刪改查的SQL顯然是非常耗時耗力的。

          于是乎,就有了mybatis-plus這個框架。正如官網(wǎng)所說,mybatis-plus是為簡化開發(fā)而生

          mybatis-plus有以下特點:

          • 只做增強不做改變,引入它不會對現(xiàn)有工程產(chǎn)生影響,如絲般順滑。
          • 只需簡單配置,即可快速進行單表CRUD操作,節(jié)省大量時間。
          • 代碼生成,物理分頁,性能分析等功能一應(yīng)俱全。

          一、整合mybatis-plus

          這里用的是SpringBoot2.5.2做演示。首先導(dǎo)入依賴:

          <dependency>
              <groupId>org.mybatis.spring.boot</groupId>
              <artifactId>mybatis-spring-boot-starter</artifactId>
              <version>2.2.0</version>
          </dependency>
          <dependency>
              <groupId>mysql</groupId>
              <artifactId>mysql-connector-java</artifactId>
              <scope>runtime</scope>
          </dependency>
          <!-- 引入 mybatis-plus -->
          <dependency>
              <groupId>com.baomidou</groupId>
              <artifactId>mybatis-plus-boot-starter</artifactId>
              <version>3.3.0</version>
          </dependency>

          然后在application.properties文件配置數(shù)據(jù)庫信息:

          spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
          spring.datasource.url=jdbc:mysql://localhost:3306/user?createDatabaseIfNotExist=true
          spring.datasource.username=root
          spring.datasource.password=root123456
          #mapper.xml文件路徑地址
          mybatis-plus.mapper-locations=classpath:mapper/*Mapper.xml

          在啟動類加上掃描注解:

          @SpringBootApplication
          @MapperScan(basePackages = "com.yehongzhi.mydemo.mapper")
          public class MydemoApplication {
              public static void main(String[] args) {
                  SpringApplication.run(MydemoApplication.classargs);
              }
          }

          其實這樣就完成了,但是我們要建個表進行測試。

          CREATE TABLE `user` (
            `id` char(36NOT NULL DEFAULT '' COMMENT 'ID',
            `name` varchar(255DEFAULT '' COMMENT '姓名',
            `age` int(3DEFAULT NULL COMMENT '年齡',
            PRIMARY KEY (`id`)
          ENGINE=InnoDB DEFAULT CHARSET=utf8;
          -- 初始化4條數(shù)據(jù)
          INSERT INTO `user`.`user` (`id``name``age`VALUES ('1345fc0985b111eba0e488d7f66fdab8''觀辰''20');
          INSERT INTO `user`.`user` (`id``name``age`VALUES ('d47561e885b011eba0e488d7f66fdab8''姚大秋''30');
          INSERT INTO `user`.`user` (`id``name``age`VALUES ('ef2741fe87f011eba0e488d7f66fdab8''周星馳''60');
          INSERT INTO `user`.`user` (`id``name``age`VALUES ('ff784f6b85b011eba0e488d7f66fdab8''李嘉晟''33');

          建了表之后,再創(chuàng)建一個User實體類對應(yīng):

          //表名
          @TableName("user")
          public class User {
           //主鍵
              @TableId(type = IdType.UUID)
              private String id;
           //姓名
              private String name;
           //年齡
              private Integer age;
              //getter、setter方法
          }

          接著創(chuàng)建UserMapper接口類,,然后繼承BaseMapper:

          @Repository
          public interface UserMapper extends BaseMapper<User{
              
          }

          創(chuàng)建一個UserMapper.xml與UserMapper對應(yīng):

          <?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.yehongzhi.mydemo.mapper.UserMapper">

          </mapper>

          最后我們寫一個UserService接口,查詢user表:

          @Service
          public class UserServiceImpl implements UserService {
              @Resource
              private UserMapper userMapper;

              @Override
              public List<User> getList() {
                  return userMapper.selectList(null);
              }
          }

          啟動項目,測試是沒問題的:

          二、CRUD操作

          整合完了之后,按照mybatis-plus的官方說明,是有簡單的單表CRUD操作功能。

          這些單表的CRUD操作其實都放在BaseMapper里面了,所以當我們繼承了BaseMapper類之后,就會獲得mybatis-plus的增強特性,其中就包括單表的CRUD操作。

          1、insert操作

          BaseMapper直接提供一個insert()方法,傳一個實體類。

          @Service
          public class UserServiceImpl implements UserService {
              @Resource
              private UserMapper userMapper;
              
              @Override
              public int insertOne(User user) {
                  return userMapper.insert(user);
              }
          }

          接著在Controller調(diào)用,因為在User類上面貼了注解@TableId,所以會自動生成ID。

          @TableName("user")
          public class User {
              @TableId(type = IdType.UUID)
              private String id;
              //省略...
          }

          Controller層代碼:

          @RequestMapping("/insert")
          public String insertUser(@RequestParam(name = "name") String name,
                                   @RequestParam(name = "age") Integer age) 
          {
              User user = new User();
              user.setName(name);
              user.setAge(age);
              //在實體類使用了@TableId注解,ID會自動生成
              int i = userService.insertOne(user);
              return i == 1 ? "success" : "fail";
          }

          2、update操作

          BaseMapper直接提供一個updateById()方法,傳一個實體類。

          @Override
          public int updateOne(User user) {
              return userMapper.updateById(user);
          }

          Controller層代碼:

          @RequestMapping("/update")
          public String updateUser(@RequestParam(name = "id") String id,
                                   @RequestParam(name = "name",required = false) String name,
                                   @RequestParam(name = "age",required = false) Integer age) 
          {
              User user = new User();
              user.setId(id);
              user.setName(name);
              user.setAge(age);
              int i = userService.updateOne(user);
              return i == 1 ? "success" : "fail";
          }

          3、delete操作

          BaseMapper直接提供一個deleteById()方法,傳主鍵值。

          @Override
          public int deleteOne(String id) {
              return userMapper.deleteById(id);
          }

          Controller層代碼:

          @RequestMapping("/delete")
          public String deleteUser(@RequestParam(name = "id") String id) {
              int i = userService.deleteOne(id);
              return i == 1 ? "success" : "fail";
          }

          除此之外,還有批量刪除deleteBatchIds方法,傳主鍵值的集合:

          @Override
          public int deleteBatch(List<String> ids){
              return userMapper.deleteBatchIds(ids);
          }

          Controller層代碼:

          @RequestMapping("/deleteBatch")
          public String deleteBatchUser(@RequestParam(name = "ids") String ids) {
              List<String> list = Arrays.asList(ids.split(","));
              int i = userService.deleteBatch(list);
              return i == list.size() ? "success" : "fail";
          }

          三、條件構(gòu)造器(Wrapper)

          條件構(gòu)造器在Mybatis-plus各種方法中都有出現(xiàn),比如:

          Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

          List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

          int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);

          int delete(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

          Wrapper通俗點理解就是定義where語句后面的查詢條件,是Mybatis-Plus里功能比較強大的工具。Wrapper是一個抽象類,下面有很多子類,我們先看個類圖混個眼熟。

          常用的子類實現(xiàn)有四個,分別是:

          • QueryWrapper
          • UpdateWrapper
          • LambdaQueryWrapper
          • LambdaUpdateWrapper

          QueryWrapper

          主要用于生成where條件,舉個例子,我們用name查詢user表:

          public List<User> queryUserByName(String name) {
              //相當于:SELECT * FROM user WHERE name = ?
              QueryWrapper<User> queryWrapper = new QueryWrapper<>();
              //eq()表示相等
              queryWrapper.eq("name", name);
              return userMapper.selectList(queryWrapper);
          }

          我們看日志打印:

          ==>  Preparing: SELECT id,name,age FROM user WHERE name = ?
          ==> Parameters: 姚大秋(String)
          <==    Columns: id, name, age
          <==        Row: d47561e885b011eba0e488d7f66fdab8, 姚大秋, 30
          <==      Total: 1

          假如我們要like查詢,可以這樣寫:

          public List<User> queryUserLikeName(String name) {
              //相當于:SELECT * FROM user WHERE name like %#{name}%
              QueryWrapper<User> queryWrapper = new QueryWrapper<>();
              queryWrapper.like("name",name);
              return userMapper.selectList(queryWrapper);
          }

          假如要查詢年齡大于30歲,可以這樣:

          public List<User> queryUserGtByAge(int age) {
              //相當于:SELECT * FROM user WHERE age > ?
              QueryWrapper<User> queryWrapper = new QueryWrapper<>();
              queryWrapper.gt("age", age);
              //小于是lt()
              //大于等于是ge()
              //小于等于是le()
              //范圍的話,則使用between()
              return userMapper.selectList(queryWrapper);
          }

          如果要查詢某個字段不為空,可以這樣:

          public List<User> queryUserByNameNotNull() {
              //相當于:SELECT * FROM user WHERE name IS NOT NULL
              QueryWrapper<User> queryWrapper = new QueryWrapper<>();
              queryWrapper.isNotNull("name");
              //查詢某個字段為空,則使用isNull()
              return userMapper.selectList(queryWrapper);
          }

          如果使用IN查詢,可以這樣:

          public List<User> queryUserByIds(List<String> ids) {
              //相當于:SELECT * FROM user WHERE name IN ('id1','id2');
              QueryWrapper<User> queryWrapper = new QueryWrapper<>();
              queryWrapper.in("id", ids);
              //相反也提供了notIn()方法
              return userMapper.selectList(queryWrapper);
          }

          如果需要排序,可以這樣寫:

          public List<User> queryUserOrderByAge() {
              //相當于:SELECT * FROM user ORDER BY age ASC
              QueryWrapper<User> queryWrapper = new QueryWrapper<>();
              queryWrapper.orderByAsc("age");
              //相反的,如果降序則使用orderByDesc()方法
              return userMapper.selectList(queryWrapper);
          }

          如果需要子查詢,可以這樣寫:

          public List<User> queryUserInSql() {
              //相當于:SELECT * FROM user WHERE id IN (SELECT id FROM user WHERE age > 30)
              QueryWrapper<User> queryWrapper = new QueryWrapper<>();
              queryWrapper.inSql("id","select id from user where age > 30");
              return userMapper.selectList(queryWrapper);
          }

          大部分的方法都是源自AbstractWrapper抽象類,除此之外還有很多功能,這里就不一一介紹下去了,有興趣的可以到官網(wǎng)的條件構(gòu)造器慢慢探索。

          UpdateWrapper

          UpdateWrapper也是AbstractWrapper抽象類的子類實現(xiàn),所以上述的設(shè)置條件的方法都有,不同的是,UpdateWrapper會有set()和setSql()設(shè)置更新的值。舉個例子:

          public int updateUserNameById(String id, String name) {
              //相當于:UPDATE user SET name = ? where id = ?
              UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
              userUpdateWrapper.eq("id", id);
              //設(shè)置set關(guān)鍵字后面的語句,相當于set name = #{name}
              userUpdateWrapper.set("name", name);
              return userMapper.update(new User(), userUpdateWrapper);
          }

          setSql()就是設(shè)置SET關(guān)鍵字后面拼接的部分SQL語句,舉個例子:

          public int updateUserBySql(String id, String name) {
              //相當于:UPDATE user SET name = ? where id = ?
              UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
              userUpdateWrapper.setSql("name = '" + name + "'");
              userUpdateWrapper.eq("id", id);
              return userMapper.update(new User(), userUpdateWrapper);
          }

          setSql()就是純粹的SQL語句拼接,我們可以看到SET后面接的是name='大D',而不是占位符會有SQL注入的風(fēng)險。

          ==>  Preparing: UPDATE user SET name = '大D' WHERE id = ?
          ==> Parameters: d47561e885b011eba0e488d7f66fdab8(String)
          <==    Updates: 1

          LambdaQueryWrapper

          用LambdaQueryWrapper的好處在于消除硬編碼,比如QueryWrapper在查詢name=?時,需要這樣寫:

          QueryWrapper<User> queryWrapper = new QueryWrapper<>();
          //使用"name"字符串,就是硬編碼
          queryWrapper.eq("name", name);

          如果換成LambdaQueryWrapper就可以這樣寫:

          public List<User> lambdaQueryUserByName(String name) {
              //相當于:SELECT id,name,age FROM user WHERE name = ?
              LambdaQueryWrapper<User> lambdaQueryWrapper = new QueryWrapper<User>().lambda();
              lambdaQueryWrapper.eq(User::getName, name);
              return userMapper.selectList(lambdaQueryWrapper);
          }

          再比如使用模糊查詢,可以這樣寫:

          public List<User> lambdaQueryUserLikeName(String name) {
              LambdaQueryWrapper<User> lambdaQueryWrapper = new QueryWrapper<User>().lambda();
              lambdaQueryWrapper.like(User::getName, name);
              return userMapper.selectList(lambdaQueryWrapper);
          }

          LambdaUpdateWrapper

          跟上面差不多,LambdaUpdateWrapper也可以消除硬編碼:

          public int lambdaUpdateUserNameById(String id, String name) {
              //相當于:UPDATE user SET name=? WHERE id = ?
              LambdaUpdateWrapper<User> lambdaUpdateWrapper = new UpdateWrapper<User>().lambda();
              lambdaUpdateWrapper.set(User::getName, name);
              lambdaUpdateWrapper.eq(User::getId, id);
              return userMapper.update(new User(), lambdaUpdateWrapper);
          }

          分頁查詢

          Mybatis-plus提供了分頁插件支持分頁查詢,只需要幾個步驟即可實現(xiàn)。

          首先添加一個配置類:

          @Configuration
          public class MybatisPlusConfig {
              @Bean
              public PaginationInterceptor paginationInterceptor() {
                  return new PaginationInterceptor();
              }
          }

          第二步,在UserMapper類里定義分頁查詢方法:

          @Repository
          public interface UserMapper extends BaseMapper<User{
           //分頁查詢方法
              IPage<User> selectPageByName(Page<User> page, @Param("name") String name);
          }

          對應(yīng)的UserMapper.xml方法:

          <select id="selectPageByName" parameterType="java.lang.String" resultType="com.yehongzhi.mydemo.model.User">
              select * from `user` where name = #{name}
          </select>

          第三步,在userService里調(diào)用:

          public IPage<User> selectPageByName(long pageNo, long pageSize, String name) {
              Page<User> page = new Page<>();
              //設(shè)置當前頁碼
              page.setCurrent(pageNo);
              //設(shè)置每頁顯示數(shù)
              page.setSize(pageSize);
              return userMapper.selectPageByName(page, name);
          }

          最后寫個Controller接口測試:

          @RequestMapping("/queryPage/ByName")
          public IPage<User> selectPageByName(@RequestParam("pageNo") long pageNo,
                                              @RequestParam("pageSize") long pageSize,
                                              @RequestParam("name") String name) 
          {
              return userService.selectPageByName(pageNo, pageSize, name);
          }

          查看控制臺日志:

          ==>  Preparing: SELECT COUNT(1) FROM `user` WHERE name = ?
          ==> Parameters: 杜琪峰(String)
          <==    Columns: COUNT(1)
          <==        Row: 1
          ==>  Preparing: select * from `user` where name = ? LIMIT ?,?
          ==> Parameters: 杜琪峰(String), 0(Long), 10(Long)
          <==    Columns: id, name, age
          <==        Row: d47561e885b011eba0e488d7f66fdab8, 杜琪峰, 30
          <==      Total: 1

          分頁查詢成功!

          自定義主鍵生成器

          有時在實際開發(fā)中,可能會遇到,Mybatis-plus提供的主鍵生成策略并不能滿足,需要自定義主鍵ID生成策略,怎么設(shè)置呢?

          很簡單,根據(jù)官網(wǎng)的說明,我們先定義一個主鍵生成器:

          @Component
          public class SnowflakeKeyGenerator implements IdentifierGenerator {
           //自己實現(xiàn)的一個雪花ID生成工具類
              @Resource
              private SnowflakeIdWorker snowflakeIdWorker;

              @Override
              public Number nextId(Object entity) {
                  //使用雪花ID生成器,生成一個雪花ID
                  long nextId = snowflakeIdWorker.nextId();
                  System.out.println(String.format("使用自定義ID生成器,生成雪花ID:%s", nextId));
                  return nextId;
              }
          }

          然后我們在需要使用該自定義ID生成器的實體類上面加上注解屬性:

          @TableName("user")
          public class User {
           //屬性設(shè)置為:IdType.ASSIGN_ID
              @TableId(type = IdType.ASSIGN_ID)
              private String id;
           
              //省略...
          }

          接著測試一下,我們可以看到控制臺有打印日志:

          總結(jié)

          除了上面介紹的功能之外,Mybatis-plus還有很多功能,比如:代碼生成器、擴展等等。這里就不再一一介紹了,實際上我們掌握上面介紹的CRUD、條件構(gòu)造器、分頁查詢、自定義主鍵策略,基本上已經(jīng)足夠日常的開發(fā)。

          當然如果你覺得會用還不夠,還想要看懂框架的源碼實現(xiàn),那沒問題。下一篇文章,我就講講框架的源碼分析,敬請期待,

          非常感謝你的閱讀,希望這篇文章能給到你幫助和啟發(fā)。

          覺得有用就點個贊吧,你的點贊是我創(chuàng)作的最大動力~

          我是一個努力讓大家記住的程序員。我們下期再見!!!

          能力有限,如果有什么錯誤或者不當之處,請大家批評指正,一起學(xué)習(xí)交流!


          瀏覽 66
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲男人的天堂网 | 国产电影无码 | 人人妻人人操人人摸 | 日韩AⅤ | 18黄网站|