java開發(fā)工具下載海口網(wǎng)站關(guān)鍵詞優(yōu)化
大家在日常開發(fā)中應(yīng)該能發(fā)現(xiàn),單表的CRUD功能代碼重復(fù)度很高,也沒有什么難度。而這部分代碼量往往比較大,開發(fā)起來(lái)比較費(fèi)時(shí)。
因此,目前企業(yè)中都會(huì)使用一些組件來(lái)簡(jiǎn)化或省略單表的CRUD開發(fā)工作。目前在國(guó)內(nèi)使用較多的一個(gè)組件就是MybatisPlus.
官方網(wǎng)站如下:
當(dāng)然,MybatisPlus不僅僅可以簡(jiǎn)化單表操作,而且還對(duì)Mybatis的功能有很多的增強(qiáng)??梢宰屛覀兊拈_發(fā)更加的簡(jiǎn)單,高效。
通過(guò)今天的學(xué)習(xí),我們要達(dá)成下面的目標(biāo):
-
能利用MybatisPlus實(shí)現(xiàn)基本的CRUD
-
會(huì)使用條件構(gòu)建造構(gòu)建查詢和更新語(yǔ)句
-
會(huì)使用MybatisPlus中的常用注解
-
會(huì)使用MybatisPlus處理枚舉、JSON類型字段
-
會(huì)使用MybatisPlus實(shí)現(xiàn)分頁(yè)
為了方便測(cè)試,我們先創(chuàng)建一個(gè)新的項(xiàng)目,并準(zhǔn)備一些基礎(chǔ)數(shù)據(jù)。
1.環(huán)境準(zhǔn)備
復(fù)制課前資料提供好的一個(gè)項(xiàng)目到你的工作空間(不要包含空格和特殊字符):
然后用你的IDEA工具打開,項(xiàng)目結(jié)構(gòu)如下:
注意配置一下項(xiàng)目的JDK版本為JDK11。首先點(diǎn)擊項(xiàng)目結(jié)構(gòu)設(shè)置:
在彈窗中配置JDK:
接下來(lái),要導(dǎo)入兩張表,在課前資料中已經(jīng)提供了SQL文件:
對(duì)應(yīng)的數(shù)據(jù)庫(kù)表結(jié)構(gòu)如下:
最后,在application.yaml
中修改jdbc參數(shù)為你自己的數(shù)據(jù)庫(kù)參數(shù):
spring:datasource:url: jdbc:mysql://127.0.0.1:3306/mp?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghaidriver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: MySQL123
logging:level:com.itheima: debugpattern:dateformat: HH:mm:ss
2.快速開始
比如我們要實(shí)現(xiàn)User表的CRUD,只需要下面幾步:
-
引入MybatisPlus依賴
-
定義Mapper
2.1引入依賴
MybatisPlus提供了starter,實(shí)現(xiàn)了自動(dòng)Mybatis以及MybatisPlus的自動(dòng)裝配功能,坐標(biāo)如下:
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.1</version>
</dependency>
由于這個(gè)starter包含對(duì)mybatis的自動(dòng)裝配,因此完全可以替換掉Mybatis的starter。 最終,項(xiàng)目的依賴如下:
<dependencies><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.1</version></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></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>
</dependencies>
2.2定義Mapper
為了簡(jiǎn)化單表CRUD,MybatisPlus提供了一個(gè)基礎(chǔ)的BaseMapper
接口,其中已經(jīng)實(shí)現(xiàn)了單表的CRUD:
因此我們自定義的Mapper只要實(shí)現(xiàn)了這個(gè)BaseMapper
,就無(wú)需自己實(shí)現(xiàn)單表CRUD了。 修改mp-demo中的com.itheima.mp.mapper
包下的UserMapper
接口,讓其繼承BaseMapper
:
代碼如下:
package com.itheima.mp.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.mp.domain.po.User;public interface UserMapper extends BaseMapper<User> {
}
2.3測(cè)試
新建一個(gè)測(cè)試類,編寫幾個(gè)單元測(cè)試,測(cè)試基本的CRUD功能:
package com.itheima.mp.mapper;import com.itheima.mp.domain.po.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.time.LocalDateTime;
import java.util.List;@SpringBootTest
class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testvoid testInsert() {User user = new User();user.setId(5L);user.setUsername("Lucy");user.setPassword("123");user.setPhone("18688990011");user.setBalance(200);user.setInfo("{\"age\": 24, \"intro\": \"英文老師\", \"gender\": \"female\"}");user.setCreateTime(LocalDateTime.now());user.setUpdateTime(LocalDateTime.now());userMapper.insert(user);}@Testvoid testSelectById() {User user = userMapper.selectById(5L);System.out.println("user = " + user);}@Testvoid testSelectByIds() {List<User> users = userMapper.selectBatchIds(List.of(1L, 2L, 3L, 4L, 5L));users.forEach(System.out::println);}@Testvoid testUpdateById() {User user = new User();user.setId(5L);user.setBalance(20000);userMapper.updateById(user);}@Testvoid testDelete() {userMapper.deleteById(5L);}
}
可以看到,在運(yùn)行過(guò)程中打印出的SQL日志,非常標(biāo)準(zhǔn):
11:05:01 INFO 15524 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
11:05:02 INFO 15524 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
11:05:02 DEBUG 15524 --- [ main] c.i.mp.mapper.UserMapper.selectById : ==> Preparing: SELECT id,username,password,phone,info,status,balance,create_time,update_time FROM user WHERE id=?
11:05:02 DEBUG 15524 --- [ main] c.i.mp.mapper.UserMapper.selectById : ==> Parameters: 5(Long)
11:05:02 DEBUG 15524 --- [ main] c.i.mp.mapper.UserMapper.selectById : <== Total: 1
user = User(id=5, username=Lucy, password=123, phone=18688990011, info={"age": 21}, status=1, balance=20000, createTime=Fri Jun 30 11:02:30 CST 2023, updateTime=Fri Jun 30 11:02:30 CST 2023)
3.常見注解
在剛剛的入門案例中,我們僅僅引入了依賴,繼承了BaseMapper就能使用MybatisPlus,非常簡(jiǎn)單。但是問題來(lái)了: MybatisPlus如何知道我們要查詢的是哪張表?表中有哪些字段呢?
大家回憶一下,UserMapper在繼承BaseMapper的時(shí)候指定了一個(gè)泛型:
泛型中的User就是與數(shù)據(jù)庫(kù)對(duì)應(yīng)的PO.
MybatisPlus就是根據(jù)PO實(shí)體的信息來(lái)推斷出表的信息,從而生成SQL的。默認(rèn)情況下:
-
MybatisPlus會(huì)把PO實(shí)體的類名駝峰轉(zhuǎn)下劃線作為表名
-
MybatisPlus會(huì)把PO實(shí)體的所有變量名駝峰轉(zhuǎn)下劃線作為表的字段名,并根據(jù)變量類型推斷字段類型
-
MybatisPlus會(huì)把名為id的字段作為主鍵
但很多情況下,默認(rèn)的實(shí)現(xiàn)與實(shí)際場(chǎng)景不符,因此MybatisPlus提供了一些注解便于我們聲明表信息。
3.1@TableName
說(shuō)明:
-
描述:表名注解,標(biāo)識(shí)實(shí)體類對(duì)應(yīng)的表
-
使用位置:實(shí)體類
示例:
@TableName("user")
public class User {private Long id;private String name;
}
TableName注解除了指定表名以外,還可以指定很多其它屬性:
屬性 | 類型 | 必須指定 | 默認(rèn)值 | 描述 |
value | String | 否 | "" | 表名 |
schema | String | 否 | "" | schema |
keepGlobalPrefix | boolean | 否 | false | 是否保持使用全局的 tablePrefix 的值(當(dāng)全局 tablePrefix 生效時(shí)) |
resultMap | String | 否 | "" | xml 中 resultMap 的 id(用于滿足特定類型的實(shí)體類對(duì)象綁定) |
autoResultMap | boolean | 否 | false | 是否自動(dòng)構(gòu)建 resultMap 并使用(如果設(shè)置 resultMap 則不會(huì)進(jìn)行 resultMap 的自動(dòng)構(gòu)建與注入) |
excludeProperty | String[] | 否 | {} | 需要排除的屬性名 @since 3.3.1 |
3.2@TableId
說(shuō)明:
-
描述:主鍵注解,標(biāo)識(shí)實(shí)體類中的主鍵字段
-
使用位置:實(shí)體類的主鍵字段
示例:
@TableName("user")
public class User {@TableIdprivate Long id;private String name;
}
TableId
注解支持兩個(gè)屬性:
屬性 | 類型 | 必須指定 | 默認(rèn)值 | 描述 |
---|---|---|---|---|
value | String | 否 | "" | 表名 |
type | Enum | 否 | IdType.NONE | 指定主鍵類型 |
IdType
支持的類型有:
值 | 描述 |
---|---|
AUTO | 數(shù)據(jù)庫(kù) ID 自增 |
NONE | 無(wú)狀態(tài),該類型為未設(shè)置主鍵類型(注解里等于跟隨全局,全局里約等于 INPUT) |
INPUT | insert 前自行 set 主鍵值 |
ASSIGN_ID | 分配 ID(主鍵類型為 Number(Long 和 Integer)或 String)(since 3.3.0),使用接口IdentifierGenerator的方法nextId(默認(rèn)實(shí)現(xiàn)類為DefaultIdentifierGenerator雪花算法) |
ASSIGN_UUID | 分配 UUID,主鍵類型為 String(since 3.3.0),使用接口IdentifierGenerator的方法nextUUID(默認(rèn) default 方法) |
| 分布式全局唯一 ID 長(zhǎng)整型類型(please use ASSIGN_ID) |
| 32 位 UUID 字符串(please use ASSIGN_UUID) |
| 分布式全局唯一 ID 字符串類型(please use ASSIGN_ID) |
這里比較常見的有三種:
-
AUTO
:利用數(shù)據(jù)庫(kù)的id自增長(zhǎng) -
INPUT
:手動(dòng)生成id -
ASSIGN_ID
:雪花算法生成Long
類型的全局唯一id,這是默認(rèn)的ID策略
3.3@TableField
說(shuō)明:
描述:普通字段注解
示例:
@TableName("user")
public class User {@TableIdprivate Long id;private String name;private Integer age;@TableField("isMarried")private Boolean isMarried;@TableField("concat")private String concat;
}
一般情況下我們并不需要給字段添加@TableField
注解,一些特殊情況除外:
-
成員變量名與數(shù)據(jù)庫(kù)字段名不一致
-
成員變量是以
isXXX
命名,按照JavaBean
的規(guī)范,MybatisPlus
識(shí)別字段時(shí)會(huì)把is
去除,這就導(dǎo)致與數(shù)據(jù)庫(kù)不符。 -
成員變量名與數(shù)據(jù)庫(kù)一致,但是與數(shù)據(jù)庫(kù)的關(guān)鍵字沖突。使用
@TableField
注解給字段名添加````轉(zhuǎn)義
支持的其它屬性如下:
屬性 | 類型 | 必填 | 默認(rèn)值 | 描述 |
value | String | 否 | "" | 數(shù)據(jù)庫(kù)字段名 |
exist | boolean | 否 | true | 是否為數(shù)據(jù)庫(kù)表字段 |
condition | String | 否 | "" | 字段 where 實(shí)體查詢比較條件,有值設(shè)置則按設(shè)置的值為準(zhǔn),沒有則為默認(rèn)全局的 %s=#{%s},參考(opens new window) |
update | String | 否 | "" | 字段 update set 部分注入,例如:當(dāng)在version字段上注解update="%s+1" 表示更新時(shí)會(huì) set version=version+1 (該屬性優(yōu)先級(jí)高于 el 屬性) |
insertStrategy | Enum | 否 | FieldStrategy.DEFAULT | 舉例:NOT_NULL insert into table_a(<if test="columnProperty != null">column</if>) values (<if test="columnProperty != null">#{columnProperty}</if>) |
updateStrategy | Enum | 否 | FieldStrategy.DEFAULT | 舉例:IGNORED update table_a set column=#{columnProperty} |
whereStrategy | Enum | 否 | FieldStrategy.DEFAULT | 舉例:NOT_EMPTY where <if test="columnProperty != null and columnProperty!=''">column=#{columnProperty}</if> |
fill | Enum | 否 | FieldFill.DEFAULT | 字段自動(dòng)填充策略 |
select | boolean | 否 | true | 是否進(jìn)行 select 查詢 |
keepGlobalFormat | boolean | 否 | false | 是否保持使用全局的 format 進(jìn)行處理 |
jdbcType | JdbcType | 否 | JdbcType.UNDEFINED | JDBC 類型 (該默認(rèn)值不代表會(huì)按照該值生效) |
typeHandler | TypeHander | 否 | 類型處理器 (該默認(rèn)值不代表會(huì)按照該值生效) | |
numericScale | String | 否 | "" | 指定小數(shù)點(diǎn)后保留的位數(shù) |
4.常見配置
MybatisPlus也支持基于yaml文件的自定義配置,詳見官方文檔:
大多數(shù)的配置都有默認(rèn)值,因此我們都無(wú)需配置。但還有一些是沒有默認(rèn)值的,例如:
-
實(shí)體類的別名掃描包
-
全局id類型
mybatis-plus:type-aliases-package: com.itheima.mp.domain.poglobal-config:db-config:id-type: auto # 全局id類型為自增長(zhǎng)
需要注意的是,MyBatisPlus也支持手寫SQL的,而mapper文件的讀取地址可以自己配置:
mybatis-plus:mapper-locations: "classpath*:/mapper/**/*.xml" # Mapper.xml文件地址,當(dāng)前這個(gè)是默認(rèn)值。
可以看到默認(rèn)值是classpath*:/mapper/**/*.xml
,也就是說(shuō)我們只要把mapper.xml文件放置這個(gè)目錄下就一定會(huì)被加載。
例如,我們新建一個(gè)UserMapper.xml
文件:
?然后在其中定義一個(gè)方法:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mp.mapper.UserMapper"><select id="queryById" resultType="User">SELECT * FROM user WHERE id = #{id}</select>
</mapper>
然后在測(cè)試類UserMapperTest
中測(cè)試該方法:
@Test
void testQuery() {User user = userMapper.queryById(1L);System.out.println("user = " + user);
}