MyBatisPlus


1.簡介

1.什么是Mybatis-plus?

   MyBatis-Plus(簡稱 MP)是一個 MyBatis 的增強工具,在 MyBatis 的基礎上只做增強不做改變,為簡化開發、提高效率而生。

  官網:https://mp.baomidou.com/

2.開發環境准備

1.配置數據庫環境,創建一張測試表

2.創建springboot項目,引入依賴

<!--mybatis plus 起步依賴-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.2</version>
</dependency>

3.編寫DataSource相關配置

spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8
username: root
password: 123456

4.編寫實體類

@Data
//指定表名
@TableName("user_info")
public class UserInfo implements Serializable {
//指定表的id
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
//指定表中的字段名
@TableField("name")
private String name;
private Integer sex;
private Integer age;
private String address;
private String mobile;
private String email;
@TableField(exist = false)
private String test;
//邏輯刪除,1:刪除,0:未刪
@TableLogic(value = "0", delval = "1")
private Integer disabled;
}
1) @TableField("name") 指定映射關系。
  • 實體類的屬性名和數據庫的字段名自動映射。
  • 自動映射條件:名稱一樣,或者數據庫字段使用_分割,實體類屬性名使用駝峰名稱
  • 否則需要使用@TableField("name") 指定映射關系。
2)@TableField(exist = false) 忽略某個字段的查詢和插入。
3) @TableId(type = IdType.AUTO)設置id生成策略:AUTO 數據庫自增。
  • AUTO 數據庫ID自增,依賴於數據庫。在插入操作生成SQL語句時,不會插入主鍵這一列
  • NONE 未設置主鍵類型。用戶輸入,為空則會根據主鍵的全局策略自動生成
  • INPUT 需要手動設置主鍵,若不設置。插入操作生成SQL語句時,主鍵這一列的值會是null
  • ID_WORKER(Long) 當實體類的主鍵屬性為空時,才會自動填充
  • ID_WORKER_STR(String) 當實體類的主鍵屬性為空時,才會自動填充
  • UUID 當實體類的主鍵屬性為空時,才會自動填充,使用UUID
4)@TableLogic(value = "0", delval = "1")設置邏輯刪除字段,並設置刪除與未刪的代表值
添加該注解之后:
  • 刪除轉變為更新,調用mp提供的刪除接口時,更新disable字段0->1
  • 只對自動注入的SQL起效
  • 查詢時自動生成where disable=0查詢
  • 更新時自動生成where disable=0條件防止更新到已刪除數據
  • 自己寫的刪除接口依然為物理刪除
不添加此注解時:
  • mp提供的刪除接口默認為物理刪除

5.啟動類增加 @MapperScan 注解,指定dao包的位置

@SpringBootApplication
@MapperScan("com.jinrui.dao")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}

3.Mapper 接口

編寫dao

使用mp定義Mapper,需要讓Mapper接口繼承 BaseMapper接口。

@Mapper
public interface UserInfoDao extends BaseMapper<UserInfo> {
}

1.增加

// 插入一條記錄

int insert(T entity);

類型

參數名

描述

T entity 實體對象

2.刪除

// 根據 entity 條件,刪除記錄
int delete(Wrapper<T> wrapper);
// 刪除(根據ID 批量刪除)
int deleteBatchIds(Collection<? extends Serializable> idList);
// 根據 ID 刪除
int deleteById(Serializable id);
// 根據 columnMap 條件,刪除記錄
int deleteByMap(Map<String, Object> columnMap);

類型 參數名 描述
Wrapper<T> wrapper 實體對象封裝操作類(可以為 null)
Collection<? extends Serializable> idList 主鍵ID列表(不能為 null 以及 empty)
Serializable id 主鍵ID
Map<String, Object> columnMap 表字段 map 對象

3.修改

// 根據 whereWrapper 條件,更新記錄
int update(Wrapper<T> updateWrapper);
// 根據 ID 修改
int updateById(T entity);

類型 參數名 描述
T entity 實體對象 (set 條件值,可為 null)
Wrapper<T> updateWrapper 實體對象封裝操作類(可以為 null,里面的 entity 用於生成 where 語句)

4.查詢

// 根據 ID 查詢
T selectById(Serializable id);
// 根據 entity 條件,查詢一條記錄
T selectOne(Wrapper<T> queryWrapper);

// 查詢(根據ID 批量查詢)
List<T> selectBatchIds(Collection<? extends Serializable> idList);
// 根據 entity 條件,查詢全部記錄
List<T> selectList(Wrapper<T> queryWrapper);
// 查詢(根據 columnMap 條件)
List<T> selectByMap(Map<String, Object> columnMap);
// 根據 Wrapper 條件,查詢全部記錄,只展示查詢的字段,不展示為null的字段
List<Map<String, Object>> selectMaps(Wrapper<T> queryWrapper);
// 根據 Wrapper 條件,查詢全部記錄。注意: 只返回第一個字段的值
List<Object> selectObjs(Wrapper<T> queryWrapper);

// 根據 entity 條件,查詢全部記錄(並翻頁)
IPage<T> selectPage(IPage<T> page, Wrapper<T> queryWrapper);
// 根據 Wrapper 條件,查詢全部記錄(並翻頁)
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, Wrapper<T> queryWrapper);
// 根據 Wrapper 條件,查詢總記錄數
Integer selectCount(Wrapper<T> queryWrapper);

類型 參數名 描述
Serializable id 主鍵ID
Wrapper<T> queryWrapper 實體對象封裝操作類(可以為 null)
Collection<? extends Serializable> idList 主鍵ID列表(不能為 null 以及 empty)
Map<String, Object> columnMap 表字段 map 對象
IPage<T> page 分頁查詢條件(可以為 RowBounds.DEFAULT)

條件構造器

AbstractWrapper是QueryWrapper和 UpdateWrapper的父類,用於生成 sql 的 where 條件

AbstractWrapper:
like(R column, Object val) like(boolean condition, R column, Object val)
  • LIKE '%值%'

  • 例: like("name", "王")--->name like '%王%
eq(R column, Object val) eq(boolean condition, R column, Object val)
  • 等於 =

  • 例: eq("name", "老王")--->name = '老王'

likeLeft(R column, Object val) likeLeft(boolean condition, R column, Object val)
  • LIKE '%值'

  • 例: likeLeft("name", "王")--->name like '%王'

likeRight(R column, Object val) likeRight(boolean condition, R column, Object val)
  • LIKE '值%'
  • 例: likeRight("name", "王")--->name like '王%'
gt(R column, Object val) gt(boolean condition, R column, Object val)
  • 大於 >
  • 例: gt("age", 18)--->age > 18
ge(R column, Object val) ge(boolean condition, R column, Object val)
  • 大於等於 >=

  • 例: ge("age", 18)--->age >= 18

lt(R column, Object val) lt(boolean condition, R column, Object val)
  • 小於 <
  • 例: lt("age", 18)--->age < 18
le(R column, Object val) le(boolean condition, R column, Object val)
  • 小於等於 <=
  • 例: le("age", 18)--->age <= 18
isNull(R column) isNull(boolean condition, R column)
  • 字段 IS NULL
  • 例: isNull("name")--->name is null
isNotNull(R column) isNotNull(boolean condition, R column)
  • 字段 IS NOT NULL
  • 例: isNotNull("name")--->name is not null
in(R column, Collection<?> value) in(boolean condition, R column, Collection<?> value)
  • 字段 IN (value.get(0), value.get(1), ...)
  • 例: in("age",{1,2,3})--->age in (1,2,3)
orderBy(boolean condition, boolean isAsc, R... columns)
  • 排序:ORDER BY 字段, ...
  • 例: orderBy(true, true, "id", "name")--->order by id ASC,name ASC
between(R column, Object val1, Object val2) between(boolean condition, R column, Object val1, Object val2)
  • BETWEEN 值1 AND 值2
  • 例: between("age", 18, 30)--->age between 18 and 30
notBetween(R column, Object val1, Object val2) notBetween(boolean condition, R column, Object val1, Object val2)
  • NOT BETWEEN 值1 AND 值2
  • 例: notBetween("age", 18, 30)--->age not between 18 and 30
groupBy(R... columns) groupBy(boolean condition, R... columns)
  • 分組:GROUP BY 字段, ...
  • 例: groupBy("id", "name")--->group by id,name
having(String sqlHaving, Object... params) having(boolean condition, String sqlHaving, Object... params)
  • HAVING ( sql語句 )
  • 例: having("sum(age) > 10")--->having sum(age) > 10
  • 例: having("sum(age) > {0}", 11)--->having sum(age) > 11
or() or(boolean condition)
  • 拼接 OR
  • 主動調用or表示緊接着下一個方法不是用and連接!(不調用or則默認為使用and連接)
apply(String applySql, Object... params) apply(boolean condition, String applySql, Object... params)
  • 該方法可用於數據庫函數 動態入參的params對應前面的{index}部分.這樣是不會有sql注入風險的,反之會有!
  • apply("date_format(dateColumn,'%Y-%m-%d') = {0}", "2008-08-08")--->date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")

QueryWrapper:
select(String... sqlSelect)
  • 設置查詢字段
  • 例: select("id", "name", "age")->select id,name,age
UpdateWrapper:
set(String column, Object val) set(boolean condition, String column, Object val)
  • SQL SET 字段
  • 例: set("name", "wang")
  • 例: set("name", "")--->數據庫字段值變為空字符串
  • 例: set("name", null)--->數據庫字段值變為null
setSql(String sql)
  • 設置 SET 部分 SQL
  • 例: setSql("name = 'wang'")

4.Service接口

說明:

通用 Service CRUD 封裝IService 接口,進一步封裝 CRUD 采用 get 查詢、單行 remove 刪除、 list 查詢集合、 page 分頁, 前綴命名方式區分 Mapper 層避免混淆。

需要繼承Service類

public interface UserInfoService extends IService<UserInfo> {}

建議如果存在自定義通用 Service 方法,請創建自己的 BaseService 繼承 Mybatis-Plus 提供的基類

public interface UserInfoService extends BaseService<UserInfo> {}
public interface BaseService extends IService<UserInfo> {}

 

接口介紹:

#Save

// 插入一條記錄(選擇字段,策略插入)

boolean save(T entity);

// 插入(批量)

boolean saveBatch(Collection<T> entityList);

類型

參數名

描述

T entity 實體對象
Collection<T> entityList 實體對象集合

SaveOrUpdate

// 主鍵id存在更新記錄,否則插入一條記錄

boolean saveOrUpdate(T entity);

// 批量修改插入

boolean saveOrUpdateBatch(Collection<T> entityList);

// 批量修改插入

boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);

類型 參數名 描述
T entity 實體對象
Collection<T> entityList 實體對象集合
int batchSize 插入批次數量

#Remove

// 根據 entity 條件,刪除記錄
boolean remove(Wrapper<T> queryWrapper);
// 根據 ID 刪除
boolean removeById(Serializable id);
// 根據 columnMap 條件,刪除記錄
boolean removeByMap(Map<String, Object> columnMap);
// 刪除(根據ID 批量刪除)
boolean removeByIds(Collection<? extends Serializable> idList);

類型 參數名 描述
Wrapper<T> queryWrapper 實體包裝類 QueryWrapper
Serializable id 主鍵ID
Map<String, Object> columnMap 表字段 map 對象
Collection<? extends Serializable> idList 主鍵ID列表

#Update

// 根據 updateWrapper條件,更新記錄
boolean update(T updateEntity, Wrapper<T> updateWrapper);
// 根據 ID 選擇修改
boolean updateById(T entity);
// 根據ID 批量更新
boolean updateBatchById(Collection<T> entityList);
// 根據ID 批量更新
boolean updateBatchById(Collection<T> entityList, int batchSize);

類型 參數名 描述
Wrapper<T> updateWrapper 實體對象封裝操作類 UpdateWrapper
T entity 實體對象
Collection<T> entityList 實體對象集合
int batchSize 更新批次數量

#Get

// 根據 ID 查詢
T getById(Serializable id);
// 根據 Wrapper,查詢一條記錄。結果集,如果是多個會拋出異常
T getOne(Wrapper<T> queryWrapper);
// 根據 Wrapper,查詢一條記錄
T getOne(Wrapper<T> queryWrapper, boolean throwEx);
// 根據 Wrapper,查詢一條記錄
Map<String, Object> getMap(Wrapper<T> queryWrapper);

類型 參數名 描述
Serializable id 主鍵ID
Wrapper<T> queryWrapper 實體對象封裝操作類 QueryWrapper
boolean throwEx 有多個 result 是否拋出異常
T entity 實體對象

#List

// 查詢所有
List<T> list();
// 查詢列表
List<T> list(Wrapper<T> queryWrapper);
// 查詢(根據ID 批量查詢)
Collection<T> listByIds(Collection<? extends Serializable> idList);
// 查詢(根據 columnMap 條件)
Collection<T> listByMap(Map<String, Object> columnMap);
// 查詢所有列表,不顯示為null的字段
List<Map<String, Object>> listMaps();
// 根據條件查詢所有列表,不顯示為null的字段
List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper);
// 查詢全部記錄,只顯示第一個字段
List<Object> listObjs();
// 根據 Wrapper 條件,查詢全部記錄
List<Object> listObjs(Wrapper<T> queryWrapper);

類型 參數名 描述
Wrapper<T> queryWrapper 實體對象封裝操作類 QueryWrapper
Collection<? extends Serializable> idList 主鍵ID列表
Map<?String, Object> columnMap 表字段 map 對象

#Count

// 查詢總記錄數
int count();
// 根據 Wrapper 條件,查詢總記錄數
int count(Wrapper<T> queryWrapper);

 

類型

參數名

描述

Wrapper<T> queryWrapper 實體對象封裝操作類 QueryWrapper

5.分頁插件

寫mybatis-plus配置類,用來配置使用的數據庫

@Configuration
public class MybatisPlusConfig {
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor= new PaginationInterceptor();
paginationInterceptor.setDialectType("mysql");
return paginationInterceptor;
}
}

寫service,可以調用mp中service層提供的分頁接口和Ipage插件進行分頁。

// 無條件分頁查詢
IPage<T> page(IPage<T> page);
// 條件分頁查詢
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);
// 無條件分頁查詢,不顯示null字段
IPage<Map<String, Object>> pageMaps(IPage<T> page);
// 條件分頁查詢,不顯示null字段
IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper);

類型 參數名 描述
IPage<T> page 翻頁對象
Wrapper<T> queryWrapper 實體對象封裝操作類 QueryWrapper

編碼:

@Override
public List<UserInfo> selectPage(Integer page, Integer limit) {
IPage ipage = this.page(new Page(page,limit),null);
return ipage.getRecords();
}

測試

 

 

所執行的sql

6.SQL分析

在MybatisPlusConfig當中添加配置代碼,此配置可以顯示SQ語句和運行時間

@Bean
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
Properties properties=new Properties();
//開啟sql格式化
properties.setProperty("format", "true");
performanceInterceptor.setProperties(properties);
return performanceInterceptor;
}

測試

7.代碼生成器

1.添加依賴

<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.4.1</version> </dependency>

2.添加模板依賴

MyBatis-Plus 支持 Velocity(默認)、Freemarker、Beetl,項目中使用的是Freemarker,我們以Freemarker為例。

<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.30</version>
</dependency>

3.編寫配置類

設置存放路徑,作者

GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
System.out.println(projectPath);
gc.setOutputDir(projectPath + "/src/main/java");
gc.setAuthor("itheima");
gc.setOpen(false);

數據源配置

DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql:///test");
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("123456");
mpg.setDataSource(dsc);

包配置

PackageConfig pc = new PackageConfig();
pc.setModuleName(scanner("模塊名"));
pc.setParent("com.jinrui");
mpg.setPackageInfo(pc);

其他配置

// 如果模板引擎是 freemarker
String templatePath = "/templates/mapper.xml.ftl";
// 如果模板引擎是 velocity
// String templatePath = "/templates/mapper.xml.vm";
// 自定義輸出配置
List<FileOutConfig> focList = new ArrayList<>();
// 自定義配置會被優先輸出
focList.add(new FileOutConfig(templatePath) {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定義輸出文件名 , 如果你 Entity 設置了前后綴、此處注意 xml 的名稱會跟着發生變化!!
return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
+ "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
// 配置模板
TemplateConfig templateConfig = new TemplateConfig();
templateConfig.setXml(null);
mpg.setTemplate(templateConfig);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
// 下划線駝峰命名轉換
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
// 開啟lombok
strategy.setEntityLombokModel(true);
// 開啟RestController
strategy.setRestControllerStyle(true);
// 公共父類
// 寫於父類中的公共字段
// strategy.setSuperEntityColumns("id");
strategy.setInclude(scanner("表名,多個英文逗號分割").split(","));
//@RequestMapping中駝峰轉字符串
strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix(pc.getModuleName() + "_");
mpg.setStrategy(strategy);
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute();

7.測試

執行main方法,輸入模塊名和表名:

成功生成代碼

8.Demo

 

9.fir項目

1.fir-db

1.實體類添加注解,以MetricData為例,用於數據庫表與實體類、字段與屬性對應

@TableName("metric_data")
public class MetricData implements Serializable {
private static long serialVersionUID = -2449909017343874495L;
@TableId(value = "mdid", type = IdType.AUTO)
private Long id;
@TableField("metricid")
private String metricId;
@TableField("time")
private Long time;
@TableField("data")
private Double data;
@TableField("addtime")
private Date addtime;
@TableField("reporttime")
private Long reportTime;
@TableField(exist = false)
private Metric metric;
@TableLogic(value = "0", delval = "1")
@TableField("disabled")
private Integer disabled;

2.Mapper層繼承BaseMapper,可以調用mp提供的API

public interface MetricDataRepository extends BaseRepository<MetricData, Long>{}
public interface BaseRepository<T, ID extends Serializable> extends BaseMapper<T>()

3.Service層繼承Iservice,可以調用mp提供的API

public interface MetricDataService extends BaseService<MetricData>{}
public interface BaseService<T> extends IService<T>{}

4.使用了自定義通用Service類,定義了一些常用的方法,方便復用

public interface BaseService<T> extends IService<T>
{
AdminUser getCurrentAdmin();
User getCurrentUser();
SearchResult findBySearchRequest( SearchRequest searchRequest);
List<T> findAll();
T findById( Serializable id);
boolean deleteById( Serializable p0);
boolean isDisabled();
}

5.MybatisPlusConfig中寫了一些配置,用於配置分頁插件和SQL分析插件

@Configuration
public class MybatisPlusConfig {
/**
* mybatis-plus分頁插件
* @return
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor= new PaginationInterceptor();
paginationInterceptor.setDialectType("mysql");
return paginationInterceptor;
}
/**
*sql執行效率插件
* @return
*/
@Bean
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
Properties properties=new Properties();
//開啟sql格式化
properties.setProperty("format", "true");
performanceInterceptor.setProperties(properties);
return performanceInterceptor;
}
}

6.條件查詢的構造方式

Controller層,attribute(字段)、operator(操作)、values(值)封裝到Condition中,col(字段)、direction(方向)封裝到Ordering中,然后把這些數據封裝到SearchRequest中。

Service層,調用BaseService中的findBySearchRequest方法進行分頁查詢,迭代構造條件,最后返回SearchResult。

例:Controller層:封裝Condition、Ordering、page、limit到SearchRequest,以searchRequest為參數調用service中的search()。

這里面封裝數據的SearchRequest,代碼如下圖所示。

Service層:調用BaseService類中的findBySearchRequest方法用於分頁查詢。

返回結果SearchResult,代碼如圖所示。

BaseService中findBySearchRequest方法,主要用於分頁,調用contructWrapper方法構造條件。

BaseService中contructWrapper方法用於迭代構造查詢條件,調用addCondition方法。

addCondition方法:主要用於匹配操作名稱和構造條件。

private QueryWrapper addCondition(String attribute, String operator, List<Object> valuesList, QueryWrapper queryWrapper) {
Object value = null;
if (CollectionUtils.isNotEmpty(valuesList)) {
value = valuesList.get(0);
}
switch (OperatorEnum.matchValue(operator)) {
case LIKE: {
queryWrapper.like(attribute, value);
break;
}
case LIKE_BEGIN: {
queryWrapper.likeRight(attribute, value);
break;
}
case LIKE_END: {
queryWrapper.likeLeft(attribute, value);
break;
}
case GT: {
queryWrapper.gt(attribute, value);
break;
}
case GTE: {
queryWrapper.ge(attribute, value);
break;
}
case EQ: {
queryWrapper.eq(attribute, value);
break;
}
case LT: {
queryWrapper.lt(attribute, value);
break;
}
case LTE: {
queryWrapper.le(attribute, value);
break;
}
case ISNULL: {
queryWrapper.isNull(attribute);
break;
}
case ISNOTNULL: {
queryWrapper.isNotNull(attribute);
break;
}
case IN: {
queryWrapper.in(attribute, valuesList);
break;
}
case NE: {
queryWrapper.ne(attribute, value);
break;
}
default: {
throw new SearchException(ServiceExceptionCodeEnum.BADARGUMENT_PARAM.getCode(), "查詢操作符不符合");
}
}
return queryWrapper;
}

枚舉類,用於選擇對應的查詢條件。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM