亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

MyBatis-Plus實(shí)用篇超完整教程

 更新時(shí)間:2025年02月17日 12:19:21   作者:冬天vs不冷  
MyBatis-Plus是一個(gè)MyBatis的增強(qiáng)工具,提供了許多便捷的功能,簡(jiǎn)化了開(kāi)發(fā)流程,同時(shí),MyBatis-Plus提供了鏈?zhǔn)讲樵?xún)與修改、靜態(tài)工具類(lèi)、自定義SQL、IPage的泛型轉(zhuǎn)換、ActiveRecord等擴(kuò)展功能,以及分頁(yè)插件和MyBatisX插件等插件,進(jìn)一步提高了開(kāi)發(fā)效率,感興趣的朋友一起看看吧

一、基礎(chǔ)組件

簡(jiǎn)介

  • MyBatis-Plus (opens new window)(簡(jiǎn)稱(chēng) MP)是一個(gè) MyBatis (opens new window)的增強(qiáng)工具
  • 在MyBatis 的基礎(chǔ)上只做增強(qiáng)不做改變,為簡(jiǎn)化開(kāi)發(fā)、提高效率而生

1、BaseMapper接口API

  • BaseMapper是MyBatis-Plus提供的模板mapper,其中包含了基本的CRUD方法,泛型為操作的實(shí)體類(lèi)型
  • Mapper繼承該接口后,無(wú)需編寫(xiě) mapper.xml 文件,即可獲得CRUD功能
  • BaseMapper接口,增刪改返回影響數(shù)據(jù)條數(shù)的Integer

BaseMapper中提供的CRUD方法

增加:insert

刪除:delete

  • 修改:update
  • update方法:entity實(shí)體對(duì)象某屬性為null,則不會(huì)修改此屬性

查詢(xún):select

  • selectObjs方法:只返回第一個(gè)字段的值
  • selectPage方法:分頁(yè)需要添加分頁(yè)插件,否則不生效

2、IService接口API

  • 封裝IService接口,進(jìn)一步封裝CRUD采用get查詢(xún)單行、remove刪除、list查詢(xún)集合、page分頁(yè)前綴命名方式
  • IService接口,增刪改返回是否操作成功的boolean
  • 泛型 T 為任意實(shí)體對(duì)象

IService中提供的CRUD方法

增加:save

刪除:remove

修改:update

新增或修改:主鍵存在則根據(jù)主鍵修改,主鍵不存在則新增

  • 查詢(xún):?jiǎn)蝹€(gè)get,集合listgetOne方法,多個(gè)拋出異常,第二個(gè)參數(shù)throwEx設(shè)置為false則獲取第一條數(shù)據(jù)

查詢(xún)記錄數(shù):count

分頁(yè)查詢(xún):page

  • 集合查詢(xún):listlistObjs方法,可以將查詢(xún)結(jié)果T類(lèi)型轉(zhuǎn)換成V類(lèi)型返回List<V>

3、創(chuàng)建Service層操作數(shù)據(jù)

Mapper接口:創(chuàng)建UserMapper對(duì)象并繼承BaseMapper

@Mapper
public interface UserMapper extends BaseMapper<User> {}

Service接口:創(chuàng)建UserService并繼承IService

/**
  * UserService繼承IService模板提供的基礎(chǔ)功能 
  */
public interface UserService extends IService<User> {}

Service實(shí)現(xiàn)類(lèi):創(chuàng)建UserService的實(shí)現(xiàn)類(lèi)并繼承ServiceImpl

/**
  * ServiceImpl實(shí)現(xiàn)了IService,提供了IService中基礎(chǔ)功能的實(shí)現(xiàn) 
  * 若ServiceImpl無(wú)法滿足業(yè)務(wù)需求,則可以使用自定的UserService定義方法,并在實(shí)現(xiàn)類(lèi)中實(shí)現(xiàn)
  */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService{}

二、常用注解

1、@TableName

  • 在實(shí)體類(lèi)類(lèi)型上添加@TableName(“t_user”),標(biāo)識(shí)實(shí)體類(lèi)對(duì)應(yīng)的表
  • 不加注解,默認(rèn)駝峰轉(zhuǎn)下劃線則是表明,如實(shí)體OrderInfo,則默認(rèn)對(duì)應(yīng)表名order_info
@Data
@TableName("t_user")
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

為實(shí)體類(lèi)所對(duì)應(yīng)的表名設(shè)置默認(rèn)的前綴,那么就不需要在每個(gè)實(shí)體類(lèi)上通過(guò)@TableName標(biāo)識(shí)實(shí)體類(lèi)對(duì)應(yīng)的表

mybatis-plus:
  global-config:
    db-config:
      # 設(shè)置實(shí)體類(lèi)所對(duì)應(yīng)的表的統(tǒng)一前綴
      table-prefix: t_

2、@TableId

2.1、value屬性

不加注解,默認(rèn)情況Long id就是主鍵如果想其他字段作為主鍵,且實(shí)體與數(shù)據(jù)庫(kù)字段不一致,則添加@TableId(value = “tid”)

@Data
public class User {
    @TableId(value = "tid")
    private Long uid;
    private String name;
    private Integer age;
    private String email;
}

2.2、type屬性

常用主鍵策略:

枚舉值描述
IdType.AUTO數(shù)據(jù)庫(kù)ID自增;該類(lèi)型請(qǐng)確保數(shù)據(jù)庫(kù)設(shè)置了ID自增,否則無(wú)效
IdType.INPUT用戶(hù)輸入ID;該類(lèi)型可以通過(guò)自己注冊(cè)自動(dòng)填充插件進(jìn)行填充
IdType.ASSIGN_ID(默認(rèn))主鍵類(lèi)型為number或string的雪花算法;只有當(dāng)插入對(duì)象ID 為空,才自動(dòng)填充
IdType.ASSIGN_UUID主鍵類(lèi)型為string,UUID.replace(“-”,“”);只有當(dāng)插入對(duì)象ID 為空,才自動(dòng)填充
IdType.NONE沒(méi)有設(shè)置主鍵類(lèi)型;跟隨全局;全局的主鍵策略如果沒(méi)有設(shè)置,默認(rèn)是雪花算法
@Data
public class User {
    @TableId(type = IdType.AUTO)
    private Long uid;
    private String name;
    private Integer age;
    private String email;
}

Mybatis-plus中的內(nèi)置雪花算法

  • 在某些情況下,我們想提前獲取這個(gè)ID,調(diào)用com.baomidou.mybatisplus.core.toolkit.IdWorker.getId()方法即可

3、@TableField

3.1、value屬性

  • 解決對(duì)象中字段名和數(shù)據(jù)庫(kù)不匹配(沒(méi)有遵循小駝峰或者完全不匹配)
//指定數(shù)據(jù)庫(kù)字段名稱(chēng)
@TableField(value = "email")
private string mail

解決關(guān)鍵字報(bào)錯(cuò)

// 執(zhí)行的sql語(yǔ)句就變成`關(guān)鍵字`,這樣sql就不會(huì)報(bào)錯(cuò)了
@TableField(value = "`desc`")
private string desc

3.2、exist屬性

解決對(duì)象中的屬性字段在表中不存在的問(wèn)題

@TableField(exist = false)
private Boolean checked;

3.3、select屬性

在查詢(xún)操作中某個(gè)字段值不想被查詢(xún)展示出來(lái)(比如密碼password),可使用此注解

@TableField(select = false)
private String password;

3.4、condition屬性

預(yù)處理where查詢(xún)條件

// 實(shí)體注解-實(shí)現(xiàn)模糊查詢(xún)
@TableField(condition = SqlCondition.LIKE)
private String name;
// 業(yè)務(wù)代碼
User user = new User();
user.setName("張");
userService.lambdaQuery(user).list();
// 打印sql
SELECT id,user_name,age FROM user WHERE name LIKE CONCAT('%',?,'%')

鏈?zhǔn)讲樵?xún)不生效(沒(méi)有模糊查詢(xún))

userService.lambdaQuery().eq(User::getName,"張").list();

3.5、update屬性

  • 預(yù)處理update set 部分
  • 方式一:@TableField(update="%s+1") update 表 set 字段=字段+1 where …
  • 方式二:@TableField(update="now()") 使用數(shù)據(jù)庫(kù)時(shí)間,update 表 set 字段=now() where …
// 方式三:
// 實(shí)體注解-實(shí)現(xiàn)修改字段時(shí)候,前后添加“**” 其中 %s 會(huì)填充為字段
@TableField(update = "CONCAT('**',%s,'**')")
private String name;
// 業(yè)務(wù)代碼
User user = new User();
user.setId(1);
user.setName("張三");
userService.updateById(user);
// 打印sql
UPDATE user SET name=CONCAT('**',name,'**') WHERE id=?

鏈?zhǔn)讲樵?xún)不生效(前后沒(méi)有填充**)

userService.lambdaQuery().eq(User::getName,"張").list();

3.6、fill屬性

解決每個(gè)數(shù)據(jù)庫(kù)表都有create_time 和 update_time字段,我們可以使用自動(dòng)填充功能維護(hù)這兩個(gè)字段

// 實(shí)體字段注解
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
// 枚舉類(lèi)
public enum FieldFill {
    /**
     * 默認(rèn)不處理
     */
    DEFAULT,
    /**
     * 插入填充字段
     */
    INSERT,
    /**
     * 更新填充字段
     */
    UPDATE,
    /**
     * 插入和更新填充字段
     */
    INSERT_UPDATE
}

創(chuàng)建MyMetaObjectHandler配置類(lèi),實(shí)現(xiàn)MetaObjectHandler接口

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
	Date date = new Date();
    @Override
    public void insertFill(MetaObject metaObject) {
        this.strictInsertFill(metaObject, "createTime", Date.class, date);
        this.strictInsertFill(metaObject, "updateTime", Date.class, date);
    }
    @Override
    public void updateFill(MetaObject metaObject) {
        this.strictUpdateFill(metaObject, "updateTime", Date.class, date);
    }
}

3.7、insertStrategy、updateStrategy、whereStrategy屬性

  • insertStrategy:當(dāng)insert操作時(shí),該字段拼接insert語(yǔ)句時(shí)的策略
  • updateStrategy:當(dāng)更新操作時(shí),該字段拼接set語(yǔ)句時(shí)的策略
  • whereStrategy:表示該字段在拼接where條件時(shí)的策略
public enum FieldStrategy {
    /**
     * 忽略判斷,所有字段都進(jìn)行更新和插入
     * 無(wú)論什么值,直接拼接,沒(méi)有值,則拼接null
     */
    IGNORED,
    /**
     * 只更新和插入非NULL值
     * 相當(dāng)于添加if判斷,不為null才操作
     * <if test="columnProperty != null">column=#{columnProperty}</if>
     */
    NOT_NULL,
    /**
     * 只更新和插入非NULL值且非空字符串
     * 相當(dāng)于添加if判斷,不為null而且不是空字符串才操作
     * <if test="columnProperty != null and columnProperty!=''">column=#{columnProperty}</if>
     */
    NOT_EMPTY,
    /**
     * 默認(rèn)NOT_NULL
     */
    DEFAULT,
    /**
     * 永遠(yuǎn)不進(jìn)行更新和插入
     */
    NEVER
}

3.8、typeHandler屬性

  • 類(lèi)型處理器,設(shè)置存入數(shù)據(jù)庫(kù)的類(lèi)型
  • 設(shè)置mysql數(shù)據(jù)庫(kù)字段info為json類(lèi)型,@TableField(typeHandler = JacksonTypeHandler.class)表示將UserInfo對(duì)象轉(zhuǎn)為json對(duì)象入庫(kù)
  • 此時(shí)user出現(xiàn)對(duì)象嵌套List<Address>,需要設(shè)置resultMap響應(yīng)對(duì)象,@TableName(autoResultMap = true)表示自動(dòng)映射resultMap

4、@TableLogic

  • 物理刪除:真實(shí)刪除,將對(duì)應(yīng)數(shù)據(jù)從數(shù)據(jù)庫(kù)中刪除,之后查詢(xún)不到此條被刪除的數(shù)據(jù)
  • 邏輯刪除:假刪除,將對(duì)應(yīng)數(shù)據(jù)中代表是否被刪除字段的狀態(tài)修改為“被刪除狀態(tài)”,之后在數(shù)據(jù)庫(kù)中仍舊能看到此條數(shù)據(jù)記錄

實(shí)現(xiàn)邏輯刪除

數(shù)據(jù)庫(kù)中創(chuàng)建邏輯刪除狀態(tài)列,設(shè)置默認(rèn)值為0

實(shí)體類(lèi)中添加邏輯刪除屬性

測(cè)試刪除功能,真正執(zhí)行的是修改

public void testDeleteById(){
    int result = userMapper.deleteById(1527472864163348482L);
    System.out.println(result > 0 ? "刪除成功!" : "刪除失?。?);
    System.out.println("受影響的行數(shù)為:" + result);
}

此時(shí)執(zhí)行查詢(xún)方法,查詢(xún)的結(jié)果為自動(dòng)添加條件is_deleted=0

public void testSelectList(){
    List<User> users = userMapper.selectList(null);
}

三、條件構(gòu)造器

1、wapper介紹

  • Wrapper:條件構(gòu)造抽象類(lèi),最頂端父類(lèi)
    • AbstractWrapper:用于查詢(xún)條件封裝,生成sql的where條件
      • QueryWrapper:查詢(xún)條件封裝
      • UpdateWrapper:update條件封裝
      • AbstractLambdaWrapper:使用Lambda語(yǔ)法
        • LambdaQueryWrapper:用于Lambda語(yǔ)法使用的查詢(xún)Wrapper
        • LambdaUpdateWrapper:用于Lambda語(yǔ)法更新Wrapper

2、構(gòu)造器常用方法

函數(shù)名說(shuō)明說(shuō)明/例子
eq等于=例:eq(“name”,“zhangsan”) —> name = ‘zhangsan’
ne不等于<>例:ne(“name”,“zhangsan”) —> name <> ‘zhangsan’
gt大于>例:gt(“age”,18) —> age > 18
ge大于等于>=例:ge(“age”,18) —> age >= 18
lt小于<例:lt(“age”,18) —> age < 18
le小于等于<=例:le(“age”,18) —> age <= 18
betweenbetween 值1 and 值2例:between(“age”,10,20) —> age between 10 and 20
notBetweennot between 值1 and 值2例:notBetween(“age”,10,20) —> age not between 10 and 20
likelike ‘%值%’例:like(“name”,“強(qiáng)”) —> name like ‘%強(qiáng)%’
notLikenot like ‘%值%’例:notLike(“name”,“強(qiáng)”) —> name not like ‘%強(qiáng)%’
likeLeftlike ‘%值’例:like(“name”,“飛”) —> name like ‘%強(qiáng)’
likeRightlike ‘值%’例:like(“name”,“王”) —> name like ‘王%’
isNull字段 is null例:isNull(“emal”) —> email is null
isNotNull字段 is not null例:isNotNull(“emal”) —> email is not null
in字段 in (值1,值2…)例:in(“age”,{10,18,30}) —> age in (10,18,30)
notIn字段 not in (值1,值2…)例:notIn(“age”,{10,18,30}) —> age not in (10,18,30)
inSql字段 in ( sql語(yǔ)句 )inSql(“id”, “select id from table where name like ‘%J%’”)
—> id in (select id from table where name like ‘%J%’)
notInSql字段 not in ( sql語(yǔ)句 )notInSql(“id”, “select id from table where name like ‘%J%’”)
—> id not in (select id from table where name like ‘%J%’)
groupBy分組 group by 字段,…例:groupBy(“id”,“name”) —> group by id,name
??注意:如果不查詢(xún)聚合函數(shù),默認(rèn)返回第一條數(shù)據(jù)
orderBy排序 ordery by 字段,…例:orderBy(true,true,“id”,“name”) —> order by id asc,name asc
orderByAsc升排序 order by 字段,… asc例:orderByAsc(“id”,“name”) —> order by id,name
orderByDesc降排序 order by 字段,… desc例:orderByDesc(“id”,“name”) —> order by id desc,name desc
havinghaving (sql語(yǔ)句)having(“sum(age) > {0}”,18) —> having sum(age) > 18
or拼接or例:eq(“id”,1).or().eq(“name”,“老王”) —> id =1 or name = ‘老王’
andand 嵌套例:and(i -> i.eq(“name”,“李白”).ne(“status”,“活著”))
—> and (name = ’李白‘ and status <> ‘活著’)
apply拼接sql**例:apply(“date_format(date_time,‘%Y-%m-%d’) = {0}”,“2002-08-08”)
—> date_fromat(date_time,‘%Y-%m-%d’) = ‘2008-08-08’
??注意:動(dòng)態(tài)入?yún)?duì)應(yīng){index}部分,直接寫(xiě)sql語(yǔ)句,有sql注入風(fēng)險(xiǎn)
last拼接到sql的最后例:last(“limit 5”)
注意事項(xiàng):只能調(diào)用一次,多次調(diào)用以最后一次為準(zhǔn),有sql注入風(fēng)險(xiǎn)
exists拼接exists (sql語(yǔ)句)例:exists(“select id from table where age = 1”)
not exists拼接not exists (sql語(yǔ)句)例:not exists(“select id from table where age = 1”)
nested正常嵌套 不帶and和or例:nested(i-> i.eq(“name”,“李華”).gt(“age”,20))
—> (name = “李華” and age > 20)

3、組裝條件示例

條件的優(yōu)先級(jí)

sql語(yǔ)句規(guī)則:and和or一起用,and優(yōu)先級(jí)高

 /** 組裝修改條件  將(年齡大于20并且用戶(hù)名中包含有a)或郵箱為null的用戶(hù)信息修改 **/
@Test
public void test01() {
    /*
        UPDATE t_user SET user_name=?, email=?
        age > ? AND user_name LIKE ? OR email IS NOT NULL
     */
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.gt("age", 20)
            .like("user_name", "a")
            .or()
            .isNotNull("email");
    User user = new User();
    user.setName("小明");
    user.setEmail("test@atguigu.com");
    int result = userMapper.update(user, queryWrapper);
    System.out.println("result = " + result);
}
/** 條件優(yōu)先級(jí)  將用戶(hù)名中包含a并且(年齡大于20或郵箱為null)的用戶(hù)信息修改 **/
@Test
public void test02() {
    // lambda中條件優(yōu)先級(jí)
    /*
        UPDATE t_user SET user_name=?, email=?
        WHERE user_name LIKE ? AND (age > ? OR email IS NULL)
     */
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.like("user_name", "a")
            .and(i -> i.gt("age", 20).or().isNull("email"));
    User user = new User();
    user.setName("小紅");
    user.setEmail("test@atguigu.com");
    int result = userMapper.update(user, queryWrapper);
    System.out.println("result = " + result);
}

Lambda表達(dá)式

@Test
public void test3() {
    /*
        SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user
        WHERE user_name LIKE ? AND age <= ?
     */
    String username = "a";
    Integer ageBegin = null;
    Integer ageEnd = 30;
    //組裝set子句
    LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
    //避免使用字符串表示字段,防止運(yùn)行時(shí)錯(cuò)誤
    queryWrapper.like(StringUtils.isNotBlank(username), User::getName, username)
            .gt(ageBegin != null, User::getAge, ageBegin)
            .le(ageEnd != null, User::getAge, ageEnd);
    List<User> list = userMapper.selectList(queryWrapper);
    list.forEach(System.out::println);
}
@Test
public void test4() {
    /*
        UPDATE t_user SET user_name=?,email=?
        WHERE user_name LIKE ? AND (age > ? OR email IS NULL)
     */
    LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
    updateWrapper.like(User::getName, "a")
            //lambda表達(dá)式內(nèi)的邏輯優(yōu)先運(yùn)算
            .and(i -> i.gt(User::getAge, 20).or().isNull(User::getEmail)); 
    updateWrapper.set(User::getName, "小黑").set(User::getEmail, "abc@atguigu.com");
    int result = userMapper.update(null, updateWrapper);
    System.out.println("result = " + result);
}

四、擴(kuò)展功能

1、鏈?zhǔn)讲樵?xún)與修改

IService接口中提供

  • 鏈?zhǔn)讲樵?xún):可以串著寫(xiě)多個(gè)條件
    • .one()結(jié)尾:查詢(xún)單條數(shù)據(jù)
    • .list()結(jié)尾:查詢(xún)多條數(shù)據(jù)
    • .count()結(jié)尾:查詢(xún)記錄數(shù)

 @Test
 public void test1(){
 	 // 單個(gè)查詢(xún),多個(gè)報(bào)錯(cuò)
     User user = userService.lambdaQuery().eq(User::getName, "Tom").one();
	 // 集合查詢(xún)
     List<User> userList = userService.lambdaQuery().like(User::getName, "J").eq(User::getAge,20).list();
     // 記錄數(shù)查詢(xún)
     Integer count = userService.lambdaQuery().like(User::getAge, 20).select(User::getName, User::getAge).count();
  }
  • 鏈?zhǔn)叫薷模嚎梢源鴮?xiě)多個(gè)條件
    • .update()結(jié)尾:修改set的字段(只修改set的字段,fill屬性更新填充屬性不會(huì)修改)
    • .update(entity)結(jié)尾:修改entity數(shù)據(jù)的字段
    • .remove()結(jié)尾:刪除數(shù)據(jù)

  @Test
  public void test2() {
	  // set修改某些屬性
      userService.lambdaUpdate().eq(User::getName, "Tom").set(User::getId, 110).set(User::getAge, 15).update();
      // 修改整個(gè)對(duì)象
      User user = new User();
      user.setId(110L);
      user.setAge(15);
      userService.lambdaUpdate().eq(User::getName, "Tom").update(user);
      // 根據(jù)名稱(chēng)刪除
      userService.lambdaUpdate().eq(User::getName, "Jack").remove();
   }

2、靜態(tài)工具類(lèi)Db

Service之間也會(huì)相互調(diào)用,為了避免出現(xiàn)循環(huán)依賴(lài)問(wèn)題,MybatisPlus提供一個(gè)靜態(tài)工具類(lèi):Db

@Test
void testDbGet() {
    User user = Db.getById(1L, User.class);
    System.out.println(user);
}
?
@Test
void testDbList() {
    // 利用Db實(shí)現(xiàn)復(fù)雜條件查詢(xún)
    List<User> list = Db.lambdaQuery(User.class)
            .like(User::getUsername, "o")
            .ge(User::getBalance, 1000)
            .list();
}
?
@Test
void testDbUpdate() {
    Db.lambdaUpdate(User.class)
            .set(User::getBalance, 2000)
            .eq(User::getUsername, "Rose");
}

這樣就可以在任意serviceImpl中都可以使用任意的service,而不需要依賴(lài)注入了

4、自定義sql

4.1、自定義xml分頁(yè)sql

UserMapper中定義接口方法

page 分頁(yè)對(duì)象,xml中可以從里面進(jìn)行取值,傳遞參數(shù) Page 即自動(dòng)分頁(yè),必須放在第一位

/**
* 根據(jù)年齡查詢(xún)用戶(hù)列表,分頁(yè)顯示
*/
Page<User> selectPageVo(@Param("page") Page<User> page,@Param("age") Integer age);

UserMapper.xml中編寫(xiě)SQL

<select id="selectPageVo" resultType="User">
    select id,username as name,age,email from t_user where age > #{age}
</select>

測(cè)試方法

  • xml中沒(méi)有分頁(yè)語(yǔ)句,mybatisplus自動(dòng)分頁(yè)
  • 前提必須有分頁(yè)插件,否則沒(méi)有分頁(yè)效果
@Test
public void testSelectPageVo(){ //設(shè)置分頁(yè)參數(shù)
    Page<User> page = new Page<>(1, 5); 
    userMapper.selectPageVo(page, 20);
    //獲取分頁(yè)數(shù)據(jù)
    List<User> list = page.getRecords(); 
    list.forEach(System.out::println); 
    System.out.println("當(dāng)前頁(yè):"+page.getCurrent()); 
    System.out.println("每頁(yè)顯示的條數(shù):"+page.getSize()); 
    System.out.println("總記錄數(shù):"+page.getTotal()); 
    System.out.println("總頁(yè)數(shù):"+page.getPages()); 
    System.out.println("是否有上一頁(yè):"+page.hasPrevious()); 
    System.out.println("是否有下一頁(yè):"+page.hasNext());
}

4.2、@Select注解自定義sql

普通sql

@Select("select * from student where age = #{age} and user_name = #{userName}")
Student getStudent( @Param("age") Integer age, @Param("userName") String userName);

帶Wrapper條件sql

  • @Param("ew"):固定寫(xiě)法,可以參照BaseMapper接口里的方法
  • ${ew.customSqlSegment}:固定寫(xiě)法,在sql后面拼接條件,不需要寫(xiě)where關(guān)鍵字
  • @Param("page") Page<?> page:Wrapper條件和分頁(yè)可以共用,但是分頁(yè)需要寫(xiě)在最前面
// 單表查詢(xún)
@Select("select * from student ${ew.customSqlSegment}")
Student getStudentById( @Param("ew") QueryWrapper<Student> wrapper);
// 多表查詢(xún)
@Select("SELECT u.* FROM student u INNER JOIN address a ON u.id = a.student_id ${ew.customSqlSegment}")
List<Student> queryStudentListByWrapper(@Param("page") Page<Student> page, @Param("ew")QueryWrapper<User> wrapper);

4.3、連表left join和inner join的分頁(yè)查詢(xún)區(qū)別

  • left join查詢(xún)通過(guò)Page<?> page參數(shù)自動(dòng)分頁(yè)時(shí)候,查詢(xún)總條數(shù)COUNT(*)時(shí)候會(huì)將left join去掉,也就是只查主表的數(shù)據(jù)
  • 此時(shí)如果有副表的字段作為查詢(xún)條件會(huì)報(bào)錯(cuò):Unknown column ‘xxx’ in ‘where clause’(主表找不到xxx字段)
// 情況1:如果查詢(xún)條件中有address的字段,比如模糊查詢(xún)地址名稱(chēng)
// 情況2:如果查詢(xún)條件的字段,兩個(gè)表都有,這里會(huì)有問(wèn)題
// 自動(dòng)分頁(yè)的查詢(xún)count(*)時(shí)候,就會(huì)拋出以上異常
@Select("SELECT u.* FROM student u LEFT JOIN address a ON u.id = a.student_id ${ew.customSqlSegment}")
List<Student> queryStudentListByWrapper(@Param("page") Page<Student> page, @Param("ew")QueryWrapper<User> wrapper);

解決方式:嵌套一層select * from (連表復(fù)雜sql)as result ${ew.customSqlSegment}

@Select("SELECT * FROM (SELECT u.* FROM student u LEFT JOIN address a ON u.id = a.student_id) as result ${ew.customSqlSegment}")
List<Student> queryStudentListByWrapper(@Param("page") Page<Student> page, @Param("ew")QueryWrapper<User> wrapper);

inner join查詢(xún)通過(guò)Page<?> page參數(shù)自動(dòng)分頁(yè)時(shí)候,查詢(xún)總條數(shù)COUNT(*)時(shí)候不會(huì)將inner join去掉,所以一般不需要嵌套

4.4、連表查詢(xún)條件Wrapper和響應(yīng)IPage的泛型

  • 查詢(xún)條件Wrapper和響應(yīng)IPage的泛型非表實(shí)體也行,只有符合數(shù)據(jù)庫(kù)字段的駝峰命名即可(需要?jiǎng)?chuàng)建實(shí)體對(duì)象)
  • 如果查詢(xún)條件同時(shí)需要多個(gè)表字段,也可以@Param("ew") Wrapper<?> queryWrapper(不需要?jiǎng)?chuàng)建實(shí)體對(duì)象)

5、IPage的泛型轉(zhuǎn)換(entity轉(zhuǎn)換為vo)

// 分頁(yè)查詢(xún)
Page<UserEntity> userPage = super.lambdaQuery().page(new Page<>(request.getCurrent(), request.getSize()));
// entity轉(zhuǎn)換為vo
IPage<UserVO> infoResPage = userPage.convert(item -> Convert.convert(UserVO.class, item));

6、SimpleQuery工具類(lèi)

Simplequery可以對(duì)selectList查詢(xún)后的結(jié)果用stream流進(jìn)行了一些封裝,使其可以返回一些指定結(jié)果,簡(jiǎn)潔api的調(diào)用

示例

獲取Student對(duì)象集合的名字集合

// 方式一
List<String> nameList = SimpleQuery.list(
        new LambdaQueryWrapper<Student>().like(Student::getUserName, "張"),
        Student::getUserName
);
// 方式二
List<Student> list = studentService.list();
List<String> nameList2 = SimpleQuery.list2List(list, Student::getUserName);

先將Student對(duì)象的名稱(chēng)前后添加**再獲取名字集合

List<String> nameList = SimpleQuery.list(
        new LambdaQueryWrapper<Student>().like(Student::getUserName, "李"),
        Student::getUserName,
        new Consumer<Student>() {
            @Override
            public void accept(Student student) {
                student.setUserName("**"+student.getUserName()+"**");
            }
        }
);

返回key=名字,value=年齡的map

Map<String, Integer> map = SimpleQuery.map(
        new LambdaQueryWrapper<>(), 
        Student::getUserName, 
        Student::getAge
);

group分組,key位名字,value相同名字的Student對(duì)象集合

Map<String, List<Student>> group = SimpleQuery.group(
        new LambdaQueryWrapper<Student>(), 
        Student::getUserName
);

7、ActiveRecord

  • ActiveRecord(活動(dòng)記錄,簡(jiǎn)稱(chēng) AR),是一種領(lǐng)域模型模式,特點(diǎn)是一個(gè)模型類(lèi)對(duì)應(yīng)關(guān)系型數(shù)據(jù)庫(kù)中的一個(gè)表,而模型類(lèi)的一個(gè)實(shí)例對(duì)應(yīng)表中的一行記錄
  • ActiveRecord 一直廣受解釋型動(dòng)態(tài)語(yǔ)言( PHP 、 Ruby 等)的喜愛(ài),通過(guò)圍繞一個(gè)數(shù)據(jù)對(duì)象進(jìn)行CRUD操作
  • 僅僅需要讓實(shí)體類(lèi)繼承Model類(lèi)且實(shí)現(xiàn)主鍵指定方法
@Data
@TableName(value = "student")
public class Student extends Model<Student> {
    /**
     * 主鍵id
     */
    private Long id;
    /**
     * 姓名
     */
    private String userName;
    /**
     * 年齡
     */
    private Integer age;
}
@Test
void activeRecordAddQ{
	Student student = new Student();
	student.setUserName("李四");
	student.setAge(12);
	student.insert();
}

Model抽象類(lèi)方法

注意: 必須存在對(duì)應(yīng)的原始mapper并繼承baseMapper并且可以使用

五、插件

1、Mybatis插件

MybatisPlusInterceptor分頁(yè)插件

@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //注意使用哪種數(shù)據(jù)庫(kù)
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

2、MyBatisX插件

2.1、生成逆向工程

找到我們需要生成的表點(diǎn)擊右鍵

填寫(xiě)完信息以后下一步

繼續(xù)填寫(xiě)信息

結(jié)果展示

2.2、快速生成CRUD

MyBaitsX可以根據(jù)我們?cè)贛apper接口中輸入的方法名【alt+Enter】快速幫我們生成對(duì)應(yīng)的sql語(yǔ)句

到此這篇關(guān)于MyBatis-Plus實(shí)用篇超完整教程的文章就介紹到這了,更多相關(guān)MyBatis-Plus實(shí)用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用JavaBean根據(jù)指定條件設(shè)置屬性值默認(rèn)值方式

    使用JavaBean根據(jù)指定條件設(shè)置屬性值默認(rèn)值方式

    這篇文章主要介紹了使用JavaBean根據(jù)指定條件設(shè)置屬性值默認(rèn)值方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • SSH框架網(wǎng)上商城項(xiàng)目第8戰(zhàn)之查詢(xún)和刪除商品類(lèi)別功能實(shí)現(xiàn)

    SSH框架網(wǎng)上商城項(xiàng)目第8戰(zhàn)之查詢(xún)和刪除商品類(lèi)別功能實(shí)現(xiàn)

    SSH框架網(wǎng)上商城項(xiàng)目第8戰(zhàn)之查詢(xún)和刪除商品類(lèi)別功能實(shí)現(xiàn),為項(xiàng)目增加功能,添加、更新、刪除和查詢(xún)操作,感興趣的小伙伴們可以參考一下
    2016-05-05
  • Java19新特性中結(jié)構(gòu)化并發(fā)的使用

    Java19新特性中結(jié)構(gòu)化并發(fā)的使用

    Java19在并發(fā)編程領(lǐng)域引入了一個(gè)全新的概念:結(jié)構(gòu)化并發(fā),這一特性旨在簡(jiǎn)化并發(fā)任務(wù)的管理,提升多線程程序的可維護(hù)性和安全性,使其生命周期和控制流更加有序和明確,感興趣的可以了解一下
    2024-09-09
  • Java多線程環(huán)境下SimpleDateFormat類(lèi)安全轉(zhuǎn)換

    Java多線程環(huán)境下SimpleDateFormat類(lèi)安全轉(zhuǎn)換

    這篇文章主要介紹了Java多線程環(huán)境下SimpleDateFormat類(lèi)安全轉(zhuǎn)換,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • springboot整合Mybatis、JPA、Redis的示例代碼

    springboot整合Mybatis、JPA、Redis的示例代碼

    這篇文章主要介紹了springboot整合Mybatis、JPA、Redis的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Java ArrayList與Vector和LinkedList的使用及源碼分析

    Java ArrayList與Vector和LinkedList的使用及源碼分析

    ArrayList、Vector、LinkedList類(lèi)均在java.util包中,均為可伸縮數(shù)組,即可以動(dòng)態(tài)改變長(zhǎng)度的數(shù)組。ArrayList 和 Vector都是基于存儲(chǔ)元素的Object[] array來(lái)實(shí)現(xiàn)的,它們會(huì)在內(nèi)存中開(kāi)辟一塊連續(xù)的內(nèi)存來(lái)存儲(chǔ)
    2022-11-11
  • Spring Boot實(shí)戰(zhàn)之?dāng)?shù)據(jù)庫(kù)操作的示例代碼

    Spring Boot實(shí)戰(zhàn)之?dāng)?shù)據(jù)庫(kù)操作的示例代碼

    本篇文章主要介紹了Spring Boot實(shí)戰(zhàn)之?dāng)?shù)據(jù)庫(kù)操作的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-01-01
  • 談?wù)刯ava的concurrent用法

    談?wù)刯ava的concurrent用法

    這篇文章給大家介紹java的concurrent用法,感興趣的朋友一起學(xué)習(xí)吧
    2015-10-10
  • cmd使用javac和java及注意事項(xiàng)

    cmd使用javac和java及注意事項(xiàng)

    這篇文章主要介紹了cmd使用javac和java及注意事項(xiàng),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2021-12-12
  • dubbo如何設(shè)置連接zookeeper權(quán)限

    dubbo如何設(shè)置連接zookeeper權(quán)限

    這篇文章主要介紹了dubbo如何設(shè)置連接zookeeper權(quán)限問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05

最新評(píng)論