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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Mybatis-Plus 详解 拉钩笔记

發布時間:2023/12/20 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Mybatis-Plus 详解 拉钩笔记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

1. Mybatis-Plus概念

1.1 Mybatis-Plus介紹

1.3 架構

1.4 作者

2. Mybatis-Plus快速??

2.1 安裝

2.2 創建數據庫以及表

2.3 創建?程

2.4 Mybatis + MP

2.5 Spring + Mybatis + MP

2.6 SpringBoot + Mybatis + MP

3. 通?CRUD

3.1 插?操作

3.2 更新操作

3.3 刪除操作

3.3.4、deleteBatchIds

3.4 查詢操作

3.4.1、selectById

3.4.2、selectBatchIds

3.4.3、selectOne

3.4.4、selectCount

3.4.5、selectList

3.4.6、selectPage

3.5 SQL注?的原理

4. 配置

4.1、基本配置

4.1.1、configLocation

4.1.2、mapperLocations

4.1.3、typeAliasesPackage ?

4.2、進階配置

4.2.1、mapUnderscoreToCamelCase

4.2.2、cacheEnabled

4.3、DB 策略配置

4.3.1、idType

4.3.2、tablePrefix

5. 條件構造器

5.1、allEq

5.1.1、說明

5.1.2、測試?例

5.2、基本?較操作

5.3、模糊查詢

5.4、排序

5.6、select

6. ActiveRecord

6.1、開啟AR之旅

6.3、新增數據

?編輯?

6.4、更新操作

?編輯

6.5、刪除操作

6.6、根據條件查詢

7. 插件

7.1、mybatis的插件機制

7.2、執?分析插件

7.3、性能分析插件

7.4、樂觀鎖插件

7.4.1、主要適?場景

7.4.2、插件配置

7.4.3、注解實體字段

7.4.4、測試

7.4.5、特別說明

8. Sql 注?器

8.1、編寫MyBaseMapper

8.2、編寫MySqlInjector

8.3、編寫FindAll

8.4、注冊到Spring容器

8.5、測試

9. ?動填充功能

9.1、添加@TableField注解

9.2、編寫MyMetaObjectHandler

9.3、測試

10. 邏輯刪除

10.1、修改表結構

10.2、配置

10.3、測試

11. 代碼?成器

11.1、創建?程

11.2、代碼

11.3、測試

12. MybatisX 快速開發插件


1. Mybatis-Plus概念

1.1 Mybatis-Plus介紹

官?: https://mybatis.plus/ https://mp.baomidou.com/ Mybatis-Plus介紹 MyBatis-Plus(簡稱 MP)是?個 MyBatis 的增強?具,在 MyBatis 的基礎上只做增強不做改變,-為簡化開發、提?效率??。

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

1.2 特性

  • ?侵?:只做增強不做改變,引?它不會對現有?程產?影響,如絲般順滑
  • 損耗?:啟動即會?動注?基本 CURD,性能基本?損耗,直接?向對象操作
  • 強?的 CRUD 操作:內置通? Mapper、通? Service,僅僅通過少量配置即可實現單表?部分CRUD 操作,更有強?的條件構造器,滿?各類使?需求
  • ?持 Lambda 形式調?:通過 Lambda 表達式,?便的編寫各類查詢條件,?需再擔?字段寫錯
  • ?持主鍵?動?成:?持多達 4 種主鍵策略(內含分布式唯? ID ?成器 - Sequence),可?由配置,完美解決主鍵問題
  • ?持 ActiveRecord 模式:?持 ActiveRecord 形式調?,實體類只需繼承 Model 類即可進?強?的 CRUD 操作
  • ?持?定義全局通?操作:?持全局通??法注?( Write once, use anywhere
  • 內置代碼?成器:采?代碼或者 Maven 插件可快速?成 Mapper Model Service Controller 層代碼,?持模板引擎,更有超多?定義配置等您來使?
  • 內置分?插件:基于 MyBatis 物理分?,開發者?需關?具體操作,配置好插件之后,寫分?等同于普通 List 查詢
  • 分?插件?持多種數據庫:?持 MySQLMariaDBOracleDB2H2HSQLSQLitePostgreSQLServer 等多種數據庫
  • 內置性能分析插件:可輸出 Sql 語句以及其執?時間,建議開發測試時啟?該功能,能快速揪出慢查詢
  • 內置全局攔截插件:提供全表 delete update 操作智能分析阻斷,也可?定義攔截規則,預防誤操作

1.3 架構

1.4 作者

Mybatis-Plus是由baomidou(苞??)組織開發并且開源的,?前該組織?概有30?左右。 碼云地址:https://gitee.com/organizations/baomidou

2. Mybatis-Plus快速??

2.1 安裝

全新的 MyBatis-Plus 3.0 版本基于 JDK8,提供了 lambda 形式的調?,所以安裝集成 MP3.0 要求 如下:
  • JDK 8+
  • Maven or Gradle
Release Spring Boot Maven <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.0</version> </dependency> Spring MVC Maven: <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus</artifactId><version>3.4.0</version> </dependency> 對于Mybatis整合MP有常常有三種?法,分別是Mybatis+MPSpring+Mybatis+MPSpring Boot+Mybatis+MP

2.2 創建數據庫以及表

創建User表,其表結構如下:

-- 創建測試表 DROP TABLE IF EXISTS tb_user; CREATE TABLE user (id BIGINT(20) NOT NULL COMMENT '主鍵ID',name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',age INT(11) NULL DEFAULT NULL COMMENT '年齡',email VARCHAR(50) NULL DEFAULT NULL COMMENT '郵箱',PRIMARY KEY (id) ); -- 插?測試數據 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 創建?程

?導?依賴:

<dependencies><!-- mybatis-plus插件依賴 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus</artifactId><version>3.1.1</version></dependency><!--Mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency><!--連接池--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.0.11</version></dependency><!--簡化bean代碼的?具包--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.4</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.6.4</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target></configuration></plugin></plugins></build>

2.4 Mybatis + MP

下?演示,通過純MybatisMybatis-Plus整合。 創建?Module <?xml version="1.0" encoding="UTF-8" ?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>lagou-mybatis-plus</artifactId><groupId>com.lagou.mp</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>lagou-mybatis-plus-simple</artifactId> </project> log4j.properties log4j.rootLogger=DEBUG,A1 log4j.appender.A1=org.apache.log4j.ConsoleAppender log4j.appender.A1.layout=org.apache.log4j.PatternLayout log4j.appender.A1.layout.ConversionPattern=[%t] [%c]-[%p] %m%n Mybatis實現查詢User 第?步,編寫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><properties resource="jdbc.properties"></properties><!--environments: 運?環境--><environments default="development"><environment id="development"><!--當前的事務事務管理器是JDBC--><transactionManager type="JDBC"></transactionManager><!--數據源信息 POOLED:使?mybatis的連接池--><dataSource type="POOLED"><property name="driver" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment></environments><!--引?映射配置?件--><mappers><mapper resource="mapper/UserMapper.xml"></mapper></mappers> </configuration> 第?步,編寫User實體對象:(這?使?lombok進?了進化bean操作) @Data // getter setter @toString @NoArgsConstructor @AllArgsConstructor public class User {private Long id;private String name;private Integer age;private String email; } 第三步,編寫UserMapper接?: public interface UserMapper {List<User> findAll(); } 第四步,編寫UserMapper.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.lagou.mapper.UserMapper"><!-- 查詢所有 --><select id="findAll" resultType="com.lagou.pojo.User">select * from user</select> </mapper> 第五步,編寫TestMybatis測試?例: public class MPTest {@Testpublic void test1() throws IOException {InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);List<User> all = mapper.findAll();for (User user : all) {System.out.println(user);}} } 測試結果: User(id=1, name=Jone, age=18, email=test1@baomidou.com) User(id=2, name=Jack, age=20, email=test2@baomidou.com) User(id=3, name=Tom, age=28, email=test3@baomidou.com) User(id=4, name=Sandy, age=21, email=test4@baomidou.com) User(id=5, name=Billie, age=24, email=test5@baomidou.com) 注:如果實體類名稱和表名稱不?致,可以在實體類上添加注解@TableName("指定數據庫表名") Mybatis+MP實現查詢User 第?步,將UserMapper繼承BaseMapper,將擁有了BaseMapper中的所有?法: import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.lagou.pojo.User; public interface UserMapper extends BaseMapper<User> { } 第?步,使?MP中的MybatisSqlSessionFactoryBuilder進程構建: @Test public void test2() throws IOException {InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");//這?使?的是MP中的MybatisSqlSessionFactoryBuilderSqlSessionFactory sqlSessionFactory = new MybatisSqlSessionFactoryBuilder().build(resourceAsStream);SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);// 可以調?BaseMapper中定義的?法List<User> all = mapper.selectList(null);for (User user : all) {System.out.println(user);} } 測試: User(id=1, name=Jone, age=18, email=test1@baomidou.com) User(id=2, name=Jack, age=20, email=test2@baomidou.com) User(id=3, name=Tom, age=28, email=test3@baomidou.com) User(id=4, name=Sandy, age=21, email=test4@baomidou.com) User(id=5, name=Billie, age=24, email=test5@baomidou.com) 注:如果實體類名稱和表名稱不?致,可以在實體類上添加注解@TableName("指定數據庫表名") 簡單說明:
  • 由于使?了 MybatisSqlSessionFactoryBuilder進?了構建,繼承的BaseMapper中的?法就載?到了SqlSession中,所以就可以直接使?相關的?法;
  • 如圖

2.5 Spring + Mybatis + MP

引?了Spring框架,數據源、構建等?作就交給了Spring管理。 創建?Module <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>lagou-mybatis-plus</artifactId><groupId>com.lagou.mp</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>lagou-mybatis-plus-spring</artifactId><properties><spring.version>5.1.6.RELEASE</spring.version></properties><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</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></dependencies> 實現查詢User 第?步,編寫jdbc.properties jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://127.0.0.1:3306/mp?serverTimezone=GMT%2B8&useSSL=false jdbc.username=root jdbc.password=root 第?步,編寫applicationContext.xml <?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/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!--引?properties--><context:property-placeholder location="classpath:jdbc.properties"/><!--dataSource--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean><!--這?使?MP提供的sqlSessionFactory,完成spring與mp的整合--><bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean" ><property name="dataSource" ref="dataSource"/></bean><!--掃描mapper接?,使?的依然是mybatis原?的掃描器--><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.lagou.mapper"/></bean> </beans> 第三步,編寫User對象以及UserMapper接?: @Data @NoArgsConstructor @AllArgsConstructor public class User {private Long id;private String name;private Integer age;private String email; } public interface UserMapper extends BaseMapper<User> {List<User> findAll(); } 第四步,編寫測試?例: @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:applicationContext.xml") public class TestSpringMP {@Autowiredprivate UserMapper userMapper;@Testpublic void test2() throws IOException {List<User> users = this.userMapper.selectList(null);for (User user : users) {System.out.println(user);}}

2.6 SpringBoot + Mybatis + MP

使?SpringBoot將進?步的簡化MP的整合,需要注意的是,由于使?SpringBoot需要繼承parent,所以需要重新創建?程,并不是創建?Module 創建?程

導?依賴 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--簡化代碼的?具包--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!--mybatis-plus的springboot?持--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.1.1</version></dependency><!--mysql驅動--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build> log4j.properties log4j.rootLogger=DEBUG,A1 log4j.appender.A1=org.apache.log4j.ConsoleAppender log4j.appender.A1.layout=org.apache.log4j.PatternLayout log4j.appender.A1.layout.ConversionPattern=[%t] [%c]-[%p] %m%n

編寫application.properties

spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mp? useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=tr ue&useSSL=false spring.datasource.username=root spring.datasource.password=root

編寫pojo

@Data @NoArgsConstructor @AllArgsConstructor public class User {private Long id;private String name;private Integer age;private String email; } 編寫mapper public interface UserMapper extends BaseMapper<User> { } 編寫啟動類 package com.lagou.mp; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; @MapperScan("com.lagou.mp.mapper") //設置mapper接?的掃描包 @SpringBootApplication public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);} }

編寫測試?例

package com.lagou.mp; import com.lagou.mp.mapper.UserMapper; import com.lagou.mp.pojo.User; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testSelect() {List<User> userList = userMapper.selectList(null);for (User user : userList) {System.out.println(user);}} } 測試: User(id=1, name=Jone, age=18, email=test1@baomidou.com) User(id=2, name=Jack, age=20, email=test2@baomidou.com) User(id=3, name=Tom, age=28, email=test3@baomidou.com) User(id=4, name=Sandy, age=21, email=test4@baomidou.com) User(id=5, name=Billie, age=24, email=test5@baomidou.com)

3. 通?CRUD

通過前?的學習,我們了解到通過繼承BaseMapper就可以獲取到各種各樣的單表操作,接下來我們將詳細講解這些操作。

3.1 插?操作

?法定義 /*** 插??條記錄** @param entity 實體對象.*/int insert(T entity); 測試?例 @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testInsert(){User user = new User();user.setAge(18);user.setEmail("test@lagou.cn");user.setName("?慕");//返回的result是受影響的?數,并不是?增后的idint result = userMapper.insert(user);System.out.println(result);System.out.println(user.getId());} } 測試 1 1318744682116739074 可以看到,數據已經寫?到了數據庫,但是,id的值不正確,我們期望的是數據庫?增?,實際是MP? 成了id的值寫?到了數據庫。 如何設置id的?成策略呢? MP?持的id策略: package com.baomidou.mybatisplus.annotation; import lombok.Getter; /** * ?成ID類型枚舉類 * * @author hubin * @since 2015-11-10 */ @Getter public enum IdType {/*** 數據庫ID?增*/AUTO(0),/*** 該類型為未設置主鍵類型*/NONE(1),/*** ?戶輸?ID* <p>該類型可以通過??注冊?動填充插件進?填充</p>*/INPUT(2),/* 以下3種類型、只有當插?對象ID 為空,才?動填充。 *//*** 全局唯?ID (idWorker)*/ID_WORKER(3),/*** 全局唯?ID (UUID)*/UUID(4),/*** 字符串全局唯?ID (idWorker 的字符串表示)*/ID_WORKER_STR(5);private final int key;IdType(int key) {this.key = key;} }

修改User對象: package com.lagou.mp.pojo; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor @TableName("tb_user") public class User {@TableId(type = IdType.AUTO) //指定id類型為?增?private Long id;private String userName;private String password;private String name;private Integer age;private String email; } 數據插?成功:

@TableField MP中通過@TableField注解可以指定字段的?些屬性,常常解決的問題有2個: 1、對象中的屬性名和字段名不?致的問題(?駝峰) 2、對象中的屬性字段在表中不存在的問題 使?:

?其他?法,如?字段不加?查詢字段:

?效果:

3.2 更新操作

MP中,更新操作有2種,?種是根據id更新,另?種是根據條件更新。 根據id更新 ?法定義: /*** 根據 ID 修改** @param entity 實體對象*/int updateById(@Param(Constants.ENTITY) T entity); 測試: @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testUpdateById() {User user = new User();user.setId(6L); //主鍵user.setAge(21); //更新的字段//根據id更新,更新不為null的字段this.userMapper.updateById(user);} } 結果:

根據條件更新 ?法定義: /*** 根據 whereEntity 條件,更新記錄** @param entity 實體對象 (set 條件值,可以為 null)* @param updateWrapper 實體對象封裝操作類(可以為 null,??的 entity ?于?成 where 語句)*/int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper); 測試?例: package com.lagou.mp; import com.lagou.mp.mapper.UserMapper; import com.lagou.mp.pojo.User; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import net.minidev.json.writer.UpdaterMapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testUpdate() {User user = new User();user.setAge(22); //更新的字段//更新的條件QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.eq("id", 6);//執?更新操作int result = this.userMapper.update(user, wrapper);System.out.println("result = " + result);} } 或者,通過UpdateWrapper進?更新: @Testpublic void testUpdate() {//更新的條件以及字段UpdateWrapper<User> wrapper = new UpdateWrapper<>();wrapper.eq("id", 6).set("age", 23);//執?更新操作int result = this.userMapper.update(null, wrapper);System.out.println("result = " + result);} 測試結果: [main] [com.lagou.mp.mapper.UserMapper.update]-[DEBUG] ==> Preparing: UPDATE tb_user SET age=? WHERE id = ? [main] [com.lagou.mp.mapper.UserMapper.update]-[DEBUG] ==> Parameters: 23(Integer), 6(Integer) [main] [com.lagou.mp.mapper.UserMapper.update]-[DEBUG] <== Updates: 1 均可達到更新的效果。 關于wrapper更多的?法后?會詳細講解。

3.3 刪除操作

deleteById ?法定義: /** * 根據 ID 刪除 * * @param id 主鍵ID */ int deleteById(Serializable id); 測試?例: package com.lagou.mp; import com.lagou.mp.mapper.UserMapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testDeleteById() {//執?刪除操作int result = this.userMapper.deleteById(6L);System.out.println("result = " + result);} }

結果:

[main] [com.lagou.mp.mapper.UserMapper.deleteById]-[DEBUG] ==> Preparing: DELETE FROM tb_user WHERE id=? [main] [com.lagou.mp.mapper.UserMapper.deleteById]-[DEBUG] ==> Parameters: 6(Long) [main] [com.lagou.mp.mapper.UserMapper.deleteById]-[DEBUG] <== Updates: 1 數據被刪除。 deleteByMap ?法定義: /*** 根據 columnMap 條件,刪除記錄** @param columnMap 表字段 map 對象*/int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap); 測試?例: package com.lagou.mp; import com.lagou.mp.mapper.UserMapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.HashMap; import java.util.Map; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testDeleteByMap() {Map<String, Object> columnMap = new HashMap<>();columnMap.put("age",21);columnMap.put("name","?慕");//將columnMap中的元素設置為刪除的條件,多個之間為and關系int result = this.userMapper.deleteByMap(columnMap);System.out.println("result = " + result);} }

結果:

[main] [com.lagou.mp.mapper.UserMapper.deleteByMap]-[DEBUG] ==> Preparing: DELETE FROM tb_user WHERE name = ? AND age = ? [main] [com.lagou.mp.mapper.UserMapper.deleteByMap]-[DEBUG] ==> Parameters: ? (String), 21(Integer) [main] [com.lagou.mp.mapper.UserMapper.deleteByMap]-[DEBUG] <== Updates: 0 delete ?法定義: /** * 根據 entity 條件,刪除記錄 * * @param wrapper 實體對象封裝操作類(可以為 null) */ int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper); 測試?例: package com.lagou.mp; import com.lagou.mp.mapper.UserMapper; import com.lagou.mp.pojo.User; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.junit.Test; 結果: 3.3.4、deleteBatchIds ?法定義: import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.HashMap; import java.util.Map; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testDeleteByMap() {User user = new User();user.setAge(20);user.setName("?慕");//將實體對象進?包裝,包裝為操作條件QueryWrapper<User> wrapper = new QueryWrapper<>(user);int result = this.userMapper.delete(wrapper);System.out.println("result = " + result);} }

結果:

[main] [com.lagou.mp.mapper.UserMapper.delete]-[DEBUG] ==> Preparing: DELETE FROM tb_user WHERE name=? AND age=? [main] [com.lagou.mp.mapper.UserMapper.delete]-[DEBUG] ==> Parameters: ?慕 (String), 20(Integer) [main] [com.lagou.mp.mapper.UserMapper.delete]-[DEBUG] <== Updates: 0

3.3.4deleteBatchIds

?法定義: /*** 刪除(根據ID 批量刪除)** @param idList 主鍵ID列表(不能為 null 以及 empty)*/int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList); 測試?例: package com.lagou.mp; import com.lagou.mp.mapper.UserMapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.Arrays; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testDeleteByMap() {//根據id集合批量刪除int result = this.userMapper.deleteBatchIds(Arrays.asList(1L,10L,20L));System.out.println("result = " + result);} } 結果: [main] [com.lagou.mp.mapper.UserMapper.deleteBatchIds]-[DEBUG] ==> Preparing: DELETE FROM tb_user WHERE id IN ( ? , ? , ? ) [main] [com.lagou.mp.mapper.UserMapper.deleteBatchIds]-[DEBUG] ==> Parameters: 1(Long), 10(Long), 20(Long) [main] [com.lagou.mp.mapper.UserMapper.deleteBatchIds]-[DEBUG] <== Updates: 1

3.4 查詢操作

MP提供了多種查詢操作,包括根據id查詢、批量查詢、查詢單條數據、查詢列表、分?查詢等操作。

3.4.1selectById

?法定義: /*** 根據 ID 查詢** @param id 主鍵ID*/T selectById(Serializable id); 測試?例: package com.lagou.mp; import com.lagou.mp.mapper.UserMapper; import com.lagou.mp.pojo.User; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testSelectById() {//根據id查詢數據User user = this.userMapper.selectById(2L);System.out.println("result = " + user);} } 結果: result = User(id=2, name=Jack, age=20, email=test2@baomidou.com)

3.4.2selectBatchIds

?法定義: /** * 查詢(根據ID 批量查詢) * * @param idList 主鍵ID列表(不能為 null 以及 empty) */ List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList); 測試?例: package com.lagou.mp; import com.lagou.mp.mapper.UserMapper; import com.lagou.mp.pojo.User; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.Arrays; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testSelectBatchIds() {//根據id集合批量查詢List<User> users = this.userMapper.selectBatchIds(Arrays.asList(2L, 3L, 10L));for (User user : users) {System.out.println(user);}} } 結果: User(id=2, name=Jack, age=20, email=test2@baomidou.com) User(id=3, name=Tom, age=28, email=test3@baomidou.com)

3.4.3selectOne

?法定義: /** * 根據 entity 條件,查詢?條記錄 * * @param queryWrapper 實體對象封裝操作類(可以為 null) */ T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); 測試?例: package com.lagou.mp; import com.lagou.mp.mapper.UserMapper; import com.lagou.mp.pojo.User; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testSelectOne() {QueryWrapper<User> wrapper = new QueryWrapper<User>();wrapper.eq("name", "jack");//根據條件查詢?條數據,如果結果超過?條會報錯User user = this.userMapper.selectOne(wrapper);System.out.println(user);} } 結果: User(id=2, name=Jack, age=20, email=test2@baomidou.com)

3.4.4selectCount

?法定義: /** * 根據 Wrapper 條件,查詢總記錄數 * * @param queryWrapper 實體對象封裝操作類(可以為 null) */ Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); 測試?例: package com.lagou.mp; import com.lagou.mp.mapper.UserMapper; import com.lagou.mp.pojo.User; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testSelectCount() {QueryWrapper<User> wrapper = new QueryWrapper<User>();wrapper.gt("age", 23); //年齡?于23歲//根據條件查詢數據條數Integer count = this.userMapper.selectCount(wrapper);System.out.println("count = " + count);} } 結果: count = 2

3.4.5selectList

?法定義: /** * 根據 entity 條件,查詢全部記錄 * * @param queryWrapper 實體對象封裝操作類(可以為 null) */ List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); 測試?例: package com.lagou.mp; import com.lagou.mp.mapper.UserMapper; import com.lagou.mp.pojo.User; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testSelectList() {QueryWrapper<User> wrapper = new QueryWrapper<User>();wrapper.gt("age", 23); //年齡?于23歲//根據條件查詢數據List<User> users = this.userMapper.selectList(wrapper);for (User user : users) {System.out.println("user = " + user);}} } 結果: user = User(id=3, name=Tom, age=28, email=test3@baomidou.com) user = User(id=5, name=Billie, age=24, email=test5@baomidou.com)

3.4.6selectPage

?法定義: /** * 根據 entity 條件,查詢全部記錄(并翻?) * * @param page 分?查詢條件(可以為 RowBounds.DEFAULT) * @param queryWrapper 實體對象封裝操作類(可以為 null) */ IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper); 配置分?插件: package com.lagou.mp; import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @MapperScan("com.lagou.mp.mapper") //設置mapper接?的掃描包 public class MybatisPlusConfig {/*** 分?插件*/@Beanpublic PaginationInterceptor paginationInterceptor() {return new PaginationInterceptor();} } 測試?例: package com.lagou.mp; import com.lagou.mp.mapper.UserMapper; import com.lagou.mp.pojo.User; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testSelectPage() {QueryWrapper<User> wrapper = new QueryWrapper<User>();wrapper.gt("age", 20); //年齡?于20歲Page<User> page = new Page<>(1,1);//根據條件查詢數據IPage<User> iPage = this.userMapper.selectPage(page, wrapper);System.out.println("數據總條數:" + iPage.getTotal());System.out.println("總?數:" + iPage.getPages());List<User> users = iPage.getRecords();for (User user : users) {System.out.println("user = " + user);}} }

結果:

數據總條數:4 總?數:4 user = User(id=3, name=Tom, age=28, email=test3@baomidou.com)

3.5 SQL注?的原理

前?我們已經知道,MP在啟動后會將BaseMapper中的?系列的?法注冊到meppedStatements中, 那么究竟是如何注?的呢?流程?是怎么樣的?下?我們將?起來分析下。 MP中,ISqlInjector負責SQL的注??作,它是?個接?,AbstractSqlInjector是它的實現類,實現關系如下:

AbstractSqlInjector中,主要是由inspectInject()?法進?注?的,如下: @Override public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) {Class<?> modelClass = extractModelClass(mapperClass);if (modelClass != null) {String className = mapperClass.toString();Set<String> mapperRegistryCache = GlobalConfigUtils.getMapperRegistryCache(builderAssistant.getConfiguration());if (!mapperRegistryCache.contains(className)) {List<AbstractMethod> methodList = this.getMethodList();if (CollectionUtils.isNotEmpty(methodList)) {TableInfo tableInfo = TableInfoHelper.initTableInfo(builderAssistant, modelClass);// 循環注??定義?法methodList.forEach(m -> m.inject(builderAssistant, mapperClass, modelClass, tableInfo));} else {logger.debug(mapperClass.toString() + ", No effective injection method was found.");}mapperRegistryCache.add(className);}} } 在實現?法中, methodList.forEach(m -> m.inject(builderAssistant, mapperClass, modelClass, tableInfo)); 是關鍵,循環遍歷?法,進?注?。 最終調?抽象?法injectMappedStatement進?真正的注?: /*** 注??定義 MappedStatement** @param mapperClass mapper 接?* @param modelClass mapper 泛型* @param tableInfo 數據庫表反射信息* @return MappedStatement*/public abstract MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo); 查看該?法的實現:

SelectById為例查看: public class SelectById extends AbstractMethod {@Overridepublic MappedStatement injectMappedStatement(Class<?> mapperClass, Class<? > modelClass, TableInfo tableInfo) {SqlMethod sqlMethod = SqlMethod.LOGIC_SELECT_BY_ID;SqlSource sqlSource = new RawSqlSource(configuration, String.format(sqlMethod.getSql(),sqlSelectColumns(tableInfo, false),tableInfo.getTableName(), tableInfo.getKeyColumn(), tableInfo.getKeyProperty(),tableInfo.getLogicDeleteSql(true, false)), Object.class);return this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, modelClass, tableInfo);} } 可以看到,?成了SqlSource對象,再將SQL通過addSelectMappedStatement?法添加到meppedStatements中。

4. 配置

MP中有?量的配置,其中有?部分是Mybatis原?的配置,另?部分是MP的配置,詳情:https://m ybatis.plus/config/ 下?我們對常?的配置做講解。

4.1、基本配置

4.1.1configLocation

MyBatis 配置?件位置,如果有單獨的 MyBatis 配置,請將其路徑配置到 configLocation 中。 MyBatis Configuration 的具體內容請參考MyBatis 官??檔 Spring Boot mybatis-plus.config-location = classpath:mybatis-config.xml

Spring MVC

<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean" ><property name="configLocation" value="classpath:mybatis-config.xml"/> </bean>

4.1.2mapperLocations

MyBatis Mapper 所對應的 XML ?件位置,如果您在 Mapper 中有?定義?法(XML 中有?定義實現),需要進?該配置,告訴 Mapper 所對應的 XML ?件位置。 Spring Boot mybatis-plus.mapper-locations = classpath*:mybatis/*.xml Spring MVC <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean" ><property name="mapperLocations" value="classpath*:mybatis/*.xml"/> </bean> Maven 多模塊項?的掃描路徑需以 classpath*: 開頭 (即加載多個 jar 包下的 XML ?件) 測試: UserMapper.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.lagou.mp.mapper.UserMapper"><select id="findById" resultType="com.lagou.mp.pojo.User">select * from tb_user where id = #{id}</select> </mapper> package com.lagou.mp.mapper; import com.lagou.mp.pojo.User; import com.baomidou.mybatisplus.core.mapper.BaseMapper; public interface UserMapper extends BaseMapper<User> {User findById(Long id); } 測試?例: package com.lagou.mp; import com.lagou.mp.mapper.UserMapper; import com.lagou.mp.pojo.User; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testSelectPage() {User user = this.userMapper.findById(2L);System.out.println(user);} } 運?結果:

4.1.3typeAliasesPackage ?

MyBaits 別名包掃描路徑,通過該屬性可以給包中的類注冊別名,注冊后在 Mapper 對應的 XML ?件中可以直接使?類名,?不?使?全限定的類名(即 XML 中調?的時候不?包含包名)。 Spring Boot mybatis-plus.type-aliases-package = com.lagou.mp.pojo Spring MVC <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean" ><property name="typeAliasesPackage" value="com.baomidou.mybatisplus.samples.quickstart.entity"/> </bean>

4.2、進階配置

本部分(Configuration)的配置?都為 MyBatis 原??持的配置,這意味著您可以通過 MyBatis XML配置?件的形式進?配置。

4.2.1mapUnderscoreToCamelCase

  • 類型: boolean
  • 默認值: true
是否開啟?動駝峰命名規則(camel case)映射,即從經典數據庫列名 A_COLUMN(下劃線命名) 到經典 Java 屬性名 aColumn(駝峰命名) 的類似映射。 注意: 此屬性在 MyBatis 中原默認值為 false,在 MyBatis-Plus 中,此屬性也將?于?成最終的 SQL 的select body 如果您的數據庫命名符合規則?需使? @TableField 注解指定數據庫字段名 示例(SpringBoot): ? #關閉?動駝峰映射,該參數不能和mybatis-plus.config-location同時存在 mybatis-plus.configuration.map-underscore-to-camel-case=false

4.2.2cacheEnabled

  • 類型: boolean
  • 默認值: true
全局地開啟或關閉配置?件中的所有映射器已經配置的任何緩存,默認為 true 示例: mybatis-plus.configuration.cache-enabled=false

4.3DB 策略配置

4.3.1idType

  • 類型: com.baomidou.mybatisplus.annotation.IdType
  • 默認值: ID_WORKER
全局默認主鍵類型,設置后,即可省略實體對象中的@TableId(type = IdType.AUTO)配置。 示例: SpringBoot mybatis-plus.global-config.db-config.id-type=auto SpringMVC <!--這?使?MP提供的sqlSessionFactory,完成了Spring與MP的整合--><bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean" ><property name="dataSource" ref="dataSource"/><property name="globalConfig"><bean class="com.baomidou.mybatisplus.core.config.GlobalConfig"><property name="dbConfig"><bean class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig"><property name="idType" value="AUTO"/></bean></property></bean></property></bean>

4.3.2tablePrefix

  • 類型: String
  • 默認值: null
表名前綴,全局配置后可省略@TableName()配置。 SpringBoot mybatis-plus.global-config.db-config.table-prefix=tb_ SpringMVC <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean" ><property name="dataSource" ref="dataSource"/><property name="globalConfig"><bean class="com.baomidou.mybatisplus.core.config.GlobalConfig"><property name="dbConfig"><bean class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig"><property name="idType" value="AUTO"/><property name="tablePrefix" value="tb_"/></bean></property></bean></property></bean>

5. 條件構造器

MP中,Wrapper接?的實現類關系如下:

可以看到,AbstractWrapperAbstractChainWrapper是重點實現,接下來我們重點學習 AbstractWrapper以及其?類。 說明: QueryWrapper(LambdaQueryWrapper) UpdateWrapper(LambdaUpdateWrapper) 的?類 ?于?成 sql where 條件, entity 屬性也?于?成 sql where 條件 注意: entity ?成的 where 條件與 使?各個 api ?成的 where 條件沒有任何關聯?為 官??檔地址:https://mybatis.plus/guide/wrapper.html

5.1allEq

5.1.1、說明

allEq(Map<R, V> params) allEq(Map<R, V> params, boolean null2IsNull) allEq(boolean condition, Map<R, V> params, boolean null2IsNull)
  • 全部eq(或個別isNull)
個別參數說明: params : key 為數據庫字段名, value 為字段值 null2IsNull : true 則在 map value null 時調? isNull ?法,false 時則忽 value null 1: allEq({id:1,name:"?王",age:null}) ---> id = 1 and name = '?王' and age is null 2: allEq({id:1,name:"?王",age:null}, false) ---> id = 1 and name = '?王' allEq(BiPredicate<R, V> filter, Map<R, V> params) allEq(BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull) allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull) 個別參數說明: filter : 過濾函數,是否允許字段傳??對條件中 params null2IsNull : 同上 1: allEq((k,v) -> k.indexOf("a") > 0, {id:1,name:"?王",age:null}) --- > name = '?王' and age is null 2: allEq((k,v) -> k.indexOf("a") > 0, {id:1,name:"?王",age:null}, false) ---> name = '?王'

5.1.2、測試?例

package com.lagou.mp; import com.lagou.mp.mapper.UserMapper; import com.lagou.mp.pojo.User; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.HashMap; import java.util.List; import java.util.Map;@RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testWrapper() {QueryWrapper<User> wrapper = new QueryWrapper<>();//設置條件Map<String,Object> params = new HashMap<>();params.put("name", "jack");params.put("age", "20"); // wrapper.allEq(params);//SELECT * FROM tb_user WHERE password IS NULL AND name = ? AND age = ? // wrapper.allEq(params,false); //SELECT * FROM tb_user WHERE name = ? AND age = ? // wrapper.allEq((k, v) -> (k.equals("name") || k.equals("age")) ,params);//SELECT * FROM tb_user WHERE name = ? AND age = ?List<User> users = this.userMapper.selectList(wrapper);for (User user : users) {System.out.println(user);}} }

5.2、基本?較操作

  • eq
    • 等于 =
  • ne
    • 不等于 <>
  • gt
    • ?于 >
  • ge
    • ?于等于 >=
  • lt
    • ?于 <
  • le
    • ?于等于 <=
  • between
    • BETWEEN 1 AND 2
  • notBetween
    • NOT BETWEEN 1 AND 2
  • in
    • 字段 IN (value.get(0), value.get(1), ...)
  • notIn
    • 字段 NOT IN (v0, v1, ...)
測試?例: package com.lagou.mp; import com.lagou.mp.mapper.UserMapper; import com.lagou.mp.pojo.User; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;QueryWrapper<User> wrapper = new QueryWrapper<>();//SELECT id,name,age,email FROM tb_user WHERE password = ? AND age >= ? AND name IN (?,?,?)wrapper.eq("email", "test2@baomidou.com").ge("age", 20).in("name", "jack", "jone", "tom");List<User> users = this.userMapper.selectList(wrapper);for (User user : users) {System.out.println(user);}} }

5.3、模糊查詢

  • like
    • LIKE '%值%'
    • 例: like("name", "") ---> name like '%%'
  • notLike
    • NOT LIKE '%%'
    • : notLike("name", "") ---> name not like '%%'
  • likeLeft
    • LIKE '%'
    • : likeLeft("name", "") ---> name like '%'
  • likeRight
    • LIKE '%'
    • : likeRight("name", "") ---> name like '%'
測試?例: package com.lagou.mp; import com.lagou.mp.mapper.UserMapper; import com.lagou.mp.pojo.User; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testWrapper() {QueryWrapper<User> wrapper = new QueryWrapper<>();//SELECT id,user_name,password,name,age,email FROM tb_user WHERE name LIKE ?//Parameters: %?%(String)wrapper.like("name", "?");List<User> users = this.userMapper.selectList(wrapper);for (User user : users) {System.out.println(user);}} }

5.4、排序

  • orderBy
    • 排序:ORDER BY 字段, ...
    • : orderBy(true, true, "id", "name") ---> order by id ASC,name ASC
  • orderByAsc
    • 排序:ORDER BY 字段, ... ASC
    • : orderByAsc("id", "name") ---> order by id ASC,name ASC
  • orderByDesc
    • 排序:ORDER BY 字段, ... DESC
    • : orderByDesc("id", "name") ---> order by id DESC,name DESC
測試?例: package com.lagou.mp; import com.lagou.mp.mapper.UserMapper; import com.lagou.mp.pojo.User; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testWrapper() {QueryWrapper<User> wrapper = new QueryWrapper<>();//SELECT id,user_name,password,name,age,email FROM tb_user ORDER BY age DESCwrapper.orderByDesc("age");List<User> users = this.userMapper.selectList(wrapper);for (User user : users) {System.out.println(user);}} }

5.5、邏輯查詢

  • or
    • 拼接 OR
    • 主動調? or 表示緊接著下?個?法不是? and 連接!(不調? or 則默認為使? and 連接)
  • and
    • AND 嵌套
    • : and(i -> i.eq("name", "李?").ne("status", "活著")) ---> and (name = '?' and status <> '活著')
測試?例: package com.lagou.mp; import com.lagou.mp.mapper.UserMapper; import com.lagou.mp.pojo.User; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testWrapper() {QueryWrapper<User> wrapper = new QueryWrapper<>();//SELECT id,user_name,password,name,age,email FROM tb_user WHERE name= ? OR age = ?wrapper.eq("name","jack").or().eq("age", 24);List<User> users = this.userMapper.selectList(wrapper);for (User user : users) {System.out.println(user);}} }

5.6select

MP查詢中,默認查詢所有的字段,如果有需要也可以通過select?法進?指定字段。 package com.lagou.mp; import com.lagou.mp.mapper.UserMapper; import com.lagou.mp.pojo.User; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testWrapper() {QueryWrapper<User> wrapper = new QueryWrapper<>();//SELECT id,name,age FROM tb_user WHERE name = ? OR age = ?wrapper.eq("name", "jack").or().eq("age", 24).select("id", "name", "age");List<User> users = this.userMapper.selectList(wrapper);for (User user : users) {System.out.println(user);}} }

6. ActiveRecord

ActiveRecord(簡稱AR)?直?受動態語?( PHP Ruby 等)的喜愛,? Java 作為準靜態語?,對于 ActiveRecord 往往只能感嘆其優雅,所以我們也在 AR 道路上進?了?定的探索,希望?家能夠喜歡。? 什么是ActiveRecord ActiveRecord也屬于ORM(對象關系映射)層,由Rails最早提出,遵循標準的ORM模型:表映射到記錄,記錄映射到對象,字段映射到對象屬性。配合遵循的命名和配置慣例,能夠很?程度的快速實現模型的操作,?且簡潔易懂。 ActiveRecord的主要思想是:
  • 每?個數據庫表對應創建?個類,類的每?個對象實例對應于數據庫中表的??記錄;通常 表的每個字段在類中都有相應的Field
  • ActiveRecord同時負責把??持久化,在ActiveRecord中封裝了對數據庫的訪問,即 CURD;
  • ActiveRecord是?種領域模型(Domain Model),封裝了部分業務邏輯;

6.1、開啟AR之旅

MP中,開啟AR?常簡單,只需要將實體對象繼承Model即可。 package com.lagou.mp.pojo; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.extension.activerecord.Model; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor public class User extends Model<User> {private Long id;private String userName;private String password;private String name;private Integer age;private String email; }

6.2、根據主鍵查詢

@RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testAR() {User user = new User();user.setId(2L);User user2 = user.selectById();System.out.println(user2);} }

6.3、新增數據

@RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testARInsert() {User user = new User();user.setName("應顛");user.setAge(30);user.setEmail("yingdian@lagou.cn");boolean insert = user.insert();System.out.println(insert);} } [main] [com.lagou.mp.mapper.UserMapper.insert]-[DEBUG] ==> Preparing: INSERT INTO tb_user ( name, age, email ) VALUES ( ?, ?, ?, ?, ? ) [main] [com.lagou.mp.mapper.UserMapper.insert]-[DEBUG] ==> Parameters: 應癲 (String), 30(Integer), liubei@lagou.cn(String) [main] [com.lagou.mp.mapper.UserMapper.insert]-[DEBUG] <== Updates: 1

6.4、更新操作

@RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testAR() {User user = new User();user.setId(8L);user.setAge(35);boolean update = user.updateById();System.out.println(update);} } 結果: [main] [com.lagou.mp.mapper.UserMapper.updateById]-[DEBUG] ==> Preparing: UPDATE tb_user SET age=? WHERE id=? [main] [com.lagou.mp.mapper.UserMapper.updateById]-[DEBUG] ==> Parameters: 35(Integer), 8(Long) [main] [com.lagou.mp.mapper.UserMapper.updateById]-[DEBUG] <== Updates: 1

6.5、刪除操作

@RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testAR() {User user = new User();user.setId(7L);boolean delete = user.deleteById();System.out.println(delete);} }

結果:

[main] [com.lagou.mp.mapper.UserMapper.deleteById]-[DEBUG] ==> Preparing: DELETE FROM tb_user WHERE id=? [main] [com.lagou.mp.mapper.UserMapper.deleteById]-[DEBUG] ==> Parameters: 7(Long) [main] [com.lagou.mp.mapper.UserMapper.deleteById]-[DEBUG] <== Updates: 1

6.6、根據條件查詢

@RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testARFindById() {User user = new User();QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();userQueryWrapper.le("age","20");List<User> users = user.selectList(userQueryWrapper);for (User user1 : users) {System.out.println(user1);}} } 結果: User(id=1, name=Jone, age=18, email=test1@baomidou.com) User(id=2, name=Jack, age=20, email=test2@baomidou.com) User(id=7, name=?慕, age=18, email=test@lagou.cn)

7. 插件

7.1mybatis的插件機制

MyBatis 允許你在已映射語句執?過程中的某?點進?攔截調?。默認情況下,MyBatis 允許使?插件 來攔截的?法調?包括: 1. Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed) 2. ParameterHandler (getParameterObject, setParameters) 3. ResultSetHandler (handleResultSets, handleOutputParameters) 4. StatementHandler (prepare, parameterize, batch, update, query) 我們看到了可以攔截Executor接?的部分?法,?如updatequerycommitrollback等?法,還有其他接?的?些?法等。 總體概括為: 1. 攔截執?器的?法 2. 攔截參數的處理 3. 攔截結果集的處理 4. 攔截Sql語法構建的處理 攔截器示例: package com.lagou.mp.plugins; import org.apache.ibatis.executor.Executor; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.plugin.*; import java.util.Properties; @Intercepts({@Signature(type= Executor.class,method = "update",args = {MappedStatement.class,Object.class})}) public class MyInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {//攔截?法,具體業務邏輯編寫的位置return invocation.proceed();}@Overridepublic Object plugin(Object target) {//創建target對象的代理對象,?的是將當前攔截器加?到該對象中return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {//屬性設置} }

注?到Spring容器:

/*** ?定義攔截器*/@Beanpublic MyInterceptor myInterceptor(){return new MyInterceptor();}

或者通過xml配置,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><plugins><plugin interceptor="com.lagou.mp.plugins.MyInterceptor"></plugin></plugins> </configuration>

7.2、執?分析插件

MP中提供了對SQL執?的分析的插件,可?作阻斷全表更新、刪除的操作,注意:該插件僅適?于開發環境,不適?于?產環境。 SpringBoot配置: @Bean public SqlExplainInterceptor sqlExplainInterceptor(){SqlExplainInterceptor sqlExplainInterceptor = new SqlExplainInterceptor();List<ISqlParser> sqlParserList = new ArrayList<>();// 攻擊 SQL 阻斷解析器、加?解析鏈sqlParserList.add(new BlockAttackSqlParser());sqlExplainInterceptor.setSqlParserList(sqlParserList);return sqlExplainInterceptor; } 測試: @Test public void testUpdate(){User user = new User();user.setAge(20);int result = this.userMapper.update(user, null);System.out.println("result = " + result); } 結果: Caused by: com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: Prohibition of table update operation at com.baomidou.mybatisplus.core.toolkit.ExceptionUtils.mpe(ExceptionUtils.java:4 9) at com.baomidou.mybatisplus.core.toolkit.Assert.isTrue(Assert.java:38) at com.baomidou.mybatisplus.core.toolkit.Assert.notNull(Assert.java:72) at com.baomidou.mybatisplus.extension.parsers.BlockAttackSqlParser.processUpdate( BlockAttackSqlParser.java:45) at com.baomidou.mybatisplus.core.parser.AbstractJsqlParser.processParser(Abstract JsqlParser.java:92) at com.baomidou.mybatisplus.core.parser.AbstractJsqlParser.parser(AbstractJsqlPar ser.java:67) at com.baomidou.mybatisplus.extension.handlers.AbstractSqlParserHandler.sqlParser (AbstractSqlParserHandler.java:76) at com.baomidou.mybatisplus.extension.plugins.SqlExplainInterceptor.intercept(Sql ExplainInterceptor.java:63) at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61) at com.sun.proxy.$Proxy70.update(Unknown Source) at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession. java:197) ... 41 more 可以看到,當執?全表更新時,會拋出異常,這樣有效防?了?些誤操作。

7.3、性能分析插件

性能分析攔截器,?于輸出每條 SQL 語句及其執?時間,可以設置最?執?時間,超過時間會拋出異常。 該插件只?于開發環境,不建議?產環境使?。 配置: javaconfig?式 @Bean public PerformanceInterceptor performanceInterceptor(){PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();performanceInterceptor.setMaxTime(100);performanceInterceptor.setFormat(true);return performanceInterceptor; } 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><plugins><!-- SQL 執?性能分析,開發環境使?,線上不推薦。 maxTime 指的是 sql 最?執?時 ? --><plugin interceptor="com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor "><property name="maxTime" value="100" /><!--SQL是否格式化 默認false--><property name="format" value="true" /></plugin></plugins> </configuration> 執?結果: Time11 ms - IDcom.lagou.mp.mapper.UserMapper.selectById Execute SQL SELECT id, user_name, password, name, age, email FROM tb_user WHERE id=7 可以看到,執?時間為11ms。如果將maxTime設置為1,那么,該操作會拋出異常。

7.4、樂觀鎖插件

7.4.1、主要適?場景

意圖: 當要更新?條記錄的時候,希望這條記錄沒有被別?更新 樂觀鎖實現?式:
  • 取出記錄時,獲取當前version
  • 更新時,帶上這個version
  • 執?更新時, set version = newVersion where version = oldVersion
  • 如果version不對,就更新失敗

7.4.2、插件配置

spring xml: <bean class="com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor" /> spring boot: @Bean public OptimisticLockerInterceptor optimisticLockerInterceptor() {return new OptimisticLockerInterceptor(); }

7.4.3、注解實體字段

需要為實體字段添加@Version注解。 第?步,為表添加version字段,并且設置初始值為1 ALTER TABLE `tb_user` ADD COLUMN `version` int(10) NULL AFTER `email`; UPDATE `tb_user` SET `version`='1';

第?步,為User實體對象添加version字段,并且添加@Version注解:

@Version private Integer version;

7.4.4、測試

測試?例: @Test public void testUpdate(){User user = new User();user.setAge(30);user.setId(2L);user.setVersion(1); //獲取到version為1int result = this.userMapper.updateById(user);System.out.println("result = " + result); } 執??志: main] [com.baomidou.mybatisplus.extension.parsers.BlockAttackSqlParser]- [DEBUG] Original SQL: UPDATE tb_user SET age=?, version=? WHERE id=? AND version=? [main] [com.baomidou.mybatisplus.extension.parsers.BlockAttackSqlParser]- [DEBUG] parser sql: UPDATE tb_user SET age = ?, version = ? WHERE id = ? AND version = ? [main] [org.springframework.jdbc.datasource.DataSourceUtils]-[DEBUG] Fetching JDBC Connection from DataSource [main] [org.mybatis.spring.transaction.SpringManagedTransaction]-[DEBUG] JDBC Connection [HikariProxyConnection@540206885 wrapping com.mysql.jdbc.JDBC4Connection@27e0f2f5] will not be managed by Spring [main] [com.lagou.mp.mapper.UserMapper.updateById]-[DEBUG] ==> Preparing: UPDATE tb_user SET age=?, version=? WHERE id=? AND version=? [main] [com.lagou.mp.mapper.UserMapper.updateById]-[DEBUG] ==> Parameters: 30(Integer), 2(Integer), 2(Long), 1(Integer) [main] [com.lagou.mp.mapper.UserMapper.updateById]-[DEBUG] <== Updates: 1 [main] [org.mybatis.spring.SqlSessionUtils]-[DEBUG] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@30135202] result = 1 可以看到,更新的條件中有version條件,并且更新的version2 如果再次執?,更新則不成功。這樣就避免了多?同時更新時導致數據的不?致。

7.4.5、特別說明

  • ?持的數據類型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
  • 整數類型下 newVersion = oldVersion + 1
  • newVersion 會回寫到 entity
  • 僅?持 updateById(id) update(entity, wrapper) ?法
  • update(entity, wrapper) ?法下, wrapper 不能復?!!!

8. Sql 注?器

我們已經知道,在MP中,通過AbstractSqlInjectorBaseMapper中的?法注?到了Mybatis容器,這樣這些?法才可以正常執?。 那么,如果我們需要擴充BaseMapper中的?法,?該如何實現呢? 下?我們以擴展findAll?法為例進?學習。

8.1、編寫MyBaseMapper

package com.lagou.mp.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import java.util.List; public interface MyBaseMapper<T> extends BaseMapper<T> {List<T> findAll(); } 其他的Mapper都可以繼承該Mapper,這樣實現了統?的擴展。 如: package com.lagou.mp.mapper; import com.lagou.mp.pojo.User; public interface UserMapper extends MyBaseMapper<User> {User findById(Long id); }

8.2、編寫MySqlInjector

如果直接繼承AbstractSqlInjector的話,原有的BaseMapper中的?法將失效,所以我們選擇繼承 DefaultSqlInjector進?擴展。 package com.lagou.mp.sqlInjector; import com.baomidou.mybatisplus.core.injector.AbstractMethod; import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector; import java.util.List; public class MySqlInjector extends DefaultSqlInjector {@Overridepublic List<AbstractMethod> getMethodList() {List<AbstractMethod> methodList = super.getMethodList();methodList.add(new FindAll());// 再擴充?定義的?法list.add(new FindAll());return methodList;} }

8.3、編寫FindAll

package com.lagou.mp.sqlInjector; import com.baomidou.mybatisplus.core.enums.SqlMethod; import com.baomidou.mybatisplus.core.injector.AbstractMethod; import com.baomidou.mybatisplus.core.metadata.TableInfo; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.SqlSource; public class FindAll extends AbstractMethod {@Overridepublic MappedStatement injectMappedStatement(Class<?> mapperClass, Class<? > modelClass, TableInfo tableInfo) {String sqlMethod = "findAll";String sql = "select * from " + tableInfo.getTableName();SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);return this.addSelectMappedStatement(mapperClass, sqlMethod, sqlSource, modelClass, tableInfo);} }

8.4、注冊到Spring容器

/** * ?定義SQL注?器 */ @Bean public MySqlInjector mySqlInjector(){return new MySqlInjector(); }

8.5、測試

@Test public void testFindAll(){List<User> users = this.userMapper.findAll();for (User user : users) {System.out.println(user);} } 輸出的SQL [main] [com.lagou.mp.mapper.UserMapper.findAll]-[DEBUG] ==> Preparing: select * from tb_user [main] [com.lagou.mp.mapper.UserMapper.findAll]-[DEBUG] ==> Parameters: [main] [com.lagou.mp.mapper.UserMapper.findAll]-[DEBUG] <== Total: 10 ?此,我們實現了全局擴展SQL注?器。

9. ?動填充功能

有些時候我們可能會有這樣的需求,插?或者更新數據時,希望有些字段可以?動填充數據,?如密碼、version等。在MP中提供了這樣的功能,可以實現?動填充。

9.1、添加@TableField注解

@TableField(fill = FieldFill.INSERT) //插?數據時進?填充 private String version; email添加?動填充功能,在新增數據時有效。 FieldFill提供了多種模式選擇: public enum FieldFill { 9.2、編寫MyMetaObjectHandler 9.3、測試/*** 默認不處理*/DEFAULT,/*** 插?時填充字段*/INSERT,/*** 更新時填充字段*/UPDATE,/*** 插?和更新時填充字段*/INSERT_UPDATE }

9.2、編寫MyMetaObjectHandler

package com.lagou.mp.handler; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import org.apache.ibatis.reflection.MetaObject; import org.springframework.stereotype.Component; @Component public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {Object password = getFieldValByName("version", metaObject);if(null == password){//字段為空,可以進?填充setFieldValByName("version", "123456", metaObject);}}@Overridepublic void updateFill(MetaObject metaObject) {} }

9.3、測試

@Test public void testInsert(){User user = new User();user.setName("冰冰");user.setAge(30);user.setVersion(1);int result = this.userMapper.insert(user);System.out.println("result = " + result); } 結果:

10. 邏輯刪除

開發系統時,有時候在實現功能時,刪除操作需要實現邏輯刪除,所謂邏輯刪除就是將數據標記為刪除,?并?真正的物理刪除(?DELETE操作),查詢時需要攜帶狀態條件,確保被標記的數據不被查詢到。這樣做的?的就是避免數據被真正的刪除。 MP就提供了這樣的功能,?便我們使?,接下來我們?起學習下。

10.1、修改表結構

ALTER TABLE `tb_user` ADD COLUMN `deleted` int(1) NULL DEFAULT 0 COMMENT '1代表刪除,0代表未刪除' AFTER `version`; tb_user表增加deleted字段,?于表示數據是否被刪除,1代表刪除,0代表未刪除。 同時,也修改User實體,增加deleted屬性并且添加@TableLogic注解: @TableLogic private Integer deleted;

10.2、配置

application.properties # 邏輯已刪除值(默認為 1) mybatis-plus.global-config.db-config.logic-delete-value=1 # 邏輯未刪除值(默認為 0) mybatis-plus.global-config.db-config.logic-not-delete-value=0

10.3、測試

@Test public void testDeleteById(){this.userMapper.deleteById(2L); } 執?的SQL [main] [com.lagou.mp.mapper.UserMapper.deleteById]-[DEBUG] ==> Preparing: UPDATE tb_user SET deleted=1 WHERE id=? AND deleted=0 [main] [com.lagou.mp.mapper.UserMapper.deleteById]-[DEBUG] ==> Parameters: 2(Long) [main] [com.lagou.mp.mapper.UserMapper.deleteById]-[DEBUG] <== Updates: 1

測試查詢: @Test public void testSelectById(){User user = this.userMapper.selectById(2L);System.out.println(user); } 執?的SQL [main] [com.lagou.mp.mapper.UserMapper.selectById]-[DEBUG] ==> Preparing: SELECT id,user_name,password,name,age,email,version,deleted FROM tb_user WHERE id=? AND deleted=0 [main] [com.lagou.mp.mapper.UserMapper.selectById]-[DEBUG] ==> Parameters: 2(Long) [main] [com.lagou.mp.mapper.UserMapper.selectById]-[DEBUG] <== Total: 0 可?,已經實現了邏輯刪除。

11. 代碼?成器

AutoGenerator MyBatis-Plus 的代碼?成器,通過 AutoGenerator 可以快速?成 Entity MapperMapper XMLServiceController 等各個模塊的代碼,極?的提升了開發效率。

11.1、創建?程

pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.4.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.lagou</groupId><artifactId>lagou-mp-generator</artifactId><version>0.0.1-SNAPSHOT</version><name>lagou-mp-generator</name><description>Demo project for Spring Boot</description><properties><java.version>11</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--mybatis-plus的springboot?持--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.1.1</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.1.1</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency><!--mysql驅動--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--簡化代碼的?具包--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build> </project>

11.2、代碼

package com.lagou.mp.generator; import java.util.ArrayList; import java.util.List; import java.util.Scanner; import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.generator.AutoGenerator; import com.baomidou.mybatisplus.generator.InjectionConfig; import com.baomidou.mybatisplus.generator.config.DataSourceConfig; import com.baomidou.mybatisplus.generator.config.FileOutConfig; import com.baomidou.mybatisplus.generator.config.GlobalConfig; import com.baomidou.mybatisplus.generator.config.PackageConfig; import com.baomidou.mybatisplus.generator.config.StrategyConfig; import com.baomidou.mybatisplus.generator.config.TemplateConfig; import com.baomidou.mybatisplus.generator.config.po.TableInfo; import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine; /** * <p> * mysql 代碼?成器演示例? * </p> */ public class MysqlGenerator {/*** <p>* 讀取控制臺內容* </p>*/public static String scanner(String tip) {Scanner scanner = new Scanner(System.in);StringBuilder help = new StringBuilder();help.append("請輸?" + tip + ":");System.out.println(help.toString());if (scanner.hasNext()) {String ipt = scanner.next();if (StringUtils.isNotEmpty(ipt)) {return ipt;}}throw new MybatisPlusException("請輸?正確的" + tip + "!");}/*** RUN THIS*/public static void main(String[] args) {// 代碼?成器AutoGenerator mpg = new AutoGenerator();// 全局配置GlobalConfig gc = new GlobalConfig();String projectPath = System.getProperty("user.dir");gc.setOutputDir(projectPath + "/src/main/java");gc.setAuthor("lagou");gc.setOpen(false);mpg.setGlobalConfig(gc);// 數據源配置DataSourceConfig dsc = new DataSourceConfig();dsc.setUrl("jdbc:mysql://127.0.0.1:3306/mp? useUnicode=true&useSSL=false&characterEncoding=utf8");// dsc.setSchemaName("public");dsc.setDriverName("com.mysql.jdbc.Driver");dsc.setUsername("root");dsc.setPassword("root");mpg.setDataSource(dsc);// 包配置PackageConfig pc = new PackageConfig();pc.setModuleName(scanner("模塊名"));pc.setParent("com.lagou.mp.generator");mpg.setPackageInfo(pc);// ?定義配置InjectionConfig cfg = new InjectionConfig() {@Overridepublic void initMap() {// to do nothing}};List<FileOutConfig> focList = new ArrayList<>();focList.add(new FileOutConfig("/templates/mapper.xml.ftl") {@Overridepublic String outputFile(TableInfo tableInfo) {// ?定義輸??件名稱return projectPath + "/lagou-mpgenerator/src/main/resources/mapper/" + pc.getModuleName()+ "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;}});cfg.setFileOutConfigList(focList);mpg.setCfg(cfg);mpg.setTemplate(new TemplateConfig().setXml(null));// 策略配置StrategyConfig strategy = new StrategyConfig();strategy.setNaming(NamingStrategy.underline_to_camel);strategy.setColumnNaming(NamingStrategy.underline_to_camel); //strategy.setSuperEntityClass("com.baomidou.mybatisplus.samples.generator.common.BaseEntity");strategy.setEntityLombokModel(true); //strategy.setSuperControllerClass("com.baomidou.mybatisplus.samples.generator.common.BaseController");strategy.setInclude(scanner("表名"));strategy.setSuperEntityColumns("id");strategy.setControllerMappingHyphenStyle(true);strategy.setTablePrefix(pc.getModuleName() + "_");mpg.setStrategy(strategy);// 選擇 freemarker 引擎需要指定如下加,注意 pom 依賴必須有!mpg.setTemplateEngine(new FreemarkerTemplateEngine());mpg.execute();} }

11.3、測試

代碼已?成:

實體對象:

12. MybatisX 快速開發插件

MybatisX 是?款基于 IDEA 的快速開發插件,為效率??。 安裝?法:打開 IDEA,進? File -> Settings -> Plugins -> Browse Repositories,輸? mybatisx 搜索并安裝。 功能:
  • Java XML 調回跳轉
  • Mapper ?法?動?成 XML

?

?

總結

以上是生活随笔為你收集整理的Mybatis-Plus 详解 拉钩笔记的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲av无码专区在线 | a级黄色一级片 | 成人免费做受小说 | 日本大胆人体视频 | 富婆如狼似虎找黑人老外 | 亚洲综合第一区 | 久久综合婷婷国产二区高清 | 一级毛毛片 | 四虎成人免费视频 | 成人3d动漫一区二区三区91 | 国产视频首页 | 天海翼一区 | 亚洲人女屁股眼交6 | 另一种灿烂生活 | 中国极品少妇xxxxx | 国产精品视频在线免费观看 | 打美女白嫩屁屁网站 | 性做久久久久久 | 国产一区二区综合 | 欧美国产日韩在线 | 不卡av免费在线观看 | 国产九色在线播放九色 | 国产亚洲天堂 | 在线视频你懂得 | 一区二区三区中文字幕 | 国产精品传媒在线观看 | 可以免费看的毛片 | 依依成人综合网 | 在线观看亚洲视频 | 国产精品后入内射日本在线观看 | 日韩日韩| 四虎激情 | 欧美乱码精品一区二区三区 | 国产在线视视频有精品 | 国产精品福利导航 | 91极品身材尤物theporn | h片在线观看视频 | av无码久久久久久不卡网站 | 欧美日韩高清在线观看 | 国产精品久久欧美久久一区 | 少妇无内裤下蹲露大唇视频 | 亚洲天堂美女 | www.亚洲色图.com | 热久久久| 一卡二卡在线视频 | 天天干视频在线观看 | 天堂av资源网 | 亚洲av无码一区二区三区在线观看 | 麻豆传媒网址 | 中文字幕有码在线观看 | 亚洲熟妇丰满大屁股熟妇 | 日一日干一干 | 亚洲精品国产成人久久av盗摄 | 亚洲自拍激情 | 91丨porny丨国产 | 国产三级一区二区三区 | 久久天堂 | 成人导航网站 | 亚洲伦理在线 | 穿越异世荒淫h啪肉np文 | 91麻豆精品国产午夜天堂 | 国产成人在线一区二区 | 91影音| 国产高潮在线观看 | 欧美日韩在线视频一区 | 国产亚洲一区二区三区在线观看 | 黄色大片a级 | 国产在线观 | 日韩毛毛片 | 欧美精品在线免费观看 | 亚洲在线日韩 | 欧美粗暴jizz性欧美20 | 18av在线视频 | 男女做爰猛烈吃奶啪啪喷水网站 | 偷拍亚洲视频 | 日韩播放 | 国产麻豆乱码精品一区二区三区 | 欧美精品一区二区三区蜜臀 | 91精品国产一区二区 | 午夜av影院| 亚洲精品成人无码熟妇在线 | 色哟哟在线观看视频 | 国产日韩二区 | 中文av网站 | 日本激情网址 | 十八禁一区二区三区 | 精品国产999久久久免费 | 国产裸体美女永久免费无遮挡 | 精品少妇人妻一区二区黑料社区 | 亚洲一个色 | 日韩在线天堂 | 欧美激情18 | 永久视频 | 北条麻妃在线一区二区 | 亚洲av电影天堂男人的天堂 | 欧美a v在线 | 巨胸喷奶水www久久久免费动漫 | 人人妻人人澡人人爽人人欧美一区 | 波多野结衣亚洲天堂 |