一起來學SpringBoot(十五)MybatisPlus的整合
MyBatis-Plus(簡稱 MP)是一個MyBatis的增強工具 ,在 MyBatis 的基礎上只做增強不做改變,為簡化開發、提高效率而生。本篇文章介紹的是與springboot的整合。
特性
-
無侵入:只做增強不做改變,引入它不會對現有工程產生影響,如絲般順滑
-
損耗小:啟動即會自動注入基本 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 操作
-
支援自定義全域性通用操作
-
支援關鍵詞自動轉義:支援資料庫關鍵詞(order、key…)自動轉義,還可自定義關鍵詞
-
內建程式碼生成器:採用程式碼或者 Maven 外掛可快速生成 Mapper 、 Model 、 Service 、 Controller 層程式碼,支援模板引擎,更有超多自定義配置等您來使用
-
內建分頁外掛:基於 MyBatis 物理分頁,開發者無需關心具體操作,配置好外掛之後,寫分頁等同於普通 List 查詢
-
內建效能分析外掛:可輸出 Sql 語句以及其執行時間,建議開發測試時啟用該功能,能快速揪出慢查詢
-
內建全域性攔截外掛
-
內建 Sql 注入剝離器:支援 Sql 注入剝離,有效預防 Sql 注入攻擊
不要忘記依賴
<!-- mp --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.0.3</version> </dependency>
程式碼生成器
不多說這個非常爽,執行下能生成基本結構。我這裡稍微加了點註釋,寫好表名直接執行就ok了
package com.maoxs.generator;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.ArrayList;
import java.util.List;
/**
* @author fulin
* @since 2018-09-12
*/
public class MysqlGenerator {
public static void Generator(String[] tableName) {
String projectPath = System.getProperty("user.dir");
//============================== 全域性配置
GlobalConfig gc = new GlobalConfig();
gc.setOutputDir(projectPath + "/springboot-mybatisplus/src/main/java")
.setActiveRecord(true)// 是否支援 AR
.setAuthor("fulin") //設定作者名字
.setFileOverride(true) //檔案覆蓋(全新檔案)
.setIdType(IdType.AUTO)//主鍵策略
.setBaseResultMap(true) //SQL 對映檔案
.setBaseColumnList(true)//SQL 片段
.setOpen(false);
//============================== 資料來源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setDbType(DbType.MARIADB)
.setUrl("jdbc:mariadb://localhost:3306/test")
.setDriverName("org.mariadb.jdbc.Driver")
.setUsername("root")
//.setSchemaName("public")
.setPassword("123456");
//==============================包配置
PackageConfig pc = new PackageConfig();
pc.setParent("com.maoxs")//配置父包路徑
.setModuleName("base")//配置業務包路徑
.setMapper("mapper")
.setEntity("entity")
.setService("service")
.setController("controller");
//.setServiceImpl("service.impl"); 會自動生成 impl,可以不設定
//============================== 自定義配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
List<FileOutConfig> focList = new ArrayList<>();
focList.add(new FileOutConfig("/templates/mapper.xml.ftl") {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定義輸入檔名稱
return projectPath + "/springboot-mybatisplus/src/main/resources/mapper/" + pc.getModuleName()
+ "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
cfg.setFileOutConfigList(focList);
//============================== 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel)//設定命名規則 underline_to_camel 底線變駝峰
.setColumnNaming(NamingStrategy.underline_to_camel)//設定設定列命名 underline_to_camel 底線變駝峰
//.setSuperEntityClass("com.maoxs.pojo")//設定繼承類
//.setSuperControllerClass("com.maoxs.controller")//設定繼承類
.setEntityLombokModel(true)//是否加入lombok
.setInclude(tableName)//設定表名
//.setSuperEntityColumns("id") //設定超級超級列
.setControllerMappingHyphenStyle(true)//設定controller對映聯字元
.setTablePrefix(pc.getModuleName() + "_");//表的字首
//============================== 生成配置
AutoGenerator mpg = new AutoGenerator();
mpg.setCfg(cfg)
.setTemplate(new TemplateConfig().setXml(null))
.setGlobalConfig(gc)
.setDataSource(dsc)
.setPackageInfo(pc)
.setStrategy(strategy)
// 選擇 freemarker 引擎需要指定如下加,注意 pom 依賴必須有!
.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute();
}
public static void main(String[] args) {
Generator(new String[]{"x", "xx"});
}
}
這只是生成程式碼的工作,然後呢為了確保你生成的Mapper介面可以掃描到,還需要這樣的一個配置
package com.maoxs.conf;
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;
/**
* @author fulin
* @since 2018-09-10
*/
@Configuration
@MapperScan("com.maoxs.base.mapper")
public class MybatisPlusConfig {
}
@MapperScan 是用來掃描你mapper所在的包,多個包的話英文逗號隔開即可。剩下的大多數MybatisPlus的配置基本都是在這裡配置。
crud
這邊就闡述什麼表名什麼的,可以自己嘗試建立,這裡只提到怎麼使用,重要的配置我會貼出.
這邊呢就貼出一個簡單的增刪改查的測試類。
package com.maoxs.crud;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.maoxs.SpringbootMybatisplusApplicationTests;
import com.maoxs.base.entity.User;
import com.maoxs.base.mapper.UserMapper;
import org.junit.Assert;
import org.junit.Test;
import javax.annotation.Resource;
public class CrudTest extends SpringbootMybatisplusApplicationTests {
@Resource
private UserMapper userMapper;
@Test
public void Insert() {
User user = new User();
user.setAge(17);
user.setName("我是付林");
int num = userMapper.insert(user);
Assert.assertTrue(num > 0);
System.out.println("插入成功Id為" + user.getId());
}
@Test
public void Delete() {
Assert.assertTrue(userMapper.deleteById(14L) > 0);
Assert.assertTrue(userMapper.delete(new QueryWrapper<User>().lambda().eq(User::getName, "我是付林")) > 0);
}
@Test
public void Update() {
Assert.assertTrue(userMapper.updateById(new User().setId(1L).setAge(100).setName("我是付林")) > 0);
Assert.assertTrue(userMapper.update(new User(),
new UpdateWrapper<User>().lambda().set(User::getAge, 2).eq(User::getId, 2)
) > 0);
}
@Test
public void Select() {
Assert.assertEquals("cfulin", userMapper.selectById(3L).getName());
User user = userMapper.selectOne(new QueryWrapper<User>().lambda().eq(User::getId, 2));
Assert.assertEquals("付林1", user.getName());
Assert.assertTrue(2 == user.getAge());
}
}
這裡呢說明一下Wrapper 這可是個好玩的東西,相當於QBC那樣的動態sql拼接,這裡mybatisplus是3.0以上的版本,算是一個大版本,這裡呢條件的拼接呢都使用了 lambda 方式。如果不想使用,比如new QueryWrapper().lambda().eq(User::getId, 2) 可以寫為new QueryWrapper().eq(“id”, 2)
AR(ActiveRecord)
在web後臺開發領域,經常會遇到應用程式操作資料庫的場景,目前市面上存在的資料庫包括mysql、postgresql、oracle、sqlite等,為了遮蔽不同資料庫的差異,產生了ORM(Object-Relational-Mapping),在實現層面,又分為DataMapper和ActiveRecord兩種。mybatis對其也有支援
package com.maoxs.crud;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.maoxs.SpringbootMybatisplusApplicationTests;
import com.maoxs.base.entity.User;
import org.junit.Test;
/**
* @program: plus
* @description: Ar測試
* @author: fulin
* @create: 2018-09-24 12:13
**/
public class ArTest extends SpringbootMybatisplusApplicationTests {
@Test
public void ARInsert() {
User user = new User();
user.setName("fulinlin");
user.setAge(20);
//欄位不為空插入
user.insert();
//ID為空插入,否則為更新
user.insertOrUpdate();
}
@Test
public void ARUpdate() {
User user = new User();
user.setName("快樂貓");
user.setAge(24);
user.setId(3L);
//ID 修改
user.updateById();
//條件修改
user.update(new UpdateWrapper<User>().lambda().eq(User::getId, "5"));
}
@Test
public void ARSelect() {
User user = new User();
user.setId(4L);
//setId
user.selectById();
//直接鍵入 Id
user.selectById(24);
//條件
user.selectCount(new QueryWrapper<User>().lambda().eq(User::getId, 0));
//查詢所有
user.selectAll();
//查詢總記錄數
user.selectList(new QueryWrapper<User>().lambda().eq(User::getName, "fulinlin"));
//查詢一個
user.selectOne(new QueryWrapper());
//分頁
user.selectPage(new Page<>(1, 2), new QueryWrapper<>());
}
@Test
public void ARDelete() {
//刪除不存在的資料 在邏輯上也是成功的,返回結果 true
User user = new User();
user.setId(4L);
user.deleteById();
user.deleteById(31);
//條件刪除
user.delete(new QueryWrapper<User>().lambda().eq(User::getId, 3L));
}
}
分頁
MybatisPlus也提供了一個分頁外掛,使用起來及其方便,這裡說明兩種情況下的分頁,一種是自帶的,一種是自定義的。不過呢做這些之前你要先引入這個配置。
/**
* 分頁外掛
* @return
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
普通分頁
普通分頁需要傳遞一個page 的物件,裡面說明你當前頁和分頁的大小,用起來也是非常的舒服。
@Test
public void Page() {
Page<User> page = new Page<>(1, 5);
IPage<User> userIPage = userMapper.selectPage(page, null);
System.out.println(Collections.unmodifiableCollection(userIPage.getRecords()));
}
自定義分頁
如果在某些情況下需要自己定義分頁,那怎麼辦呢
首先呢在mapper介面中定義一個方法
/**
* 3.x 的 page 可以進行取值,多個入參記得加上註解
* 自定義 page 類必須放在入參第一位
* 返回值可以用 IPage<T> 接收 也可以使用入參的 MyPage<T> 接收
* todo 目前使用註解會報錯,寫在 xml 裡就沒事
* @param myPage 自定義 page
* @return 分頁資料
*/
MyPage<User> mySelectPage(@Param("pg") MyPage<User> myPage);
然後呢你需要在xml中寫一個select做繫結
<select id="mySelectPage" resultType="com.maoxs.base.entity.User">
select * from user where name like '%' #{pg.selectStr} '%'and age > #{pg.selectInt}
</select>
這裡呢,把用到的MyPage貼出
package com.maoxs.model;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* @author fulin
* @since 2018-09-10
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
public class MyPage<T> extends Page<T> {
private static final long serialVersionUID = 5194933845448697148L;
private Integer selectInt;
private String selectStr;
public MyPage(long current, long size)