springboot+mybatis+mybaits plus 整合與基本應用

廣州蘆葦科技Java開發團隊發表於2018-12-03

引言

spring framework所支援的orm框架中,mybatis相比 hibernatespring本身提供的支援是相對少的,這在開發過程中對使用mybatis進行開發的程式設計師來說無疑產生很多難處。

為此,開源上也產生了很多三方對mybatis的一些增強工具,比如ourbatismybatis-generator等等。這篇我們主要來說下功能豐富、現在還在迭代的一款國人開發的增強工具mybatis-plus。就像官方文件說的那樣

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

可以看出,mybatis-plus是了為了提高效率和簡化配置而生的。下面就來展示下在springboot下如何整合mybatis-plus

準備工作

首先是建立一個springboot工程

引入相關依賴(springboot相關、mybaitsmybatis-plus等等)

<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- springboot對mybaits的自動配置依賴 -->
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.2</version>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<!-- mybatis-plus相關依賴 -->
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-boot-starter</artifactId>
			<version>3.0.5</version>
		</dependency>
	</dependencies>
複製程式碼

使用mybaits-plus的程式碼生成器對映生成程式碼,我們這裡所使用的資料庫為mysql。這個在另外一篇文章上說明,這裡就不講述了。

在這裡,mybaits-plus提供了BaseMapperBaseService這些基類來提供一些操作的支援,比如

  • save(T t)
  • saveOrUpdate(T t)
  • update(T t, Wrapper<T> wrapper)
  • page(IPage<T> page, Wrapper<T> queryWrapper)

等等。

下面,我們就簡單介紹下springboot中怎麼運用mybaits-plus

配置

首先是說到配置,這裡預設以yml檔案來進行對mybaits-plus的配置。

mybatis-plus:
  #MyBatis Mapper 所對應的 XML 檔案位置
  mapper-locations: classpath*:mapper/*.xml
  #  MyBaits 別名包掃描路徑,通過該屬性可以給包中的類註冊別名,
  #註冊後在 Mapper 對應的 XML 檔案中可以直接使用類名,而不用使用全限定的類名(即 XML 中呼叫的時候不用包含包名)
  typeAliasesPackage: com.luwei.models
  # 與 typeAliasesPackage 一起使用,僅掃描以該類作為父類的類
  # type-aliases-super-type: java.lang.Object
  # 配置掃描通用列舉,配置該屬性,會對列舉類進行注入
  typeEnumsPackage: com.luwei.demo.mybatisplusdemo.envm
  # 該包下的類註冊為自定義型別轉換處理類,用於屬性型別轉換
  # type-handlers-package: com.luwei.demo.mybatisplusdemo.handler
  # 指定 mybatis 處理器
  # executorType: simple
  
  configuration:
    #使用駝峰法對映屬性,配置這個resultType可以對映
    map-underscore-to-camel-case: true
  global-config:
    db-config:
	  # 配置表明字首,例如表設計時錶名為tb_manager,對應entity為Manager
      table-prefix: tb_
	  #邏輯已刪除值
	  logic-delete-value: 1 
	  #邏輯未刪除值
      logic-not-delete-value: 0 
	  # 是否開啟like查詢,即對 stirng 欄位是否使用 like,預設不開啟
	  # column-like: false
	  
logging:
  level:
  	# 日誌級別,顯示操作sql
    com.luwei.demo.mybatisplusdemo.mapper: debug
複製程式碼

基本上這些配置都能滿足一般的應用了。

CRUD 介面

上面說到,BaseMapperBaseService已經實現了一些基本操作,下面簡單說下這些介面的用法

查詢

查詢中Mybatis-plus提供多種封裝好的方式,包括對主鍵查詢、指定條件查詢、分頁查詢等。

Manager manager1 = managerService.getById(1);
Assert.assertNotNull(manager1);

LambdaQueryWrapper<Manager> wrapper = new LambdaQueryWrapper<Manager>().like(Manager::getName, "na");
List<Manager> managerList = managerService.list(wrapper);
Assert.assertFalse(managerList.isEmpty());

//先配置page分頁外掛配置
Page page = new Page<>(1, 2);
IPage<Manager> managerPage = managerService.page(page, wrapper);
Assert.assertFalse(managerPage.getRecords().isEmpty());

//獲取map物件
Map<String, Object> map = managerService.getMap(wrapper);
System.out.println(map);

Object obj = managerService.getObj(wrapper);
System.out.println(obj);

try {
	//若有多個結果,丟擲異常
	managerService.getOne(wrapper, true);
}catch (RuntimeException e) {
	e.printStackTrace();
	System.out.println("異常捕獲");
}
複製程式碼

增加

save(T t)方法,實際就是將物件持久化到資料庫中,這裡會產生一條insert語句,並執行。

@Transactional
public void add() {
	Manager manager = new Manager();
	manager.setAccount("account");
	manager.setRole(RoleEnum.ROOT);
	manager.setPassword("password");
	manager.setName("name");

	save(manager);
}
複製程式碼

日誌輸出:

==>  Preparing: INSERT INTO tb_manager ( account, name, password, role ) VALUES ( ?, ?, ?, ? ) 
==> Parameters: account(String), name(String), password(String), 0(Integer)
<==    Updates: 1
複製程式碼

更改

提供的updateupdateOrSaveupateById都可以實現資料更新。 各自的區別在於

  • update:根據條件篩選並更新指定欄位
  • updateOrSave:對物件進行更新,對未儲存的物件進行插入
  • updateById:根據id對物件進行更新
@Transactional
public void updateManager() {
	Manager manager = getById(1);
	manager.setName("testUpdate");
	updateById(manager);

	//saveOrUpdate(manager);

	//update(new Manager(), new UpdateWrapper<Manager>().lambda().set(Manager::getName, "test").eq(Manager::getManagerId, 1));
}
複製程式碼

刪除

在刪除中,除了一般的物理刪除外,mybaits-plus還提供了邏輯刪除的支援。

如果需要使用邏輯刪除,除了上述配置外,還需要新增一個配置bean來裝配外掛。

@Bean
public ISqlInjector sqlInjector() {
	return new LogicSqlInjector();
}
複製程式碼

這樣在使用刪除時,會對記錄中標記為刪除標識的欄位進行更改,在查詢和更新時,也只是針對刪除標識為未刪除的記錄。

public void deleteManager() {
	LambdaQueryWrapper<Manager> wrapper = new LambdaQueryWrapper<Manager>().eq(Manager::getManagerId, 4);
	System.out.println(baseMapper.delete(wrapper));

	/*Map<String, Object> deleteMap = new HashMap<>();
	//使用表欄位名
	deleteMap.put("manager_id", 4);
	baseMapper.deleteByMap(deleteMap);*/

	/*baseMapper.deleteById(4);*/

	//屬於service下的方法
	/*LambdaQueryWrapper<Manager> wrapper = new LambdaQueryWrapper<Manager>().eq(Manager::getManagerId, 4);
	remove(wrapper);*/
}
複製程式碼

條件構造器

在查詢、更新、刪除這些操作中,我們往往需要定義條件或者設定屬性,也就是where子句和set語句,如果不是直接通過sql去處理,在mybatis-plus中,也提供了一種包裝器來實現。

AbstractWrapper囊括了幾乎滿足日常需要的條件操作,和jpaspecification一樣,它支援動態產生條件,也支援使用lambda表示式去組裝條件。他是QueryWrapperUpdateWrapper的父類

一些常用的wrapper方法

Map<String, Object> conditionMap = new HashMap<>();
//使用表欄位名
conditionMap.put("name", "name");
conditionMap.put("manager_id", 1);
//allEq(BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)
//filter:忽略欄位
//null2IsNull:為true則在map的value為null時呼叫 isNull 方法,為false時則忽略value為null的
QueryWrapper<Manager> queryWrapper = new QueryWrapper<Manager>().allEq((r, v) -> r.indexOf("name") > 0, conditionMap, true);
managerService.list(queryWrapper);
複製程式碼
//like(R column, Object val) -> column like '%na%'
//likeLeft -> column like '%na'
//likeRight -> column like 'na%'
//and(Function<This, This> func) -> and (column = val)
LambdaQueryWrapper<Manager> lambdaWrapper = new LambdaQueryWrapper<Manager>().like(Manager::getName, "na").and((r) -> r.eq(Manager::getDisabled, false));
managerService.list(lambdaWrapper);
複製程式碼
//orderBy(boolean condition, boolean isAsc, R... columns) -> order by columns isAsc
LambdaQueryWrapper<Manager> lambdaWrapper = new LambdaQueryWrapper<Manager>().orderBy(true, false, Manager::getManagerId);
managerService.list(lambdaWrapper);
複製程式碼
//select 用於挑選屬性
LambdaQueryWrapper<Manager> lambdaWrapper = new LambdaQueryWrapper<Manager>().select(Manager::getName, Manager::getDisabled);
managerService.list(lambdaWrapper);
複製程式碼
//set(R column, Object val) -> update T set colunm = val
managerService.update(new Manager(), new UpdateWrapper<Manager>().lambda().set(Manager::getName, "newName").eq(Manager::getManagerId, 4));
複製程式碼

諸如還有其他像eqlteisNullorderByorexists等限定方法,這裡就不一一介紹了。

其他

分頁外掛

引入分頁,除了配置上,還需要新增外掛bean

@Bean
public PaginationInterceptor paginationInterceptor() {
	return new PaginationInterceptor();
}
複製程式碼

在使用時,自定義查詢中,引數中新增Page物件,並要求放在引數中的第一位

IPage<ManagerPageVO> selectManagerPage(Page page, @Param("roleEnum")RoleEnum roleEnum, @Param("managerId") Integer managerId, @Param("name") String name);
複製程式碼
<select id="selectManagerPage" resultType="com.luwei.pojos.manager.ManagerPageVO">
  <![CDATA[
	select manager_id, account, name, role, disabled, create_time, last_login_time from tb_manager where role = #{roleEnum} and deleted = false
  ]]>
	<if test="name != null">
		<![CDATA[
		  and (name like CONCAT('%',#{name},'%') or account like CONCAT('%',#{name},'%'))
		]]>
	</if>
	<if test="managerId != null">
		<![CDATA[
		  and manager_id = #{managerId}
		]]>
	</if>
</select>
<select id="selectForSpecialCondition" resultType="com.luwei.entity.Manager">
	select
	<include refid="Base_Column_List" />
	from tb_manager
	where name like '%admin%'
</select>
複製程式碼

主鍵配置

mybaits-plus中,有多種主鍵生成策略,它們分別是

  • IdType.AUTO:資料庫id自增
  • IdType.INPUT:使用者輸入
  • IdType.ID_WORKER:唯一ID,自動填充(預設)
  • IdType.UUID:唯一ID,自動填充

由於我們公司使用的是mysql本身的自增策略,所以選擇使用 IdType.AUTO。

@ApiModelProperty(value = "管理員id")
@TableId(value = "manager_id", type = IdType.AUTO)
private Integer managerId;
複製程式碼

至於 ID_WORKER 和 UUID 的不同,在於它們的唯一鍵生成策略不同,ID_WORKER 按照官方的介紹,是使用Sequence作為基礎產生唯一鍵。

列舉屬性

為了讓mybaits更好地使用列舉,mybatis-plus提供了列舉掃描注入

具體配置,首先是配置掃描路徑

# 配置掃描通用列舉,配置該屬性,會對列舉類進行注入
typeEnumsPackage: com.luwei.demo.mybatisplusdemo.envm
複製程式碼

在列舉類中實現介面,用於獲取具體值

//實現此介面用於獲取值
public interface BaseEnum<E extends Enum<?>, T> {
    T getValue();
    String getDisplayName();
}
複製程式碼

這樣,基本上就可以在mybatis上使用列舉型別了。

總結

上面描述了mybitis-plus基本用法,其實除了以上,它還提供了很多方便的外掛和應用,包括xml熱載入、樂觀鎖外掛、效能分析外掛等,這些由於篇幅和主題的原因我就不在這裡闡述了。希望這篇可以帶你很快地上手這個當前熱門的mybaits增強工具,提高開發效率。

juejin segmentfault V2EX zhihu cnblog oschina github jianshu 蘆葦科技
掘金 segmentfault V2EX 知乎 部落格園 開源中國 github 簡書 蘆葦科技

廣州蘆葦科技Java開發團隊

蘆葦科技-廣州專業軟體外包服務公司

提供微信小程式、APP應用研發、UI設計等專業服務,專注於網際網路產品諮詢、品牌設計、技術研發等領域

訪問 www.talkmoney.cn 瞭解更多

萬能說明書 | 早起日記Lite | 凹凸桌布 | 言財

springboot+mybatis+mybaits plus 整合與基本應用

相關文章