Mybatis-Plus讲义
1 Mybatis-Plus簡介
1.1 簡介
? MyBatis-Plus(簡稱 MP)是一個 MyBatis 的增強工具,在 MyBatis 的基礎上只做增強不做改變,為簡化開發、提高效率而生。該框架由baomidou(苞米豆)組織開發并且開源的。官網:https://mybatis.plus/ 或 https://mp.baomidou.com/,碼云地址:https://gitee.com/organizations/baomidou
愿景
我們的愿景是成為 MyBatis 最好的搭檔,就像魂斗羅 中的 1P、2P,基友搭配,效率翻倍。
1.2 特性
- 無侵入:只做增強不做改變,引入它不會對現有工程產生影響,如絲般順滑
- 損耗小:啟動即會自動注入基本 CURD,性能基本無損耗,直接面向對象操作
- 強大的 CRUD 操作:內置通用 Mapper、通用 Service,僅僅通過少量配置即可實現單表大部分 CRUD 操作,更有強大的條件構造器,滿足各類使用需求
- 支持 Lambda 形式調用:通過 Lambda 表達式,方便的編寫各類查詢條件,無需再擔心字段寫錯
- 支持多種數據庫:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer2005、SQLServer 等多種數據庫
- 支持主鍵自動生成:支持多達 4 種主鍵策略(內含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解決主鍵問題
- 支持 XML 熱加載:Mapper 對應的 XML 支持熱加載,對于簡單的 CRUD 操作,甚至可以無 XML 啟動
- 支持 ActiveRecord 模式:支持 ActiveRecord 形式調用,實體類只需繼承 Model 類即可進行強大的 CRUD 操作
- 支持自定義全局通用操作:支持全局通用方法注入( Write once, use anywhere )
- 支持關鍵詞自動轉義:支持數據庫關鍵詞(order、key…)自動轉義,還可自定義關鍵詞
- 內置代碼生成器:采用代碼或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 層代碼,支持模板引擎,更有超多自定義配置等您來使用
- 內置分頁插件:基于 MyBatis 物理分頁,開發者無需關心具體操作,配置好插件之后,寫分頁等同于普通 List 查詢
- 內置性能分析插件:可輸出 Sql 語句以及其執行時間,建議開發測試時啟用該功能,能快速揪出慢查詢
- 內置全局攔截插件:提供全表 delete 、update 操作智能分析阻斷,也可自定義攔截規則,預防誤操作
- 內置 Sql 注入剝離器:支持 Sql 注入剝離,有效預防 Sql 注入攻擊
2 快速入門
2.1 創建數據庫及表
-- 創建測試表 CREATE TABLE `tb_user` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',`user_name` varchar(20) NOT NULL COMMENT '用戶名',`password` varchar(20) NOT NULL COMMENT '密碼',`name` varchar(30) DEFAULT NULL COMMENT '姓名',`age` int(11) DEFAULT NULL COMMENT '年齡',`email` varchar(50) DEFAULT NULL COMMENT '郵箱',PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;-- 插入測試數據 INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES ('1', 'zhangsan', '123456', '張三', '18', 'test1@wang.cn'); INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES ('2', 'lisi', '123456', '李四', '20', 'test2@wang.cn'); INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES ('3', 'wangwu', '123456', '王五', '28', 'test3@wang.cn'); INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES ('4', 'zhaoliu', '123456', '趙六', '21', 'test4@wang.cn'); INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES ('5', 'sunqi', '123456', '孫七', '24', 'test5@wang.cn');2.2 工程搭建
2.2.1 創建springBoot工程
2.2.2 導入依賴
<?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"><modelVersion>4.0.0</modelVersion><groupId>cn.wang.mp</groupId><artifactId>wang-mp-springboot</artifactId><version>1.0-SNAPSHOT</version><!-- 繼承Spring boot工程 --><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.5.RELEASE</version></parent><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><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.1.2</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>log4j.properties:
log4j.rootLogger=DEBUG,A1log4j.appender.A1=org.apache.log4j.ConsoleAppender log4j.appender.A1.layout=org.apache.log4j.PatternLayout log4j.appender.A1.layout.ConversionPattern=[%t] [%c]-[%p] %m%n2.2.3 配置application.yml
spring:application:name: mybatis-plus-demodatasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/mp?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTCusername: rootpassword: root# 設置Mapper接口所對應的XML文件位置,如果你在Mapper接口中有自定義方法,需要進行該配置 mybatis-plus:mapper-locations: classpath*:mybatis/*.xml# 設置別名包掃描路徑,通過該屬性可以給包中的類注冊別名type-aliases-package: com.itheima.pojo2.2.4 編寫pojo
package com.wang.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 lombok.Data;@Data @TableName("tb_user") public class User {@TableId(value = "ID",type = IdType.AUTO)private Long id;@TableField("USER_NAME")private String userName; //駝峰命名,否則無需注解private String password;private String name;private Integer age;private String email; }2.2.5 編寫mapper接口和配置文件
package com.itheima.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.itheima.pojo.User;public interface UserMapper extends BaseMapper<User> { }在resources目錄下新建一個文件夾mybatis,專門存放mapper配置文件
<?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.wang.mapper.UserMapper"></mapper>2.2.6 修改啟動類
@SpringBootApplication @MapperScan("com.wang.mapper") public class MybatisPlusApplication {public static void main(String[] args) {SpringApplication.run(MybatisPlusApplication.class,args);}/*** 分頁插件*/@Beanpublic PaginationInterceptor paginationInterceptor() {return new PaginationInterceptor();} }2.2.7 編寫測試用例
@SpringBootTest(classes = MybatisPlusApplication.class) @RunWith(SpringRunner.class) public class UserMapperTest {@Autowiredprivate UserMapper userMapper;//查詢所有@Testpublic void testSelectAll(){List<User> userList = userMapper.selectList(null);System.out.println(userList);}//查詢一個@Testpublic void testSelectOne(){User user = userMapper.selectById(1);System.out.println(user);}//保存@Testpublic void testSave(){User user = new User();userMapper.insert(user);}//修改@Testpublic void testUpdate(){User user = new User();userMapper.updateById(user);}//刪除@Testpublic void testDelete(){int i = userMapper.deleteById(1l);}//條件查詢@Testpublic void testQueryParame(){Wrapper wrapper = new QueryWrapper<User>();((QueryWrapper) wrapper).eq("user_name","lisi");List<User> list = userMapper.selectList(wrapper);System.out.println(list);}//分頁查詢@Testpublic void testPage(){IPage page = new Page(2,2);IPage<User> iPage = userMapper.selectPage(page, null);System.out.println(iPage.getRecords());System.out.println(iPage.getTotal());}}3 通用CRUD
? 在入門案例中,我們的Mapper接口繼承了BaseMapper,然后就可以進行到各種各樣的單表操作,接下來我們將詳細講解這些操作。
3.1 主鍵生成策略
? 在剛才的例子中,數據已經保存到了數據庫,但是id的值不是我們期望的自增長,而是MP生成了id的值并寫入到了數據庫。我們也可以通過IdType類自己設置id的生成策略。
package com.baomidou.mybatisplus.annotation; import lombok.Getter;/*** 生成ID類型枚舉類*/ @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對象,設置id為自增長:
package cn.wang.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;... ... }4 條件構造器
? 在增刪改查中,最復雜的就是帶有各種條件的操作。在MP中,專門針對sql條件進行了封裝,提供了各種Wrapper接口及其實現類。XxxWrapper類提供了各種方法來封裝sql條件。
MP提供了各種方法用來支持帶有條件的查詢方法、修改方法和刪除方法:
/** 根據 entity 條件,查詢一條記錄 @param queryWrapper 實體對象封裝操作類(可以為null) */ T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);/** 根據 Wrapper 條件,查詢總記錄數 @param queryWrapper 實體對象封裝操作類(可以為null) */ Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);/** 根據 entity 條件,查詢全部記錄 @param queryWrapper 實體對象封裝操作類(可以為null) */ List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);下面我們以查詢方法為例學習條件構造器的具體用法。
4.1 比較操作
- 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, …)
4.2 模糊查詢
- 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 '王%'
4.3 排序
- 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 cn.wang.mp;import cn.wang.mp.mapper.UserMapper; import cn.wang.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 testOrderByAgeDesc() {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);}} }4.4 邏輯查詢
- or
- 拼接 OR
- 主動調用or表示緊接著下一個方法不是用and連接!(不調用or則默認為使用and連接)
- and
- AND 嵌套
- 例: and(i -> i.eq("name", "李白").ne("status", "活著"))—>and (name = '李白' and status <> '活著')
測試用例:
package cn.wang.mp;import cn.wang.mp.mapper.UserMapper; import cn.wang.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 testOr() {QueryWrapper<User> wrapper = new QueryWrapper<>();//SELECT id,user_name,password,name,age,email FROM tb_user WHERE //name = ? OR age = ?wrapper.eq("name","李四").or().eq("age", 24);List<User> users = this.userMapper.selectList(wrapper);for (User user : users) {System.out.println(user);}} }4.5 分頁查詢
selectPage方法:
/*** 根據 entity 條件,查詢全部記錄(并翻頁)* @param page 分頁查詢條件(可以為 RowBounds.DEFAULT)* @param queryWrapper 實體對象封裝操作類(可以為 null)*/ IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);配置分頁插件:
package cn.wang.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("cn.wang.mp.mapper") //設置mapper接口的掃描包 public class MybatisPlusConfig {/*** 分頁插件*/@Beanpublic PaginationInterceptor paginationInterceptor() {return new PaginationInterceptor();} }測試用例:
package cn.wang.mp;import cn.wang.mp.mapper.UserMapper; import cn.wang.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 TestUserMapper {@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);}} }測試結果:
[main] [cn.wang.mp.mapper.UserMapper.selectPage]-[DEBUG] ==> Preparing: SELECT COUNT(1) FROM tb_user WHERE age > ? [main] [cn.wang.mp.mapper.UserMapper.selectPage]-[DEBUG] ==> Parameters: 20(Integer) [main] [cn.wang.mp.mapper.UserMapper.selectPage]-[DEBUG] ==> Preparing: SELECT id,user_name,password,name,age,email FROM tb_user WHERE age > ? LIMIT ?,? [main] [cn.wang.mp.mapper.UserMapper.selectPage]-[DEBUG] ==> Parameters: 20(Integer), 0(Long), 1(Long) [main] [cn.wang.mp.mapper.UserMapper.selectPage]-[DEBUG] <== Total: 1 [main] [org.mybatis.spring.SqlSessionUtils]-[DEBUG] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6ecd665] 數據總條數:3 總頁數:3 user = User(id=3, userName=wangwu, password=123456, name=王五, age=28, email=test3@wang.cn, address=null)4.6 修改和刪除
? 前面都是以查詢為例講解條件構造器,那么在進行修改和刪除操作時也可以帶條件,和查詢基本一樣,這里不再講解,后面用到時再說。
/** 根據wrapper封裝的條件進行更新操作 */ int delete(@Param("ew") Wrapper<T> wrapper);/** 根據wrapper封裝的條件進行刪除操作 */ int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper);5 Mybatis-Plus的Service封裝
? Mybatis-Plus為了開發更加快捷,對業務層也進行了封裝,直接提供了相關的接口和實現類。我們在進行業務層開發時,可以繼承它提供的接口和實現類,使得編碼更加高效。
com.baomidou.mybatisplus.extension.service.IService接口
該接口是一個泛型接口,里面提供了很多方法,包括基本的增刪改查。
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl類
該類實現了上面接口中的所有方法。
測試用例
1)自定義業務層接口,繼承IService:
public interface UserService extends IService<User> {}2)自定義業務層實現類,繼承ServiceImpl:
@Service public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {}3)測試類:
@RunWith(SpringRunner.class) @SpringBootTest public class TestUserService {@Autowiredprivate UserService userService;@Testpublic void testInsert() {User user = new User();user.setEmail("123@wang.cn");user.setAge(301);user.setUserName("caocao1");user.setName("曹操1");user.setPassword("123456");userService.save(user);//獲取自增長后的id值, 自增長后的id值會回填到user對象中System.out.println("id => " + user.getId());}@Testpublic void testSelectById() {User user = userService.getById(2);System.out.println(user);}@Testpublic void testUpdateById() {User user = new User();user.setId(1L); //條件,根據id更新user.setAge(19); //更新的字段user.setPassword("666666");userService.updateById(user);}@Testpublic void testDeleteById(){// 根據id刪除數據userService.removeById(2L);}}6 MybatisX 快速開發插件
MybatisX 是一款基于 IDEA 的快速開發插件,為效率而生。
安裝方法:打開 IDEA,進入 File -> Settings -> Plugins -> Browse Repositories,輸入 mybatisx 搜索并安裝。
功能:
- Java 與 XML 調回跳轉
- Mapper 方法自動生成 XML
6 MybatisX 快速開發插件
MybatisX 是一款基于 IDEA 的快速開發插件,為效率而生。
安裝方法:打開 IDEA,進入 File -> Settings -> Plugins -> Browse Repositories,輸入 mybatisx 搜索并安裝。
功能:
- Java 與 XML 調回跳轉
- Mapper 方法自動生成 XML
總結
以上是生活随笔為你收集整理的Mybatis-Plus讲义的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: r语言 tunerf函数_R语言 | 一
- 下一篇: ESD镜像文件转换成ISO镜像文件解决方