日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

MyBatis_Plus(Spring版本笔记)

發(fā)布時(shí)間:2024/1/8 javascript 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MyBatis_Plus(Spring版本笔记) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

  • 前言
  • 一、MyBatis-Plus簡(jiǎn)介
    • 1.1 簡(jiǎn)介
    • 1.2 特性
    • 1.3 支持?jǐn)?shù)據(jù)庫(kù)
    • 1.4 框架結(jié)構(gòu)
    • 1.5 代碼及文檔地址
  • 二、 入門案例
    • 2.1 開發(fā)環(huán)境
    • 2.2 創(chuàng)建數(shù)據(jù)庫(kù)和表
      • 2.2.1 創(chuàng)建表
      • 2.2.2 添加數(shù)據(jù)
    • 2.3 創(chuàng)建maven工程
      • 2.3.1 打包方式 jar
      • 2.3.2 引入依賴
    • 2.4 Spring整合MyBatis
      • 2.4.1 創(chuàng)建實(shí)體
      • 2.4.2 創(chuàng)建MyBatis的核心配置文件
      • 2.4.3 創(chuàng)建mapper接口和映射文件
      • 2.4.4 創(chuàng)建jdbc.properties
      • 2.4.5 創(chuàng)建Spring的配置文件
      • 2.4.6 添加日志功能
      • 2.4.7 測(cè)試
    • 2.5 加入MyBatis-Plus
      • 2.5.1 創(chuàng)建Mapper接口
      • 2.5.2 測(cè)試
      • 2.5.3 結(jié)果
    • 2.6 總結(jié)
  • 三、基本CRUD
    • 3.1 BaseMapper
    • 3.2 BaseMapper功能測(cè)試
    • 3.3 通用Service
      • 3.3.1 IService
      • 3.3.2 創(chuàng)建Service接口和實(shí)現(xiàn)類
      • 3.3.3 在spring配置文件中設(shè)置自動(dòng)掃描service的包
      • 3.3.4 測(cè)試查詢記錄條數(shù)和批量添加
  • 四、常用注解
    • 4.1 @TableName
      • 4.1.1 問題
      • 4.1.2 通過@TableName解決問題
      • 4.1.3 通過GlobalConfig解決問題
    • 4.2 @TableId
      • 4.2.1 問題引出
      • 4.2.2 通過@TableId解決問題
      • 4.2.3 @TableId的value屬性
      • 4.2.4 @TableId的type屬性
      • 4.2.5 雪花算法
    • 4.3 @TableField
    • 4.4 @TableLogic(邏輯刪除)
      • 4.4.1 邏輯刪除
      • 4.4.2 實(shí)現(xiàn)邏輯刪除
  • 五、條件構(gòu)造器和常用接口
    • 5.1 wapper介紹
    • 5.2 QueryWrapper
      • 5.2.1 組裝查詢條件
      • 5.2.2 組裝排序條件
      • 5.2.3 組裝刪除條件
      • 5.2.4 條件的優(yōu)先級(jí)
      • 5.2.5 組裝select子句
      • 5.2.6 實(shí)現(xiàn)子查詢
    • 5.3 UpdateWrapper
    • 5.4 condition
    • 5.5 LambdaQueryWrapper
    • 5.6 LambdaUpdateWrapper
  • 六、插件
    • 6.1 分頁插件
      • 6.1.1 添加配置
      • 6.1.2 測(cè)試
    • 6.2 xml自定義分頁
      • 6.2.1 UserMapper中定義接口方法
      • 6.2.2 UserMapper.xml中編寫SQL
      • 6.2.3 測(cè)試
    • 6.3 樂觀鎖
      • 6.3.1 場(chǎng)景
      • 6.3.2 樂觀鎖與悲觀鎖
      • 6.3.3 模擬修改沖突
      • 6.3.4 樂觀鎖實(shí)現(xiàn)流程
      • 6.3.5 Mybatis-Plus實(shí)現(xiàn)樂觀鎖
  • 七 、通用枚舉
    • 7.1 數(shù)據(jù)庫(kù)添加字段sex
    • 7.2 創(chuàng)建通用枚舉
    • 7.3 配置掃描通用枚舉
    • 7.4 測(cè)試
  • 八、代碼生成器
    • 8.1 引入依賴
    • 8.2 快速生成
  • 九 、MyBatisX插件
    • 9.1 安裝插件
    • 9.2 功能
      • 9.2.1 XML跳轉(zhuǎn)
      • 9.2.2 快速生成代碼
  • 十、總結(jié)


前言

本文主要參考嗶站尚硅谷楊博超講師課件整理而成,屬于自己復(fù)習(xí)使用。


提示:以下是本篇文章正文內(nèi)容,下面案例可供參考

一、MyBatis-Plus簡(jiǎn)介

1.1 簡(jiǎn)介

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

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

1.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ù)庫(kù):支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多種數(shù)據(jù)庫(kù)
  • 內(nèi)置性能分析插件:可輸出 SQL 語句以及其執(zhí)行時(shí)間,建議開發(fā)測(cè)試時(shí)啟用該功能,能快速揪出慢查詢

1.3 支持?jǐn)?shù)據(jù)庫(kù)

任何能使用MyBatis進(jìn)行 CRUD, 并且支持標(biāo)準(zhǔn) SQL 的數(shù)據(jù)庫(kù),具體支持情況如下

  • MySQL,Oracle,DB2,H2,HSQL,SQLite,PostgreSQLSQLServer,Phoenix,Gauss ,ClickHouse,Sybase,OceanBase,Firebird,Cubrid,Goldilocks,csiidb
  • 達(dá)夢(mèng)數(shù)據(jù)庫(kù),虛谷數(shù)據(jù)庫(kù),人大金倉(cāng)數(shù)據(jù)庫(kù),南大通用(華庫(kù))數(shù)據(jù)庫(kù),南大通用數(shù)據(jù)庫(kù),神通數(shù)據(jù)庫(kù),瀚高數(shù)據(jù)庫(kù)

1.4 框架結(jié)構(gòu)

1.5 代碼及文檔地址

官方地址:http://mp.baomidou.com
代碼發(fā)布地址:
Github: https://github.com/baomidou/mybatis-plus
Gitee: https://gitee.com/baomidou/mybatis-plus
文檔發(fā)布地址:https://baomidou.com/pages/24112f


二、 入門案例

2.1 開發(fā)環(huán)境

以maven工程為例,以ssm整合為技術(shù)框架。

工具版本
IDEidea 2021.3
JDKJDK1.8
MAVENmaven 3.8.4
MySQLMySQL8.0.25
Spring5.3.1
MyBatis-Plus3.4.3.4

2.2 創(chuàng)建數(shù)據(jù)庫(kù)和表

2.2.1 創(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;

2.2.2 添加數(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.3 創(chuàng)建maven工程

2.3.1 打包方式 jar

<packaging>jar</packaging>

2.3.2 引入依賴

<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${spring.version}</version></dependency><!-- 連接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.8</version></dependency><!-- junit測(cè)試 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!-- MySQL驅(qū)動(dòng) --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.27</version></dependency><!-- 日志 --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.30</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version></dependency><!-- lombok用來簡(jiǎn)化實(shí)體類 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.16</version></dependency><!--MyBatis-Plus的核心依賴--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus</artifactId><version>3.4.3.4</version></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>RELEASE</version><scope>test</scope></dependency><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></dependencies><properties><spring.version>5.3.1</spring.version></properties>

注意:
Spring整合MyBatis,需要MyBatis以及Spring整合MyBatis的依賴:

但是,在以上的依賴列表中,并沒有MyBatis以及Spring整合MyBatis的依賴,因?yàn)楫?dāng)我們引入了
MyBatis-Plus的依賴時(shí),就可以間接的引入這些依賴

并且依賴和依賴之間的版本必須兼容,所以我們不能隨便引入其他版本的依賴,以免發(fā)生沖突
在官網(wǎng)上有明確提示:

2.4 Spring整合MyBatis

2.4.1 創(chuàng)建實(shí)體

public class User {private Long id;private String name;private int age;private String email;public User(Long id, String name, int age, String email) {this.id = id;this.name = name;this.age = age;this.email = email;}public User() {}public Long getId() {return this.id;}public String getName() {return this.name;}public int getAge() {return this.age;}public String getEmail() {return this.email;}public SexEnum getSex() {return this.sex;}public int getIsDeleted() {return this.isDeleted;}public void setId(Long id) {this.id = id;}public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}public void setEmail(String email) {this.email = email;}public void setSex(SexEnum sex) {this.sex = sex;}public void setIsDeleted(int isDeleted) {this.isDeleted = isDeleted;}public String toString() {return "User(id=" + this.getId() + ", name=" + this.getName() + ", age=" + this.getAge() + ", email=" + this.getEmail() + ", sex=" + this.getSex() + ", isDeleted=" + this.getIsDeleted() + ")";} }

2.4.2 創(chuàng)建MyBatis的核心配置文件

在resources下創(chuàng)建mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration></configuration>

2.4.3 創(chuàng)建mapper接口和映射文件

  • mapper接口:
public interface TestMapper { /** * 查詢所有用戶信息 * @return */ List<User> getAllUser(); }
  • mapper映射文件:
    在resources下的com/atguigu/mp/mapper目錄下創(chuàng)建TestMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.atguigu.mybatisplus.mapper.UserMapper"><!--SQL片段,記錄基礎(chǔ)字段--><!--<sql id="BaseColumns">id,name,age,email</sql>--><!--第一種寫法--><!--List<User> getAllUser();--><select id="getAllUser" resultType="User">select <include refid="BaseColumns"></include> from user</select><!--第二種寫法--><!--List<User> getAllUser();--><select id="getAllUser" resultType="User"><!--select <include refid="BaseColumns"></include> from user-->select id,name,age,email from user</select> </mapper>

2.4.4 創(chuàng)建jdbc.properties

在resources下創(chuàng)建jdbc.properties

jdbc.username=root jdbc.password=5864@WCY jdbc.url=jdbc:mysql://localhost:3306/mybatis_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false jdbc.driver=com.mysql.cj.jdbc.Driver

2.4.5 創(chuàng)建Spring的配置文件

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd"><!-- 引入jdbc.properties --><context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder><!-- 配置Druid數(shù)據(jù)源 --><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driver}"></property><property name="url" value="${jdbc.url}"></property><property name="username" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property></bean><!-- 配置用于創(chuàng)建SqlSessionFactory的工廠bean --><bean id="mybatisSqlSessionFactoryBean" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"><!-- 設(shè)置MyBatis配置文件的路徑(可以不設(shè)置) --><property name="configLocation" value="classpath:mybatis-config.xml"></property><!-- 設(shè)置數(shù)據(jù)源 --><property name="dataSource" ref="dataSource"></property><!-- 設(shè)置類型別名所對(duì)應(yīng)的包 --><property name="typeAliasesPackage" value="com.atguigu.mybatisplus.pojo"></property><!--設(shè)置映射文件的路徑若映射文件所在路徑和mapper接口所在路徑一致,則不需要設(shè)置--><property name="mapperLocations" value="classpath:mappers/*Mapper.xml"/></bean><!--配置mapper接口的掃描配置由mybatis-spring提供,可以將指定包下所有的mapper接口創(chuàng)建動(dòng)態(tài)代理并將這些動(dòng)態(tài)代理作為IOC容器的bean管理--><bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.atguigu.mybatisplus.mapper"></property></bean><!--配置自動(dòng)掃描的包--><context:component-scan base-package="com.atguigu.mybatisplus.service"></context:component-scan> </beans>

2.4.6 添加日志功能

在resources下創(chuàng)建logback.xml

<?xml version="1.0" encoding="UTF-8"?> <configuration debug="false"><!--定義日志文件的存儲(chǔ)地址 logs為當(dāng)前項(xiàng)目的logs目錄 還可以設(shè)置為../logs --><property name="LOG_HOME" value="logs" /><!--控制臺(tái)日志, 控制臺(tái)輸出 --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級(jí)別從左顯示5個(gè)字符寬度,%msg:日志消息,%n是換行符--><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}- %msg%n</pattern></encoder></appender><!--myibatis log configure--><logger name="com.apache.ibatis" level="TRACE"/><logger name="java.sql.Connection" level="DEBUG"/><logger name="java.sql.Statement" level="DEBUG"/><logger name="java.sql.PreparedStatement" level="DEBUG"/><!-- 日志輸出級(jí)別 --><root level="DEBUG"><appender-ref ref="STDOUT" /></root></configuration>

2.4.7 測(cè)試

  • 方式一:通過IOC容器
public class MyBatisPlusTest {@Testpublic void testMyBatis(){ApplicationContext ac = newClassPathXmlApplicationContext("applicationContext.xml");TestMapper mapper = ac.getBean(TestMapper.class);mapper.getAllUser().forEach(user -> System.out.println(user));} }
  • 方式二 Spring整合junit
//在Spring的環(huán)境中進(jìn)行測(cè)試 @RunWith(SpringJUnit4ClassRunner.class) //指定Spring的配置文件 @ContextConfiguration("classpath:applicationContext.xml") public class MyBatisPlusTest {@Autowiredprivate TestMapper testMapper;@Testpublic void testMyBatisBySpring(){testMapper.getAllUser().forEach(user -> System.out.println(user));} }


2.5 加入MyBatis-Plus

Spring整合MyBatis

加入MyBatis-Plus之后

<!-- 此處使用的是MybatisSqlSessionFactoryBean --> <!-- 配置用于創(chuàng)建SqlSessionFactory的工廠bean --><bean id="mybatisSqlSessionFactoryBean" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"><!-- 設(shè)置MyBatis配置文件的路徑(可以不設(shè)置) --><property name="configLocation" value="classpath:mybatis-config.xml"></property><!-- 設(shè)置數(shù)據(jù)源 --><property name="dataSource" ref="dataSource"></property><!-- 設(shè)置類型別名所對(duì)應(yīng)的包 --><property name="typeAliasesPackage" value="com.atguigu.mybatisplus.pojo"></property><!--設(shè)置映射文件的路徑若映射文件所在路徑和mapper接口所在路徑一致,則不需要設(shè)置--><property name="mapperLocations" value="classpath:mappers/*Mapper.xml"/></bean>

此處使用的是MybatisSqlSessionFactoryBean
經(jīng)觀察,目前bean中配置的屬性和SqlSessionFactoryBean一致
MybatisSqlSessionFactoryBean是在SqlSessionFactoryBean的基礎(chǔ)上進(jìn)行了增強(qiáng)
即具有SqlSessionFactoryBean的基礎(chǔ)功能,又具有MyBatis-Plus的擴(kuò)展配置
具體配置信息地址(https://baomidou.com/pages/56bac0/#%E5%9F%BA%E6%9C%AC%E9%
85%8D%E7%BD%AE)


2.5.1 創(chuàng)建Mapper接口

public interface UserMapper extends BaseMapper<User> { }

BaseMapper是MyBatis-Plus提供的基礎(chǔ)mapper接口,泛型為所操作的實(shí)體類型,其中包含CRUD的各個(gè)方法,我們的mapper繼承了BaseMapper之后,就可以直接使用BaseMapper所提供的各種方法,而不需要編寫映射文件以及SQL語句,大大的提高了開發(fā)效率

2.5.2 測(cè)試

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class MyBatisPlusTest {/*沒有使用mybatis_plus@Testpublic void testMyBatis(){ApplicationContext ac = newClassPathXmlApplicationContext("applicationContext.xml");UserMapper mapper = ac.getBean(UserMapper.class);mapper.getAllUser().forEach(user -> System.out.println(user));}*/@Autowiredprivate UserMapper userMapper;/*---------------------------------使用MyBatisPlus之后-------------------------------------*/@Testpublic void testMyBatisPlus(){//查詢所有用戶信息// SELECT id,name,age,email FROM userSystem.out.println(userMapper.selectList(null));}

2.5.3 結(jié)果

2.6 總結(jié)

在Spring整合MyBatis中加入了MyBatis-Plus后,我們就可以使用MyBatis-Plus所提供的BaseMapper實(shí)現(xiàn)CRUD,并不需要編寫映射文件以及SQL語句
但是若要自定義SQL語句,仍然可以編寫映射文件而不造成任何影響。因?yàn)镸yBatis-Plus只做增強(qiáng),而不做改變。

三、基本CRUD

3.1 BaseMapper

MyBatis-Plus中的基本CRUD在內(nèi)置的BaseMapper中都已得到了實(shí)現(xiàn),我們可以直接使用,接口如下:

/*** Mapper 繼承該接口后,無需編寫 mapper.xml 文件,即可獲得CRUD功能* <p>這個(gè) Mapper 支持 id 泛型</p>** @author hubin* @since 2016-01-23*/ public interface BaseMapper<T> extends Mapper<T> {/*** 插入一條記錄** @param entity 實(shí)體對(duì)象*/int insert(T entity);/*** 根據(jù) ID 刪除** @param id 主鍵ID*/int deleteById(Serializable id);/*** 根據(jù)實(shí)體(ID)刪除** @param entity 實(shí)體對(duì)象* @since 3.4.4*/int deleteById(T entity);/*** 根據(jù) columnMap 條件,刪除記錄** @param columnMap 表字段 map 對(duì)象*/int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);/*** 根據(jù) entity 條件,刪除記錄** @param queryWrapper 實(shí)體對(duì)象封裝操作類(可以為 null,里面的 entity 用于生成 where 語句)*/int delete(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);/*** 刪除(根據(jù)ID 批量刪除)** @param idList 主鍵ID列表(不能為 null 以及 empty)*/int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);/*** 根據(jù) ID 修改** @param entity 實(shí)體對(duì)象*/int updateById(@Param(Constants.ENTITY) T entity);/*** 根據(jù) whereEntity 條件,更新記錄** @param entity 實(shí)體對(duì)象 (set 條件值,可以為 null)* @param updateWrapper 實(shí)體對(duì)象封裝操作類(可以為 null,里面的 entity 用于生成 where 語句)*/int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);/*** 根據(jù) ID 查詢** @param id 主鍵ID*/T selectById(Serializable id);/*** 查詢(根據(jù)ID 批量查詢)** @param idList 主鍵ID列表(不能為 null 以及 empty)*/List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);/*** 查詢(根據(jù) columnMap 條件)** @param columnMap 表字段 map 對(duì)象*/List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);/*** 根據(jù) entity 條件,查詢一條記錄* <p>查詢一條記錄,例如 qw.last("limit 1") 限制取一條記錄, 注意:多條數(shù)據(jù)會(huì)報(bào)異常</p>** @param queryWrapper 實(shí)體對(duì)象封裝操作類(可以為 null)*/default T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper) {List<T> ts = this.selectList(queryWrapper);if (CollectionUtils.isNotEmpty(ts)) {if (ts.size() != 1) {throw ExceptionUtils.mpe("One record is expected, but the query result is multiple records");}return ts.get(0);}return null;}/*** 根據(jù) Wrapper 條件,查詢總記錄數(shù)** @param queryWrapper 實(shí)體對(duì)象封裝操作類(可以為 null)*/Long selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);/*** 根據(jù) entity 條件,查詢?nèi)坑涗?* @param queryWrapper 實(shí)體對(duì)象封裝操作類(可以為 null)*/List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);/*** 根據(jù) Wrapper 條件,查詢?nèi)坑涗?* @param queryWrapper 實(shí)體對(duì)象封裝操作類(可以為 null)*/List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);/*** 根據(jù) Wrapper 條件,查詢?nèi)坑涗? <p>注意: 只返回第一個(gè)字段的值</p>** @param queryWrapper 實(shí)體對(duì)象封裝操作類(可以為 null)*/List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);/*** 根據(jù) entity 條件,查詢?nèi)坑涗?#xff08;并翻頁)** @param page 分頁查詢條件(可以為 RowBounds.DEFAULT)* @param queryWrapper 實(shí)體對(duì)象封裝操作類(可以為 null)*/<P extends IPage<T>> P selectPage(P page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);/*** 根據(jù) Wrapper 條件,查詢?nèi)坑涗?#xff08;并翻頁)** @param page 分頁查詢條件* @param queryWrapper 實(shí)體對(duì)象封裝操作類*/<P extends IPage<Map<String, Object>>> P selectMapsPage(P page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper); }

3.2 BaseMapper功能測(cè)試

//插入@Testpublic void testInsert(){// INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? )User user = new User(6,"張三",23,"zhangsan@126.com");int result = userMapper.insert(user);System.out.println("result="+result);}//刪除@Testpublic void testDelete(){//根據(jù)Id刪除用戶//DELETE FROM user WHERE id=?int result = userMapper.deleteById(2L);//根據(jù)map集合刪除//DELETE FROM user WHERE name = ? AND age = ?Map<String,Object> map = new HashMap<>();map.put("name","張三");map.put("age",23);int result = userMapper.deleteByMap(map);// 根據(jù)id批量刪除// DELETE FROM user WHERE id IN ( ? , ? , ? )List<Integer> list = Arrays.asList(1, 2, 3);int result = userMapper.deleteBatchIds(list);System.out.println("result="+result);}//修改@Testpublic void testUpdate(){ // UPDATE user SET name=?, email=? WHERE id=?User user = new User();user.setId(4L);user.setName("李四");user.setEmail("lisi@atguigu.com");int result = userMapper.updateById(user);System.out.println("result="+result);}//查詢@Testpublic void testSelect(){//根據(jù)Id查詢用戶 // SELECT id,name,age,email FROM user WHERE id=?User user = userMapper.selectById(5L);System.out.println(user);// SELECT id,name,age,email FROM user WHERE id IN ( ? , ? , ? )List<Integer> list = Arrays.asList(1, 2, 4);List<User> users = userMapper.selectBatchIds(list);users.forEach(System.out::println);Map<String,Object> map = new HashMap<>();map.put("age",23);List<User> users = userMapper.selectByMap(map);users.forEach(System.out::println);}

通過觀察BaseMapper中的方法,大多方法中都有Wrapper類型的形參,此為條件構(gòu)造器,可針對(duì)于SQL語句設(shè)置不同的條件,若沒有條件,則可以為該形參賦值null,即查詢(刪除/修改)所有數(shù)據(jù)


3.3 通用Service

說明:

  • 通用 Service CRUD 封裝IService接口,進(jìn)一步封裝 CRUD 采用 get 查詢單行 remove 刪除 list 查詢集合 page 分頁 , 前綴命名方式區(qū)分 Mapper 層避免混淆
  • 泛型 T 為任意實(shí)體對(duì)象
  • 建議如果存在自定義通用 Service 方法的可能,請(qǐng)創(chuàng)建自己的 IBaseService 繼承Mybatis-Plus 提供的基類
  • 官網(wǎng)地址:https://baomidou.com/pages/49cc81/#service-crud-%E6%8E%A5%E5%8F%A3

3.3.1 IService

MyBatis-Plus中有一個(gè)接口 IService和其實(shí)現(xiàn)類 ServiceImpl,封裝了常見的業(yè)務(wù)層邏輯

詳情查看源碼IService和ServiceImpl

3.3.2 創(chuàng)建Service接口和實(shí)現(xiàn)類

UserService

/** * UserService繼承IService模板提供的基礎(chǔ)功能 */ public interface UserService extends IService<User> {}

UserServiceImpl

/** * ServiceImpl實(shí)現(xiàn)了IService,提供了IService中基礎(chǔ)功能的實(shí)現(xiàn) * 若ServiceImpl無法滿足業(yè)務(wù)需求,則可以使用自定的UserService定義方法,并在實(shí)現(xiàn)類中實(shí)現(xiàn) */ @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {}

3.3.3 在spring配置文件中設(shè)置自動(dòng)掃描service的包

在applicationContext.xml中添加掃描組件的配置,掃描業(yè)務(wù)層組件,用于測(cè)試

<context:component-scan base-package="com.atguigu.mybatisplus.service.impl"></context:component-scan>

3.3.4 測(cè)試查詢記錄條數(shù)和批量添加

//spring測(cè)試類寫法一 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class MyBatisServiceTest {@Autowiredprivate UserService userService;@Testpublic void testCount(){//查詢總記錄條數(shù)//SELECT COUNT( * ) FROM userlong count = userService.count();System.out.println("總記錄條數(shù)" + count);}@Testpublic void testSaveBatch(){//實(shí)現(xiàn)新增用戶ArrayList<User> list = new ArrayList<>();// SQL長(zhǎng)度有限制,海量數(shù)據(jù)插入單條SQL無法實(shí)行,// 因此MP將批量插入放在了通用Service中實(shí)現(xiàn),而不是通用Mapperfor (int i = 0; i < 100 ; i++) {User user = new User();user.setName("abc"+i);user.setAge(20+i);list.add(user);}//INSERT INTO user ( id, name, age ) VALUES ( ?, ?, ? )boolean b = userService.saveBatch(list);System.out.println(b);}}

錯(cuò)誤:
Duplicate entry ‘0’ for key ‘PRIMARY’
原因:發(fā)現(xiàn)了是數(shù)據(jù)庫(kù)表設(shè)計(jì)不合理導(dǎo)致的;
因?yàn)橹麈I設(shè)置不能為空,因此默認(rèn)是以"0"來進(jìn)行填充的。因此在數(shù)據(jù)插入時(shí)數(shù)據(jù)的主鍵id值被0占據(jù),但由于之前已經(jīng)有數(shù)據(jù)了,id為“0”的索引已經(jīng)被占,在使用就會(huì)報(bào)這個(gè)錯(cuò)誤,因此我們只需要對(duì)表中的主鍵“id”設(shè)置成自增即可。

糾正:為什么會(huì)出現(xiàn)這個(gè)問題,是因?yàn)樵趧?chuàng)建實(shí)體類的時(shí)候id屬性的類型寫成long了,應(yīng)該寫成Long不然雪花算法是不會(huì)實(shí)現(xiàn)的。大小寫要注意。

四、常用注解

4.1 @TableName

經(jīng)過以上的測(cè)試,在使用MyBatis-Plus實(shí)現(xiàn)基本的CRUD時(shí),我們并沒有指定要操作的表,只是在Mapper接口繼承BaseMapper時(shí),設(shè)置了泛型User,而操作的表為user表:
由此得出結(jié)論,MyBatis-Plus在確定操作的表時(shí),由BaseMapper的泛型決定,即實(shí)體類型決定,且默認(rèn)操作的表名和實(shí)體類型的類名一致

4.1.1 問題

若實(shí)體類類型的類名和要操作的表的表名不一致,會(huì)出現(xiàn)什么問題?
我們將表user更名為t_user,測(cè)試查詢功能
程序拋出異常,Table ‘mybatis_plus.user’ doesn’t exist,因?yàn)楝F(xiàn)在的表名為t_user,而默認(rèn)操作的表名和實(shí)體類型的類名一致,即user表

4.1.2 通過@TableName解決問題

在實(shí)體類類型上添加==@TableName(“t_user”)==,標(biāo)識(shí)實(shí)體類對(duì)應(yīng)的表,即可成功執(zhí)行SQL語句。

4.1.3 通過GlobalConfig解決問題

在開發(fā)的過程中,我們經(jīng)常遇到以上的問題,即實(shí)體類所對(duì)應(yīng)的表都有固定的前綴,例如t_tbl_
此時(shí),可以使用MyBatis-Plus提供的全局配置,為實(shí)體類所對(duì)應(yīng)的表名設(shè)置默認(rèn)的前綴,那么就不需要在每個(gè)實(shí)體類上通過@TableName標(biāo)識(shí)實(shí)體類對(duì)應(yīng)的表。

在spring配置文件中修改:spring-persist.xml中的sqlsessionfactorybean

<!--使用mybatisplus--><bean id="mybatisSqlSessionFactoryBean" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"><!--指定mybatis配置文件--><property name="configLocation" value="classpath:mybatis-config.xml"/><!--指定mapper.xml--><property name="mapperLocations" value="classpath:mappers/*Mapper.xml"/><!--裝配數(shù)據(jù)源--><property name="dataSource" ref="dataSource"/><!--設(shè)置mybatisplus的全局配置,即表的前綴--><property name="globalConfig" ref="globalConfig"></property></bean><bean id="globalConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig"><property name="dbConfig"><bean id="config" class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig"><!--設(shè)置實(shí)體類所對(duì)應(yīng)的表的前綴--><property name="tablePrefix" value="t_"></property></bean></property></bean>

4.2 @TableId

經(jīng)過以上的測(cè)試,MyBatis-Plus在實(shí)現(xiàn)CRUD時(shí),會(huì)默認(rèn)將id作為主鍵列,并在插入數(shù)據(jù)時(shí),默認(rèn)基于雪花算法的策略生成id。

4.2.1 問題引出

若實(shí)體類和表中表示主鍵的不是id,而是其他字段,例如uid,MyBatis-Plus會(huì)自動(dòng)識(shí)別uid為主鍵列嗎?
我們實(shí)體類中的屬性id改為uid,將表中的字段id也改為uid,測(cè)試添加功能程序拋出異常,Field ‘uid’ doesn’t have a default value,說明MyBatis-Plus沒有將uid作為主鍵賦值

4.2.2 通過@TableId解決問題

在實(shí)體類中uid屬性上通過@TableId將其標(biāo)識(shí)為主鍵,即可成功執(zhí)行SQL語句。

4.2.3 @TableId的value屬性

若實(shí)體類中主鍵對(duì)應(yīng)的屬性為id,而表中表示主鍵的字段為uid,此時(shí)若只在屬性id上添加注解@TableId,則拋出異常Unknown column ‘id’ in ‘field list’,即MyBatis-Plus仍然會(huì)將id作為表的主鍵操作,而表中表示主鍵的是字段uid
此時(shí)需要通過@TableId注解的value屬性,指定表中的主鍵字段@TableId(“uid”)或@TableId(value=“uid”)

public class User {//將屬性所對(duì)應(yīng)的字段指定為主鍵// @TableId注解的value屬性用于指定主鍵的字段@TableId("uid")private Long id;

4.2.4 @TableId的type屬性

type屬性用來定義主鍵策略


[1]臨時(shí)修改

public class User {//將屬性所對(duì)應(yīng)的字段指定為主鍵// @TableId注解的value屬性用于指定主鍵的字段// @TableId注解的type屬性設(shè)置主鍵生成策略// @TableId(value = "uid", type = IdType.AUTO)@TableId("uid")private Long id;

[2] 配置全局配置(全局有效)
在spring-persist.xml中修改。

<bean id="globalConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig"><property name="dbConfig"><bean id="config" class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig"><!--設(shè)置實(shí)體類所對(duì)應(yīng)的表的前綴--><property name="tablePrefix" value="t_"></property><!--設(shè)置全局主鍵策略--><property name="idType" value="AUTO"></property></bean></property></bean>

4.2.5 雪花算法






4.3 @TableField

經(jīng)過以上的測(cè)試,我們可以發(fā)現(xiàn),MyBatis-Plus在執(zhí)行SQL語句時(shí),要保證實(shí)體類中的屬性名和表中的字段名一致
如果實(shí)體類中的屬性名和字段名不一致的情況,會(huì)出現(xiàn)什么問題呢?
a>情況1

若實(shí)體類中的屬性使用的是駝峰命名風(fēng)格,而表中的字段使用的是下劃線命名風(fēng)格
例如實(shí)體類屬性u(píng)serName,表中字段user_name
此時(shí)MyBatis-Plus會(huì)自動(dòng)將下劃線命名風(fēng)格轉(zhuǎn)化為駝峰命名風(fēng)格
相當(dāng)于在MyBatis中配置

b>情況2

若實(shí)體類中的屬性和表中的字段不滿足情況1
例如實(shí)體類屬性name,表中字段username
此時(shí)需要在實(shí)體類屬性上使用@TableField(“username”)設(shè)置屬性所對(duì)應(yīng)的字段名

//注意:如果實(shí)體類中屬性名為:name,表中字段名也要為:name// 在不加@TableField注解的情況下,表中字段為:user_name 代碼會(huì)報(bào)錯(cuò)。//指定屬性對(duì)應(yīng)的字段名//當(dāng)實(shí)體類中是name,表中所對(duì)應(yīng)的字段名是:user_name,可以使用該注解來實(shí)現(xiàn)指定屬性對(duì)應(yīng)的字段名@TableField("user_name")private String name;

4.4 @TableLogic(邏輯刪除)

4.4.1 邏輯刪除

邏輯刪除

物理刪除:真實(shí)刪除,將對(duì)應(yīng)數(shù)據(jù)從數(shù)據(jù)庫(kù)中刪除,之后查詢不到此條被刪除的數(shù)據(jù)
邏輯刪除:假刪除,將對(duì)應(yīng)數(shù)據(jù)中代表是否被刪除字段的狀態(tài)修改為“被刪除狀態(tài)”,之后在數(shù)據(jù)庫(kù)中仍舊能看到此條數(shù)據(jù)記錄
使用場(chǎng)景:可以進(jìn)行數(shù)據(jù)恢復(fù)

4.4.2 實(shí)現(xiàn)邏輯刪除

  • 數(shù)據(jù)庫(kù)中創(chuàng)建邏輯刪除狀態(tài)列,設(shè)置默認(rèn)值為0

  • 實(shí)體類中添加邏輯刪除屬性

  • //邏輯刪除@TableLogicprivate Integer isDeleted;
  • 測(cè)試
    • 測(cè)試刪除功能,真正執(zhí)行的是修改
      UPDATE t_user SET is_deleted=1 WHERE id=? AND is_deleted=0
    • 測(cè)試查詢功能,被邏輯刪除的數(shù)據(jù)默認(rèn)不會(huì)被查詢
      SELECT id,username AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0

    五、條件構(gòu)造器和常用接口

    5.1 wapper介紹

    5.2 QueryWrapper

    5.2.1 組裝查詢條件

    @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class MyBatisPlusWrapperTest {@Autowiredpublic UserMapper userMapper;@Testpublic void test01(){//查詢用戶名包含a,年齡在20到30之間,并且郵箱不為null的用戶信息QueryWrapper<User> queryWrapper = new QueryWrapper<>();//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)queryWrapper.like("user_name","a").between("age",20,30).isNotNull("email");List<User> userList = userMapper.selectList(queryWrapper);userList.forEach(System.out::println);}

    5.2.2 組裝排序條件

    @Testpublic void test02(){//按年齡降序查詢用戶,如果年齡相同則按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 ASCQueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.orderByDesc("age").orderByAsc("uid");List<User> userList = userMapper.selectList(queryWrapper);userList.forEach(System.out::println);}

    5.2.3 組裝刪除條件

    @Testpublic void test03(){//刪除email為空的用戶QueryWrapper<User> queryWrapper = new QueryWrapper<>();//UPDATE t_user SET is_deleted=1 WHERE is_deleted=0 AND (email IS NULL)//出現(xiàn)這個(gè)是因?yàn)槲覀冊(cè)O(shè)置了邏輯刪除,即刪除變成了修改,將狀態(tài)從0(未刪除狀態(tài))--->1(已刪除狀態(tài));queryWrapper.isNull("email");int result = userMapper.delete(queryWrapper);System.out.println("受影響的行數(shù) : " + result);}

    5.2.4 條件的優(yōu)先級(jí)

    /*** update(User entity,Wrapper<User> updateWrapper)* 第一個(gè)參數(shù)為修改的內(nèi)容,第二個(gè)參數(shù)為設(shè)置修改的條件參數(shù)1設(shè)置修改的字段和值,參數(shù)2是查詢符合的條件**/@Testpublic void test04(){//條件包裝器中條件之間默認(rèn)是and連接。我們不需要手動(dòng)設(shè)置,但是如果是或,我們需要手動(dòng)設(shè)置or.//將(年齡大于20并且用戶名中包含有a)或郵箱為null的用戶信息修改QueryWrapper<User> queryWrapper = new QueryWrapper<>();//UPDATE t_user SET user_name=?, age=?, email=? WHERE is_deleted=0 AND (user_name LIKE ? AND age > ? OR email IS NULL)queryWrapper.like("user_name","a").gt("age",20).or().isNull("email");User user = new User();user.setName("小明");user.setEmail("test@atguigu.com");int result = userMapper.update(user, queryWrapper);System.out.println("受影響的行數(shù):" + result);} @Testpublic void test05(){//將(年齡大于20或郵箱為null)并且用戶名中包含有a的用戶信息修改//lambda表達(dá)式內(nèi)的邏輯優(yōu)先運(yùn)算QueryWrapper<User> queryWrapper = new QueryWrapper<>();//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 > ? OR email IS NULL))queryWrapper.like("user_name","a").and(i ->i.gt("age",20).or().isNull("email"));List<User> userList = userMapper.selectList(queryWrapper);userList.forEach(System.out::println);}

    5.2.5 組裝select子句

    @Testpublic void test06(){//查詢用戶信息的username和age字段QueryWrapper<User> queryWrapper = new QueryWrapper<>();//SELECT user_name,age FROM t_user WHERE is_deleted=0queryWrapper.select("user_name","age");List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);maps.forEach(System.out::println);}

    5.2.6 實(shí)現(xiàn)子查詢

    @Testpublic void test07(){//查詢id小于等于3的用戶信息QueryWrapper<User> queryWrapper = new QueryWrapper<>();//SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND (uid IN (select uid from t_user where uid <= 3))queryWrapper.inSql("uid","select uid from t_user where uid <= 3");List<User> userList = userMapper.selectList(queryWrapper);userList.forEach(System.out::println);}

    5.3 UpdateWrapper

    @Testpublic void test08(){//將用戶名中包含有a并且(年齡大于20或郵箱為null)的用戶信息修改// 組裝set子句以及修改條件UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();/*寫在一起updateWrapper.set("age",18).set("email","user@atguigu.com").like("user_name","a").and(i ->i.gt("age",20).or().isNull("email"));*///分開寫//UPDATE t_user SET user_name=?,email=? WHERE is_deleted=0 AND (user_name LIKE ? AND (age > ? OR email IS NULL))updateWrapper.like("user_name","a").and(i ->i.gt("age",20).or().isNull("email"));updateWrapper.set("user_name","小黑").set("email","abc@atguigu.xom");//這里必須要?jiǎng)?chuàng)建User對(duì)象,否則無法應(yīng)用自動(dòng)填充。如果沒有自動(dòng)填充,可以設(shè)置為null//UPDATE t_user SET username=?, age=?,email=? WHERE (username LIKE ? AND(age > ? OR email IS NULL))//User user = new User();//user.setName("張三");//int result = userMapper.update(user, updateWrapper);//UPDATE t_user SET age=?,email=? WHERE (username LIKE ? AND (age > ? ORemail IS NULL))int result = userMapper.update(null, updateWrapper);System.out.println("result = " + result);}

    5.4 condition

    在真正開發(fā)的過程中,組裝條件是常見的功能,而這些條件數(shù)據(jù)來源于用戶輸入,是可選的,因此我們?cè)诮M裝這些條件時(shí),必須先判斷用戶是否選擇了這些條件,若選擇則需要組裝該條件,若沒有選擇則一定不能組裝,以免影響SQL執(zhí)行的結(jié)果。

    思路一:

    @Testpublic void test09(){//定義查詢條件,有可能為null(用戶未輸入或未選擇)String username = null;Integer ageBegin = 20;Integer ageEnd = 30;QueryWrapper<User> queryWrapper = new QueryWrapper<>();//SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND (age >= ? AND age <= ?)//StringUtils.isNotBlank()判斷某字符串是否不為空且長(zhǎng)度不為0且不由空白符(whitespace)構(gòu)成if(StringUtils.isNotBlank(username)){queryWrapper.like("user_name","a");}if (ageBegin != null){queryWrapper.ge("age",ageBegin);}if (ageEnd != null){queryWrapper.le("age",ageEnd);}List<User> list = userMapper.selectList(queryWrapper);list.forEach(System.out::println);}

    思路2:

    上面的實(shí)現(xiàn)方案沒有問題,但是代碼比較復(fù)雜,我們可以使用帶condition參數(shù)的重載方法構(gòu)建查詢條件,簡(jiǎn)化代碼的編寫

    @Testpublic void test10(){String username = "a";Integer ageBegin = null;Integer ageEnd = 30;QueryWrapper<User> queryWrapper = new QueryWrapper<>();//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 <= ?)queryWrapper.like(StringUtils.isNotBlank(username),"user_name","a").ge(ageBegin != null,"age",ageBegin).le(ageEnd != null,"age",ageEnd);List<User> list = userMapper.selectList(queryWrapper);list.forEach(System.out::println);}

    5.5 LambdaQueryWrapper

    @Testpublic void test11(){String username = "a";Integer ageBegin = null;Integer ageEnd = 30;LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();//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 <= ?)queryWrapper.like(StringUtils.isNotBlank(username),User::getName,"a").ge(ageBegin != null,User::getAge,ageBegin).le(ageEnd != null,User::getAge,ageEnd);List<User> list = userMapper.selectList(queryWrapper);list.forEach(System.out::println);}

    5.6 LambdaUpdateWrapper

    @Testpublic void test12(){//將用戶名中包含有a并且(年齡大于20或郵箱為null)的用戶信息修改// 組裝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));*///分開寫updateWrapper.like(User::getName, "a").and(i -> i.lt(User::getAge, 24).or().isNull(User::getEmail));updateWrapper.set(User::getName,"小黑").set(User::getEmail,"abc@atguigu.com");User user = new User();int result = userMapper.update(user, updateWrapper);System.out.println("受影響的行數(shù):" + result);}

    六、插件

    6.1 分頁插件

    MyBatis Plus自帶分頁插件,只要簡(jiǎn)單的配置即可實(shí)現(xiàn)分頁功能。

    6.1.1 添加配置

    <!--使用mybatisplus--><bean id="mybatisSqlSessionFactoryBean" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"><!--指定mybatis配置文件--><property name="configLocation" value="classpath:mybatis-config.xml"/><!--指定mapper.xml--><property name="mapperLocations" value="classpath:mappers/*Mapper.xml"/><!--裝配數(shù)據(jù)源--><property name="dataSource" ref="dataSource"/><!--設(shè)置mybatisplus的全局配置,即表的前綴--><property name="globalConfig" ref="globalConfig"></property><!--配置插件--><property name="plugins"><array><ref bean="mybatisPlusInterceptor"></ref></array></property></bean><!--配置MyBatis-Plus插件--><bean id="mybatisPlusInterceptor" class="com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor"><property name="interceptors"><list><ref bean="paginationInnerInterceptor"></ref></list></property></bean><!--配置Mybatis-plus分頁插件的bean--><bean id="paginationInnerInterceptor" class="com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor"><!--設(shè)置數(shù)據(jù)庫(kù)類型--><property name="dbType" value="MYSQL"></property></bean>

    6.1.2 測(cè)試

    @Testpublic void testPage(){//設(shè)置分頁參數(shù)Page<User> page = new Page<>(2,3);userMapper.selectPage(page,null);List<User> list = page.getRecords();list.forEach(System.out::println);System.out.println("每頁顯示的條數(shù):"+page.getSize());System.out.println("總記錄數(shù):"+page.getTotal());System.out.println("總頁數(shù):"+page.getPages());System.out.println( "當(dāng)前頁:" + page.getCurrent());System.out.println("是否有下一頁:" + page.hasNext());System.out.println("是否有上一頁:" + page.hasPrevious());}

    測(cè)試結(jié)果:
    User(id=1, name=Jone, age=18, email=test1@baomidou.com, isDeleted=0) User(id=2,name=Jack, age=20, email=test2@baomidou.com, isDeleted=0) User(id=3, name=Tom,age=28, email=test3@baomidou.com, isDeleted=0) User(id=4, name=Sandy, age=21,email=test4@baomidou.com, isDeleted=0) User(id=5, name=Billie, age=24, email=test5@baomidou.com, isDeleted=0) 當(dāng)前頁:1 每頁顯示的條數(shù):5 總記錄數(shù):17 總頁數(shù):4 是否有上一
    頁:false 是否有下一頁:true

    6.2 xml自定義分頁

    6.2.1 UserMapper中定義接口方法

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

    6.2.2 UserMapper.xml中編寫SQL

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

    6.2.3 測(cè)試

    @Testpublic void testPageVo(){Page<User> page = new Page<>(1,5);//第一頁索引為1,不是0userMapper.selectPageVo(page,20);List<User> list = page.getRecords();list.forEach(System.out::println);System.out.println("每頁顯示的條數(shù):"+page.getSize());System.out.println("總記錄數(shù):"+page.getTotal());System.out.println("總頁數(shù):"+page.getPages());System.out.println( "當(dāng)前頁:" + page.getCurrent());System.out.println("是否有下一頁:" + page.hasNext());System.out.println("是否有上一頁:" + page.hasPrevious());}

    結(jié)果:
    User(id=3, name=Tom, age=28, email=test3@baomidou.com, isDeleted=null)
    User(id=4,name=Sandy, age=21,email=test4@baomidou.com, isDeleted=null) User(id=5, name=Billie,age=24, email=test5@baomidou.com, isDeleted=null) User(id=8,name=ybc1, age=21,email=null, isDeleted=null)
    User(id=9, name=ybc2, age=22,email=null, isDeleted=null)
    當(dāng)前頁:1 每頁顯示的條數(shù):5 總記錄數(shù):12 總頁數(shù):3 是否有上一頁:false 是否有下一頁:true

    6.3 樂觀鎖

    6.3.1 場(chǎng)景

    一件商品,成本價(jià)是80元,售價(jià)是100元。老板先是通知小李,說你去把商品價(jià)格增加50元。小李正在玩游戲,耽擱了一個(gè)小時(shí)。正好一個(gè)小時(shí)后,老板覺得商品價(jià)格增加到150元,價(jià)格太高,可能會(huì)影響銷量。又通知小王,你把商品價(jià)格降低30元。
    此時(shí),小李和小王同時(shí)操作商品后臺(tái)系統(tǒng)。小李操作的時(shí)候,系統(tǒng)先取出商品價(jià)格100元;小王也在操作,取出的商品價(jià)格也是100元。小李將價(jià)格加了50元,并將100+50=150元存入了數(shù)據(jù)
    庫(kù);小王將商品減了30元,并將100-30=70元存入了數(shù)據(jù)庫(kù)。是的,如果沒有鎖,小李的操作就完全被小王的覆蓋了。
    現(xiàn)在商品價(jià)格是70元,比成本價(jià)低10元。幾分鐘后,這個(gè)商品很快出售了1千多件商品,老板虧1萬多。

    6.3.2 樂觀鎖與悲觀鎖

    上面的故事,如果是樂觀鎖,小王保存價(jià)格前,會(huì)檢查下價(jià)格是否被人修改過了。如果被修改過了,則重新取出的被修改后的價(jià)格,150元,這樣他會(huì)將120元存入數(shù)據(jù)庫(kù)。
    如果是悲觀鎖,小李取出數(shù)據(jù)后,小王只能等小李操作完之后,才能對(duì)價(jià)格進(jìn)行操作,也會(huì)保證最終的價(jià)格是120元。

    6.3.3 模擬修改沖突

    a>數(shù)據(jù)庫(kù)中增加商品表

    CREATE TABLE t_product ( id BIGINT(20) NOT NULL COMMENT '主鍵ID', NAME VARCHAR(30) NULL DEFAULT NULL COMMENT '商品名稱', price INT(11) DEFAULT 0 COMMENT '價(jià)格', VERSION INT(11) DEFAULT 0 COMMENT '樂觀鎖版本號(hào)', PRIMARY KEY (id) );

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

    INSERT INTO t_product (id, NAME, price) VALUES (1, '外星人筆記本', 100);

    c>添加實(shí)體

    */@Data public class Product {private Long id;private String name;private Integer price;}

    d>添加mapper

    public interface ProductMapper extends BaseMapper<Product> {}

    f>測(cè)試

    @Testpublic 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à)格+50productLi.setPrice(productLi.getPrice() + 50);productMapper.updateById(productLi);//小王將商品價(jià)格-30productWang.setPrice(productWang.getPrice() - 30);int result = productMapper.updateById(productWang);//老板查詢商品價(jià)格Product productBoss = productMapper.selectById(1);System.out.println("老板查詢的商品價(jià)格為:" + productBoss.getPrice());}

    6.3.4 樂觀鎖實(shí)現(xiàn)流程

    數(shù)據(jù)庫(kù)中添加version字段
    取出記錄時(shí),獲取當(dāng)前version

    SELECT id,`name`,price,`version` FROM product WHERE id=1

    更新時(shí),version + 1,如果where語句中的version版本不對(duì),則更新失敗

    UPDATE product SET price=price+50, `version`=`version` + 1 WHERE id=1 AND `version`=1

    6.3.5 Mybatis-Plus實(shí)現(xiàn)樂觀鎖

    [1]修改實(shí)體類

    */@Data public class Product {private Long id;private String name;private Integer price;@Versionprivate Integer version;}

    [2]添加樂觀鎖插件配置

    <!--配置MyBatis-Plus插件--><bean id="mybatisPlusInterceptor" class="com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor"><property name="interceptors"><list><ref bean="paginationInnerInterceptor"></ref><ref bean="optimisticLockerInnerInterceptor"></ref></list></property></bean><!--配置樂觀鎖插件--><bean id="optimisticLockerInnerInterceptor" class="com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor"></bean>

    [3] 測(cè)試修改沖突

    小李查詢商品信息:
    SELECT id,name,price,version FROM t_product WHERE id=?
    小王查詢商品信息:
    SELECT id,name,price,version FROM t_product WHERE id=?
    小李修改商品價(jià)格,自動(dòng)將version+1
    UPDATE t_product SET name=?, price=?, version=? WHERE id=? AND version=?
    Parameters: 外星人筆記本(String), 150(Integer), 1(Integer), 1(Long), 0(Integer)
    小王修改商品價(jià)格,此時(shí)version已更新,條件不成立,修改失敗
    UPDATE t_product SET name=?, price=?, version=? WHERE id=? AND version=?
    Parameters: 外星人筆記本(String), 70(Integer), 1(Integer), 1(Long), 0(Integer)
    最終,小王修改失敗,查詢價(jià)格:150
    SELECT id,name,price,version FROM t_product WHERE id=?

    [4]優(yōu)化流程

    @Testpublic 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à)格+50productLi.setPrice(productLi.getPrice() + 50);productMapper.updateById(productLi);//小王將商品價(jià)格-30productWang.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 productBoss = productMapper.selectById(1);System.out.println("老板查詢的商品價(jià)格為:" + productBoss.getPrice());}

    七 、通用枚舉

    表中的有些字段值是固定的,例如性別(男或女),此時(shí)我們可以使用MyBatis-Plus的通用枚舉來實(shí)現(xiàn)。

    7.1 數(shù)據(jù)庫(kù)添加字段sex

    7.2 創(chuàng)建通用枚舉

    */@Getter public enum SexEnum {MALE(1,"男"),FEMALE(2,"女");@EnumValue //將注解所標(biāo)識(shí)的屬性的值存儲(chǔ)到數(shù)據(jù)庫(kù)中private Integer sex;private String sexName;SexEnum(Integer sex, String sexName) {this.sex = sex;this.sexName = sexName;} }

    7.3 配置掃描通用枚舉

    <!--使用mybatisplus--><bean id="mybatisSqlSessionFactoryBean" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"><!--指定mybatis配置文件--><property name="configLocation" value="classpath:mybatis-config.xml"/><!--指定mapper.xml--><property name="mapperLocations" value="classpath:mappers/*Mapper.xml"/><!--裝配數(shù)據(jù)源--><property name="dataSource" ref="dataSource"/><!--設(shè)置mybatisplus的全局配置,即表的前綴--><property name="globalConfig" ref="globalConfig"></property><!--配置掃描通用枚舉--><property name="typeEnumsPackage" value="com.atguigu.mybatisplus.enums"></property><!--配置插件--><property name="plugins"><array><ref bean="mybatisPlusInterceptor"></ref></array></property></bean>

    7.4 測(cè)試

    @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class MyBatisPlusEnumTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testSexEnum(){User user = new User();user.setName("Enum");user.setAge(20);//設(shè)置性別信息為枚舉項(xiàng),會(huì)將@EnumValue注解所標(biāo)識(shí)的屬性值存儲(chǔ)到數(shù)據(jù)庫(kù)// INSERT INTO t_user ( user_name, age, sex, is_deleted ) VALUES ( ?, ?, ?, ? )user.setSex(SexEnum.MALE);userMapper.insert(user);}

    八、代碼生成器

    8.1 引入依賴

    <!--代碼生成器逆向工程依賴--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.5.1</version></dependency><!--代碼生成器中 freemarker引擎模板需要這個(gè)依賴--><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.31</version></dependency>

    8.2 快速生成

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

    九 、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/

    9.1 安裝插件

    安裝方法:打開 IDEA,進(jìn)入 File -> Settings -> Plugins -> Browse Repositories,輸入 mybatisx 搜索并安裝

    9.2 功能

    9.2.1 XML跳轉(zhuǎn)

    當(dāng)mapper映射文件和mapper很多的時(shí)候,可以快速定位并跳轉(zhuǎn)到對(duì)應(yīng)的類容上。

    9.2.2 快速生成代碼

    [1]首先需要在datasource中進(jìn)行配置

    [2] 選擇驅(qū)動(dòng)

    [3]可以直接選擇舊版本的驅(qū)動(dòng),或者按提示下載

    [4] 登錄后選擇數(shù)據(jù)庫(kù)、表,然后點(diǎn)擊右鍵選擇mybatisx。


    [5] 表的基本配置

    [6] 生成的基本配置

    [7]選擇好后會(huì)自動(dòng)幫我們生成各種組件

    [8]如果我們要自定義查詢功能,我們只需要在mapper中寫我們的方法名,插件會(huì)自動(dòng)幫助我們補(bǔ)全方法名并且快速生成相對(duì)應(yīng)的sql語句放在mapper映射文件中。

    十、總結(jié)

    mybatsi-plus可以快速幫助我們完成spring和mybatsi的整合及搭建功能。

    總結(jié)

    以上是生活随笔為你收集整理的MyBatis_Plus(Spring版本笔记)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。