Mybatis-plus快速入門與詳解

一熟史、MyBatis-Plus簡介

1氧映、簡介

MyBatis-Plus(簡稱 MP)是一個(gè) MyBatis的增強(qiáng)工具钧萍,在 MyBatis 的基礎(chǔ)上只做增強(qiáng)不做改變褐缠,為 簡化開發(fā)、提高效率而生风瘦。

我們的愿景是成為 MyBatis 最好的搭檔队魏,就像魂斗羅中的 1P、2P万搔,基友搭配胡桨,效率翻倍。

image-20220518205901937.png
2瞬雹、特性
  • 無侵入:只做增強(qiáng)不做改變昧谊,引入它不會(huì)對(duì)現(xiàn)有工程產(chǎn)生影響,如絲般順滑
  • 損耗小:啟動(dòng)即會(huì)自動(dòng)注入基本 CURD酗捌,性能基本無損耗揽浙,直接面向?qū)ο蟛僮?/li>
  • 強(qiáng)大的 CRUD 操作:內(nèi)置通用 Mapper、通用 Service意敛,僅僅通過少量配置即可實(shí)現(xiàn)單表大部分 CRUD 操作馅巷,更有強(qiáng)大的條件構(gòu)造器,滿足各類使用需求
  • 支持 Lambda 形式調(diào)用:通過 Lambda 表達(dá)式草姻,方便的編寫各類查詢條件钓猬,無需再擔(dān)心字段寫錯(cuò)
  • 支持主鍵自動(dòng)生成:支持多達(dá) 4 種主鍵策略(內(nèi)含分布式唯一 ID 生成器 - Sequence),可自由配置撩独,完美解決主鍵問題
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式調(diào)用敞曹,實(shí)體類只需繼承 Model 類即可進(jìn)行強(qiáng)大的 CRUD 操作
  • 支持自定義全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 內(nèi)置代碼生成器:采用代碼或者 Maven 插件可快速生成 Mapper 、 Model 综膀、 Service 澳迫、 Controller 層代碼,支持模板引擎剧劝,更有超多自定義配置等您來使用
  • 內(nèi)置分頁插件:基于 MyBatis 物理分頁橄登,開發(fā)者無需關(guān)心具體操作,配置好插件之后讥此,寫分頁等同于普通 List 查詢
  • 分頁插件支持多種數(shù)據(jù)庫:支持 MySQL拢锹、MariaDB、Oracle萄喳、DB2卒稳、H2、HSQL他巨、SQLite充坑、Postgre减江、SQLServer 等多種數(shù)據(jù)庫
  • 內(nèi)置性能分析插件:可輸出 SQL 語句以及其執(zhí)行時(shí)間,建議開發(fā)測試時(shí)啟用該功能捻爷,能快速揪出慢查詢
  • 內(nèi)置全局?jǐn)r截插件:提供全表 delete 您市、 update 操作智能分析阻斷,也可自定義攔截規(guī)則役衡,預(yù)防誤操作
3、支持?jǐn)?shù)據(jù)庫

任何能使用 MyBatis 進(jìn)行 CRUD, 并且支持標(biāo)準(zhǔn) SQL 的數(shù)據(jù)庫薪棒,具體支持情況如下手蝎,如果不在下列表查看分頁部分教程 PR 您的支持。

  • MySQL俐芯,Oracle棵介,DB2,H2吧史,HSQL邮辽,SQLite,PostgreSQL贸营,SQLServer吨述,Phoenix,Gauss 钞脂,ClickHouse揣云,Sybase,OceanBase冰啃,F(xiàn)irebird邓夕,Cubrid,Goldilocks阎毅,csiidb
  • 達(dá)夢(mèng)數(shù)據(jù)庫焚刚,虛谷數(shù)據(jù)庫,人大金倉數(shù)據(jù)庫扇调,南大通用(華庫)數(shù)據(jù)庫矿咕,南大通用數(shù)據(jù)庫,神通數(shù)據(jù)庫狼钮,瀚高數(shù)據(jù)庫
4痴腌、框架結(jié)構(gòu)
image-20220518210026312.png
5、代碼及文檔地址

官方地址: http://mp.baomidou.com

代碼發(fā)布地址:

文檔發(fā)布地址: https://baomidou.com/pages/24112f

二燃领、入門案例

1士聪、建表

我們使用Mysql8版本

創(chuàng)建表

CREATE DATABASE `mybatis_plus` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;
use `mybatis_plus`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL COMMENT '主鍵ID',
`name` varchar(30) DEFAULT NULL COMMENT '姓名',
`age` int(11) DEFAULT NULL COMMENT '年齡',
`email` varchar(50) DEFAULT NULL COMMENT '郵箱',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

添加數(shù)據(jù)

INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');
2惶岭、導(dǎo)入依賴
<dependency>
     <groupId>com.baomidou</groupId>
     <artifactId>mybatis-plus-boot-starter</artifactId>
     <version>3.5.1</version>
</dependency>
<dependency>
     <groupId>org.projectlombok</groupId>
     <artifactId>lombok</artifactId>
     <optional>true</optional>
</dependency>
<dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
     <scope>runtime</scope>
</dependency>

其中谢肾,lombok只是為了簡化我們實(shí)體類的代碼

IDEA 2020.3及以上版本已經(jīng)內(nèi)置Lombok plugin了,無需安裝插件

3蹦骑、application.yml
spring:
  # 配置數(shù)據(jù)源信息
  datasource:
  # 配置數(shù)據(jù)源類型
    type: com.zaxxer.hikari.HikariDataSource
    # 配置連接數(shù)據(jù)庫信息
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3307/mybatis_plus?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false
    username: root
    password: root

#配置mybatis日志
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  # 配置MyBatis-Plus操作表的默認(rèn)前綴
  global-config:
    db-config:
      table-prefix: t_
      # 配置MyBatis-Plus的主鍵策略
#      id-type: auto
  # 配置類型別名所對(duì)應(yīng)的包
#  type-aliases-package: com.zl.po
4、啟動(dòng)類

在Spring Boot啟動(dòng)類中添加@MapperScan注解区岗,掃描mapper包

package com.zl;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


/**
 * @date 2022-05-15
 * @author ZL
 */
@SpringBootApplication
@MapperScan("com.zl.mapper")
public class MybatisPlusDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(MybatisPlusDemoApplication.class, args);
    }

}
5略板、實(shí)體類
package com.zl.po;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author zl
 * @time 2022/5/15
 */
@Data
@TableName("t_user")
public class User {

    //@TableId("uid")
    private Long id;

    //@TableField("user_name")
    private String name;

    private Integer age;

    private String email;

    /**
     * 邏輯刪除
     */
    //@TableLogic
   // private Integer isDeleted;
}
6、通用Mapper接口
package com.zl.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zl.po.User;
import org.springframework.stereotype.Repository;

/**
 * @author zl
 * @time 2022/5/15
 */
@Repository
public interface UserMapper extends BaseMapper<User> {

}
7慈缔、測試
package com.zl;

import com.zl.mapper.UserMapper;
import com.zl.po.User;
import com.zl.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.*;

/**
 * 通用Mapper測試
 */
@SpringBootTest
class MybatisPlusTest {

    @Autowired
    private UserMapper userMapper;

    /**
     * 查詢所有
     * SELECT id,name,age,email FROM user
     */
    @Test
    void testSelectList() {
        List<User> users = userMapper.selectList(null);
        users.forEach(System.out::println);
    }
}

三叮称、進(jìn)階

1、不同數(shù)據(jù)庫yml配置

Mysql

spring:
  # 配置數(shù)據(jù)源信息
  datasource:
  # 配置數(shù)據(jù)源類型
    type: com.zaxxer.hikari.HikariDataSource
    # 配置連接數(shù)據(jù)庫信息
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3307/mybatis_plus?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false
    username: root
    password: root

#配置mybatis日志
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  # 配置MyBatis-Plus操作表的默認(rèn)前綴
  global-config:
    db-config:
      table-prefix: t_
      # 配置MyBatis-Plus的主鍵策略
#      id-type: auto
  # 配置類型別名所對(duì)應(yīng)的包
#  type-aliases-package: com.zl.po

其中mysql8的url為:

jdbc:mysql://localhost:3307/mybatis_plus?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false

mysql5的url為:

jdbc:mysql://localhost:3307/mybatis_plus?characterEncoding=utf-8&useSSL=false

Sqlserver

# DataSource Config
spring:
  datasource:
    username: sa
    password: root
    url: jdbc:sqlserver://localhost:1433;DatabaseName=test
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver

Oracle

spring:
  datasource:
    driverClassName: oracle.jdbc.OracleDriver
    username: root
    password: root
    url: jdbc:oracle:thin:@//localhost:1521/test
2藐鹤、通用Service接口

Uservice

package com.zl.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.zl.po.User;

/**
 * @author zl
 * @time 2022/5/15
 */
public interface UserService extends IService<User> {
}

UserServiceImpl

package com.zl.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zl.mapper.UserMapper;
import com.zl.po.User;
import com.zl.service.UserService;
import org.springframework.stereotype.Service;

/**
 * @author zl
 * @time 2022/5/15
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
3瓤檐、通用Mapper和通用Service常規(guī)用法
package com.zl;

import com.zl.mapper.UserMapper;
import com.zl.po.User;
import com.zl.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.*;

/**
 * 通用Mapper測試
 */
@SpringBootTest
class MybatisPlusTest {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserService userService;

    
    /**
     * 查詢所有
     * SELECT id,name,age,email FROM user
     */
    @Test
    void testSelectList() {
        List<User> users = userMapper.selectList(null);
        users.forEach(System.out::println);
    }

    /**
     * 插入
     * INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? )
     */
    @Test
    void testInsert(){
        User user = new User();
        user.setName("張三");
        user.setAge(23);
        user.setEmail("zhangsan@163.com");
        int result = userMapper.insert(user);
        System.out.println("受影響的行數(shù):"+result);
        System.out.println("新建的ID:"+user.getId());
    }

    /**
     * 根據(jù)ID刪除
     * DELETE FROM user WHERE id=?
     */
    @Test
    void testDeleteById(){
        int result = userMapper.deleteById(1525835539440345090L);
        System.out.println("受影響的行數(shù):"+result);
    }


    /**
     * 根據(jù)ID批量刪除
     * DELETE FROM user WHERE id IN ( ? , ? )
     */
    @Test
    void testDeleteBatchIds(){
        int result = userMapper.deleteBatchIds(Arrays.asList(1L, 2L));
        System.out.println("受影響的行數(shù):"+result);
    }


    /**
     * 根據(jù)Map刪除
     * DELETE FROM user WHERE name = ? AND age = ?
     */
    @Test
    void testDeleteByMap(){
        Map<String,Object> map = new HashMap<>();
        map.put("age",21);
        map.put("name","Sandy");
        int result = userMapper.deleteByMap(map);
        System.out.println("受影響的行數(shù):"+result);
    }


    /**
     * 根據(jù)ID更新
     * UPDATE user SET name=?, age=? WHERE id=?
     */
    @Test
    void testUpdateById(){
        User user = new User();
        user.setId(5L);
        user.setName("admin");
        user.setAge(33);

        int result = userMapper.updateById(user);
        System.out.println("受影響的行數(shù):"+result);
    }


    /**
     * 根據(jù)ID查詢
     * SELECT id,name,age,email FROM user WHERE id=?
     */
    @Test
    void testSelectById(){
        User user = userMapper.selectById(5L);
        System.out.println(user);
    }


    /**
     * 根據(jù)ID批量查詢
     * SELECT id,name,age,email FROM user WHERE id IN ( ? , ? )
     */
    @Test
    void testSelectByBatchIds(){
        List<User> users = userMapper.selectBatchIds(Arrays.asList(3L, 5L));
        users.forEach(System.out::println);
    }


    /**
     * 根據(jù)Map查詢
     * SELECT id,name,age,email FROM user WHERE name = ? AND age = ?
     */
    @Test
    void testSelectByMap(){
        Map<String,Object> map = new HashMap<>();
        map.put("name","admin");
        map.put("age",33);
        List<User> users = userMapper.selectByMap(map);
        users.forEach(System.out::println);
    }

    /**
     * 查詢總記錄數(shù)
     * SELECT COUNT( * ) FROM user
     */
    @Test
    void testGetCount(){
        long count = userService.count();
        System.out.println("總記錄數(shù):"+count);
    }


    /**
     * 批量插入:執(zhí)行10次
     * INSERT INTO user ( id, name, age ) VALUES ( ?, ?, ? )
     */
    @Test
    void testSaveBatch(){
        List<User> userList = new ArrayList<>();
        for (int i=0;i<10;i++){
            User user = new User();
            user.setName("zl" + i);
            user.setAge(20 + i);
            userList.add(user);
        }

        boolean flag = userService.saveBatch(userList);
        System.out.println("插入是否成功:"+flag);
    }
}
4、Wrapper常規(guī)用法
package com.zl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.zl.mapper.UserMapper;
import com.zl.po.User;
import com.zl.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
import java.util.Map;

/**
 * Wrapper測試
 * @author zl
 * @time 2022/5/15
 */
@SpringBootTest
public class MybatisPlusWrapperTest {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserService userService;


    /**
     * 查詢用戶名包含a娱节,年齡在20到30之間挠蛉,并且郵箱不為null的用戶信息
     * SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND (user_name LIKE ? AND age BETWEEN ? AND ? AND email IS NOT NULL)
     */
    @Test
    void test01(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("user_name","a")
                .between("age",20,30)
                .isNotNull("email");
        List<User> userList = userMapper.selectList(queryWrapper);
        userList.forEach(System.out::println);
    }


    /**
     * 按年齡降序查詢用戶,如果年齡相同則按id升序排列
     * SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 ORDER BY age DESC,uid ASC
     */
    @Test
    void test02(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("age").orderByAsc("uid");
        List<User> userList = userMapper.selectList(queryWrapper);
        userList.forEach(System.out::println);
    }


    /**
     * 刪除email為空的用戶
     * UPDATE t_user SET is_deleted=1 WHERE is_deleted=0 AND (email IS NULL)
     */
    @Test
    void test03(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.isNull("email");
        int result = userMapper.delete(queryWrapper);
        System.out.println("影響的行數(shù):"+result);
    }


    /**
     * 將(年齡大于20并且用戶名中包含有a)或郵箱為null的用戶信息修改
     * UPDATE t_user SET age=?, email=? WHERE is_deleted=0 AND (age >= ? AND user_name LIKE ? OR email IS NULL)
     */
    @Test
    void test04(){
        User user = new User();
        user.setAge(10);
        user.setEmail("zl@163.com");

        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.ge("age",20)
                .like("user_name","a")
                .or()
                .isNull("email");

        int result = userMapper.update(user, queryWrapper);
        System.out.println("受影響的行數(shù):"+result);
    }


    /**
     * 將用戶名中包含有a并且(年齡大于20或郵箱為null)的用戶信息修改
     * UPDATE t_user SET age=?, email=? WHERE is_deleted=0 AND (user_name LIKE ? AND (age >= ? OR email IS NULL))
     */
    @Test
    void test05(){
        User user = new User();
        user.setAge(15);
        user.setEmail("zl2@163.com");

        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("user_name","a")
                .and(i->i.ge("age",20).or().isNull("email"));

        int result = userMapper.update(user, queryWrapper);
        System.out.println("受影響的行數(shù):"+result);
    }

    //todo 組裝select子句


    /**
     * 查詢用戶信息的username和age字段
     * SELECT user_name,age FROM t_user WHERE is_deleted=0
     */
    @Test
    void test06(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("user_name","age");

        //selectMaps()返回Map集合列表肄满,通常配合select()使用谴古,避免User對(duì)象中沒有被查詢到的列值為null
        List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
        maps.forEach(System.out::println);
    }


    /**
     * 將(年齡大于20或郵箱為null)并且用戶名中包含有a的用戶信息修改
     * UPDATE t_user SET age=?,email=? WHERE is_deleted=0 AND (user_name LIKE ? AND (age > ? OR email IS NULL))
     */
    @Test
    void test07(){
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("age",18)
                .set("email","zl@163.com")
                .like("user_name","a")
                .and(i->i.gt("age",20).or().isNull("email"));

        int result = userMapper.update(null, updateWrapper);
        System.out.println("影響行數(shù):"+result);
    }


    /**
     * Condition條件
     * SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND (age >= ? AND age <= ?)
     */
    @Test
    void test08(){
        //定義查詢條件,有可能為null(用戶未輸入或未選擇)
        String username = null;
        Integer ageBegin = 10;
        Integer ageEnd = 24;
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(username), "username", "a")
                .ge(ageBegin != null, "age", ageBegin)
                .le(ageEnd != null, "age", ageEnd);

        List<User> userList = userMapper.selectList(queryWrapper);
        userList.forEach(System.out::println);
    }



    @Test
    public void test09() {
        //定義查詢條件稠歉,有可能為null(用戶未輸入)
        String username = "a";
        Integer ageBegin = 10;
        Integer ageEnd = 24;
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        //避免使用字符串表示字段掰担,防止運(yùn)行時(shí)錯(cuò)誤
        queryWrapper
                .like(StringUtils.isNotBlank(username), User::getName, username)
                .ge(ageBegin != null, User::getAge, ageBegin)
                .le(ageEnd != null, User::getAge, ageEnd);
        List<User> users = userMapper.selectList(queryWrapper);
        users.forEach(System.out::println);
    }



    @Test
    public void test10() {
        //組裝set子句
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper
                .set(User::getAge, 18)
                .set(User::getEmail, "user@atguigu.com")
                .like(User::getName, "a")
                .and(i -> i.lt(User::getAge, 24).or().isNull(User::getEmail));
        //lambda表達(dá)式內(nèi)的邏輯優(yōu)先運(yùn)算
        User user = new User();
        int result = userMapper.update(user, updateWrapper);
        System.out.println("受影響的行數(shù):" + result);
    }
}
5、分頁和樂觀鎖
1) 分頁

配置類-包含分頁和樂觀鎖

package com.zl.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 插件配置類-包含分頁插件怒炸、樂觀鎖
 * @author zl
 * @time 2022/5/16
 */
@Configuration
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //添加分頁插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        //添加樂觀鎖插件
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}

簡單測試--查詢所有

/**
     * 分頁
     * SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 LIMIT ?,?
     */
    @Test
    void testPage(){
        //當(dāng)前頁恩敌、每頁顯示條數(shù)
        Page<User> page = new Page<>(1,2);
        userMapper.selectPage(page, null);

        //獲取分頁數(shù)據(jù)
        List<User> list = page.getRecords();
        list.forEach(System.out::println);
        System.out.println("當(dāng)前頁:"+page.getCurrent());
        System.out.println("每頁顯示的條數(shù):"+page.getSize());
        System.out.println("總記錄數(shù):"+page.getTotal());
        System.out.println("總頁數(shù):"+page.getPages());
        System.out.println("是否有上一頁:"+page.hasPrevious());
        System.out.println("是否有下一頁:"+page.hasNext());
    }

自定義分頁接口

Mapper

/**
* 根據(jù)年齡查詢用戶列表,分頁顯示
* @param page 分頁對(duì)象,xml中可以從里面進(jìn)行取值,傳遞參數(shù) Page 即自動(dòng)分頁,必須放在第一位
* @param age 年齡
* @return
*/
Page<User> selectPageVo(@Param("page") Page<User> page, @Param("age") Integer age);

UserMapper.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.zl.mapper.UserMapper">

    <!--  當(dāng)實(shí)體類的屬性名稱和數(shù)據(jù)庫的列名不一致時(shí)横媚,需要用resultMap映射   -->
    <resultMap id="UserMap" type="User">
        <!-- id為主鍵 -->
        <id column="id" property="id"/>
        <!-- column是數(shù)據(jù)庫表的列名 , property是對(duì)應(yīng)實(shí)體類的屬性名 -->
        <result column="uid" property="id"/>
        <result column="user_name" property="name"/>
    </resultMap>

    <!--Page<User> selectPageVo(@Param("page") Page<User> page, @Param("age") Integer age);-->
    <select id="selectPageVo" resultMap="UserMap">
        select uid,user_name,age,email from t_user where age > #{age}
    </select>

</mapper>

測試類

    /**
     *
     * 自定義分頁接口
     */
    @Test
    public void testSelectPageVo(){
        //設(shè)置分頁參數(shù)
        Page<User> page = new Page<>(1, 2);
        userMapper.selectPageVo(page, 10);
        //獲取分頁數(shù)據(jù)
        List<User> list = page.getRecords();
        list.forEach(System.out::println);
        System.out.println("當(dāng)前頁:"+page.getCurrent());
        System.out.println("每頁顯示的條數(shù):"+page.getSize());
        System.out.println("總記錄數(shù):"+page.getTotal());
        System.out.println("總頁數(shù):"+page.getPages());
        System.out.println("是否有上一頁:"+page.hasPrevious());
        System.out.println("是否有下一頁:"+page.hasNext());
    }
2) 樂觀鎖

數(shù)據(jù)庫表要增加一個(gè)字段version

然后用注解@Version

package com.zl.po;

import com.baomidou.mybatisplus.annotation.Version;
import lombok.Data;

/**
 * @author zl
 * @time 2022/5/16
 */
@Data
public class Product {

    private Long id;
    private String name;
    private Integer price;

    @Version
    private Integer version;
}

測試代碼

/**
 * 樂觀鎖
 */
@Test
public void testProduct01(){
    //小李查詢商品價(jià)格
    Product productLi = productMapper.selectById(1);
    System.out.println("小李查詢的商品價(jià)格:"+productLi.getPrice());
    //小王查詢商品價(jià)格
    Product productWang = productMapper.selectById(1);
    System.out.println("小王查詢的商品價(jià)格:"+productWang.getPrice());
    //小李將商品價(jià)格+50
    productLi.setPrice(productLi.getPrice()+50);
    productMapper.updateById(productLi);
    //小王將商品價(jià)格-30
    productWang.setPrice(productWang.getPrice()-30);
    int result = productMapper.updateById(productWang);
    if(result == 0){
        //操作失敗纠炮,重試
        Product productNew = productMapper.selectById(1);
        productNew.setPrice(productNew.getPrice()-30);
        productMapper.updateById(productNew);
    }
    //老板查詢商品價(jià)格
    Product productLaoban = productMapper.selectById(1);
    System.out.println("老板查詢的商品價(jià)格:"+productLaoban.getPrice());
}
6、代碼生成器

依賴

<!--   代碼生成器  -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.5.1</version>
</dependency>
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.31</version>
</dependency>

測試類

package com.zl;

import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.Collections;

/**
 * @author zl
 * @time 2022/5/16
 */
public class FastAutoGeneratorTest {

    public static void main(String[] args) {
        FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3307/mybatis_plus?characterEncoding=utf-8&userSSL=false", "root", "root")
                .globalConfig(builder -> {
                    builder.author("zl") // 設(shè)置作者
                            //.enableSwagger() // 開啟 swagger 模式
                            .fileOverride() // 覆蓋已生成文件
                            .outputDir("D://mybatis_plus"); // 指定輸出目錄
                })
                .packageConfig(builder -> {
                    builder.parent("com.zl") // 設(shè)置父包名
                            .moduleName("mybatisplus") // 設(shè)置父包模塊名
                            .pathInfo(Collections.singletonMap(OutputFile.mapperXml, "D://mybatis_plus")); // 設(shè)置mapperXml生成路徑
                })
                .strategyConfig(builder -> {
                    builder.addInclude("t_user") // 設(shè)置需要生成的表名
                            .addTablePrefix("t_", "c_"); // 設(shè)置過濾表前綴
                })
                .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板灯蝴,默認(rèn)的是Velocity引擎模板
                .execute();
    }
}
7恢口、多數(shù)據(jù)源

依賴

<!--   多數(shù)據(jù)源  -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.5.0</version>
</dependency>

配置文件

spring:
  # 配置數(shù)據(jù)源信息
  datasource:
    dynamic:
      # 設(shè)置默認(rèn)的數(shù)據(jù)源或者數(shù)據(jù)源組,默認(rèn)值即為master
      primary: master
      # 嚴(yán)格匹配數(shù)據(jù)源,默認(rèn)false.true未匹配到指定數(shù)據(jù)源時(shí)拋異常,false使用默認(rèn)數(shù)據(jù)源
      strict: false
      datasource:
        master:
          url: jdbc:mysql://localhost:3307/mybatis_plus?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true
          driver-class-name: com.mysql.cj.jdbc.Driver
          username: root
          password: root
        slave_1:
          url: jdbc:mysql://localhost:3307/mybatis_plus_1?characterEncoding=utf-8&useSSL=false
          driver-class-name: com.mysql.cj.jdbc.Driver
          username: root
          password: root
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  type-aliases-package: com.zl.po

在UserServiceImpl上加上注解@DS

package com.zl.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zl.mapper.UserMapper;
import com.zl.po.User;
import com.zl.service.UserService;
import org.springframework.stereotype.Service;

/**
 * @author zl
 * @time 2022/5/15
 */
//指定所操作的數(shù)據(jù)源
@DS("master") 
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
8、MybatisX插件

MyBatis-Plus為我們提供了強(qiáng)大的mapper和service模板穷躁,能夠大大的提高開發(fā)效率

但是在真正開發(fā)過程中耕肩,MyBatis-Plus并不能為我們解決所有問題,例如一些復(fù)雜的SQL问潭,多表 聯(lián)查猿诸,我們就需要自己去編寫代碼和SQL語句,我們?cè)撊绾慰焖俚慕鉀Q這個(gè)問題呢狡忙,這個(gè)時(shí)候可 以使用MyBatisX插件 MyBatisX一款基于 IDEA 的快速開發(fā)插件梳虽,為效率而生。

MyBatisX插件用法:https://baomidou.com/pages/ba5b24

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末灾茁,一起剝皮案震驚了整個(gè)濱河市窜觉,隨后出現(xiàn)的幾起案子谷炸,更是在濱河造成了極大的恐慌,老刑警劉巖禀挫,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件旬陡,死亡現(xiàn)場離奇詭異,居然都是意外死亡语婴,警方通過查閱死者的電腦和手機(jī)描孟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來砰左,“玉大人匿醒,你說我怎么就攤上這事〔酥埃” “怎么了?”我有些...
    開封第一講書人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵旗闽,是天一觀的道長酬核。 經(jīng)常有香客問我,道長适室,這世上最難降的妖魔是什么嫡意? 我笑而不...
    開封第一講書人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮捣辆,結(jié)果婚禮上蔬螟,老公的妹妹穿的比我還像新娘。我一直安慰自己汽畴,他們只是感情好旧巾,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著忍些,像睡著了一般鲁猩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上罢坝,一...
    開封第一講書人閱讀 51,541評(píng)論 1 305
  • 那天廓握,我揣著相機(jī)與錄音,去河邊找鬼嘁酿。 笑死隙券,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的闹司。 我是一名探鬼主播娱仔,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼游桩!你這毒婦竟也來了拟枚?” 一聲冷哼從身側(cè)響起薪铜,我...
    開封第一講書人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎恩溅,沒想到半個(gè)月后隔箍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡脚乡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年蜒滩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奶稠。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡俯艰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出锌订,到底是詐尸還是另有隱情竹握,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布辆飘,位于F島的核電站啦辐,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蜈项。R本人自食惡果不足惜芹关,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望紧卒。 院中可真熱鬧侥衬,春花似錦、人聲如沸跑芳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽博个。三九已至肘习,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間坡倔,已是汗流浹背漂佩。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留罪塔,地道東北人投蝉。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像征堪,于是被迫代替她去往敵國和親瘩缆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355