中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

免費(fèi)提供網(wǎng)站建設(shè)免費(fèi)二級(jí)域名分發(fā)平臺(tái)

免費(fèi)提供網(wǎng)站建設(shè),免費(fèi)二級(jí)域名分發(fā)平臺(tái),深圳做網(wǎng)站得外包公司,優(yōu)秀高端網(wǎng)站建設(shè)報(bào)價(jià)MyBatis-plus 是一款 Mybatis 增強(qiáng)工具,用于簡(jiǎn)化開發(fā),提高效率。下文使用縮寫 mp來簡(jiǎn)化表示 MyBatis-plus,本文主要介紹 mp 整合 Spring Boot 的使用。 (5條消息) mybatis-plus用法(二)_渣娃工程師的博客-CSDN博客 1…

MyBatis-plus 是一款 Mybatis 增強(qiáng)工具,用于簡(jiǎn)化開發(fā),提高效率。下文使用縮寫 mp來簡(jiǎn)化表示 MyBatis-plus,本文主要介紹 mp 整合?Spring Boot 的使用。

(5條消息) mybatis-plus用法(二)_渣娃工程師的博客-CSDN博客

1.創(chuàng)建一個(gè)Spring Boot項(xiàng)目。

2.導(dǎo)入依賴

<!-- pom.xml -->  <?xml version="1.0" encoding="UTF-8"?>  <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">  <modelVersion>4.0.0</modelVersion>  <parent>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-parent</artifactId>  <version>2.3.4.RELEASE</version>  <relativePath/> <!-- lookup parent from repository -->  </parent>  <groupId>com.example</groupId>  <artifactId>mybatis-plus</artifactId>  <version>0.0.1-SNAPSHOT</version>  <name>mybatis-plus</name>  <properties>  <java.version>1.8</java.version>  </properties>  <dependencies>  <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter</artifactId>  </dependency>  <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-test</artifactId>  <scope>test</scope>  </dependency>  <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-configuration-processor</artifactId>  </dependency>  <dependency>  <groupId>com.baomidou</groupId>  <artifactId>mybatis-plus-boot-starter</artifactId>  <version>3.4.2</version>  </dependency>  <dependency>  <groupId>mysql</groupId>  <artifactId>mysql-connector-java</artifactId>  <scope>runtime</scope>  </dependency>  <dependency>  <groupId>org.projectlombok</groupId>  <artifactId>lombok</artifactId>  </dependency>  </dependencies>  <build>  <plugins>  <plugin>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-maven-plugin</artifactId>  </plugin>  </plugins>  </build>  </project>

?3.配置數(shù)據(jù)庫(kù)

# application.yml  spring:  datasource:  driver-class-name: com.mysql.cj.jdbc.Driver  url: jdbc:mysql://localhost:3306/yogurt?serverTimezone=Asia/Shanghai  username: root  password: root  mybatis-plus:  configuration:  log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #開啟SQL語句打印

4.創(chuàng)建一個(gè)實(shí)體類

package com.example.mp.po;  import lombok.Data;  import java.time.LocalDateTime;  @Data  public class User {  private Long id;  private String name;  private Integer age;  private String email;  private Long managerId;  private LocalDateTime createTime;  }

5.創(chuàng)建一個(gè)mapper接口

package com.example.mp.mappers;  import com.baomidou.mybatisplus.core.mapper.BaseMapper;  import com.example.mp.po.User;  public interface UserMapper extends BaseMapper<User> { }

6.在SpringBoot啟動(dòng)類上配置mapper接口的掃描路徑


package com.example.mp;  import org.mybatis.spring.annotation.MapperScan;  import org.springframework.boot.SpringApplication;  import org.springframework.boot.autoconp.SpringBootApplication;  @SpringBootApplication  @MapperScan("com.example.mp.mappers")  public class MybatisPlusApplication {  public static void main(String[] args) {  SpringApplication.run(MybatisPlusApplication.class, args);  }  }

7.在數(shù)據(jù)庫(kù)中創(chuàng)建表

DROP TABLE IF EXISTS user;  CREATE TABLE user (  id BIGINT(20) PRIMARY KEY NOT NULL COMMENT '主鍵',  name VARCHAR(30) DEFAULT NULL COMMENT '姓名',  age INT(11) DEFAULT NULL COMMENT '年齡',  email VARCHAR(50) DEFAULT NULL COMMENT '郵箱',  manager_id BIGINT(20) DEFAULT NULL COMMENT '直屬上級(jí)id',  create_time DATETIME DEFAULT NULL COMMENT '創(chuàng)建時(shí)間',  CONSTRAINT manager_fk FOREIGN KEY(manager_id) REFERENCES user (id)  ) ENGINE=INNODB CHARSET=UTF8;  INSERT INTO user (id, name, age ,email, manager_id, create_time) VALUES  (1, '大BOSS', 40, 'boss@baomidou.com', NULL, '2021-03-22 09:48:00'),  (2, '李經(jīng)理', 40, 'boss@baomidou.com', 1, '2021-01-22 09:48:00'),  (3, '黃主管', 40, 'boss@baomidou.com', 2, '2021-01-22 09:48:00'),  (4, '吳組長(zhǎng)', 40, 'boss@baomidou.com', 2, '2021-02-22 09:48:00'),  (5, '小菜', 40, 'boss@baomidou.com', 2, '2021-02-22 09:48:00')

8.編寫一個(gè)SpringBoot測(cè)試類

package com.example.mp;  import com.example.mp.mappers.UserMapper;  import com.example.mp.po.User;  import org.junit.Test;  import org.junit.runner.RunWith;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.boot.test.context.SpringBootTest;  import org.springframework.test.context.junit4.SpringRunner;  import java.util.List;  import static org.junit.Assert.*;  @RunWith(SpringRunner.class)  @SpringBootTest  public class SampleTest {  @Autowired  private UserMapper mapper;  @Test  public void testSelect() {  List<User> list = mapper.selectList(null);  assertEquals(5, list.size());  list.forEach(System.out::println);  }  }

準(zhǔn)備工作完成,數(shù)據(jù)庫(kù)情況如下:

項(xiàng)目目錄如下:

?運(yùn)行測(cè)試類

?可以看到,針對(duì)單表的基本CRUD操作,只需要?jiǎng)?chuàng)建好實(shí)體類,并創(chuàng)建一個(gè)繼承自BaseMapper的接口即可,可謂非常簡(jiǎn)潔。并且,我們注意到,User類中的managerIdcreateTime屬性,自動(dòng)和數(shù)據(jù)庫(kù)表中的manager_idcreate_time對(duì)應(yīng)了起來,這是因?yàn)閙p自動(dòng)做了數(shù)據(jù)庫(kù)下劃線命名,到Java類的駝峰命名之間的轉(zhuǎn)化。

注解

mp一共提供了8個(gè)注解,這些注解是用在Java的實(shí)體類上面的。

@TableName

注解在類上,指定類和數(shù)據(jù)庫(kù)表的映射關(guān)系。實(shí)體類的類名(轉(zhuǎn)成小寫后)和數(shù)據(jù)庫(kù)表名相同時(shí),可以不指定該注解。

@TableId

注解在實(shí)體類的某一字段上,表示這個(gè)字段對(duì)應(yīng)數(shù)據(jù)庫(kù)表的主鍵。當(dāng)主鍵名為id時(shí)(表中列名為id,實(shí)體類中字段名為id),無需使用該注解顯式指定主鍵,mp會(huì)自動(dòng)關(guān)聯(lián)。若類的字段名和表的列名不一致,可用value屬性指定表的列名。另,這個(gè)注解有個(gè)重要的屬性type,用于指定主鍵策略。

@TableField

注解在某一字段上,指定Java實(shí)體類的字段和數(shù)據(jù)庫(kù)表的列的映射關(guān)系。這個(gè)注解有如下幾個(gè)應(yīng)用場(chǎng)景。

  • 排除非表字段

    若Java實(shí)體類中某個(gè)字段,不對(duì)應(yīng)表中的任何列,它只是用于保存一些額外的,或組裝后的數(shù)據(jù),則可以設(shè)置exist屬性為false,這樣在對(duì)實(shí)體對(duì)象進(jìn)行插入時(shí),會(huì)忽略這個(gè)字段。排除非表字段也可以通過其他方式完成,如使用statictransient關(guān)鍵字,但個(gè)人覺得不是很合理,不做贅述

  • 字段驗(yàn)證策略

    通過insertStrategyupdateStrategywhereStrategy屬性進(jìn)行配置,可以控制在實(shí)體對(duì)象進(jìn)行插入,更新,或作為WHERE條件時(shí),對(duì)象中的字段要如何組裝到SQL語句中。

  • 字段填充策略

    通過fill屬性指定,字段為空時(shí)會(huì)進(jìn)行自動(dòng)填充

@Version

樂觀鎖注解

@EnumValue

注解在枚舉字段上

@TableLogic

邏輯刪除

KeySequence

序列主鍵策略(oracle

InterceptorIgnore

插件過濾規(guī)則

CRUD接口

mp封裝了一些最基礎(chǔ)的CRUD方法,只需要直接繼承mp提供的接口,無需編寫任何SQL,即可食用。mp提供了兩套接口,分別是Mapper CRUD接口和Service CRUD接口。并且mp還提供了條件構(gòu)造器Wrapper,可以方便地組裝SQL語句中的WHERE條件。

Mapper CRUD接口

只需定義好實(shí)體類,然后創(chuàng)建一個(gè)接口,繼承mp提供的BaseMapper,即可食用。mp會(huì)在mybatis啟動(dòng)時(shí),自動(dòng)解析實(shí)體類和表的映射關(guān)系,并注入帶有通用CRUD方法的mapper。BaseMapper里提供的方法,部分列舉如下:

  • insert(T entity)??插入一條記錄

  • deleteById(Serializable id)??根據(jù)主鍵id刪除一條記錄

  • delete(Wrapper<T> wrapper)?根據(jù)條件構(gòu)造器wrapper進(jìn)行刪除

  • selectById(Serializable id)?根據(jù)主鍵id進(jìn)行查找

  • selectBatchIds(Collection idList)?根據(jù)主鍵id進(jìn)行批量查找

  • selectByMap(Map<String,Object> map)?根據(jù)map中指定的列名和列值進(jìn)行等值匹配查找

  • selectMaps(Wrapper<T> wrapper)??根據(jù) wrapper 條件,查詢記錄,將查詢結(jié)果封裝為一個(gè)Map,Map的key為結(jié)果的列,value為值

  • selectList(Wrapper<T> wrapper)?根據(jù)條件構(gòu)造器wrapper進(jìn)行查詢

  • update(T entity, Wrapper<T> wrapper)?根據(jù)條件構(gòu)造器wrapper進(jìn)行更新

  • updateById(T entity)

  • ...

下面講解幾個(gè)比較特別的方法

selectMaps

BaseMapper接口還提供了一個(gè)selectMaps方法,這個(gè)方法會(huì)將查詢結(jié)果封裝為一個(gè)Map,Map的key為結(jié)果的列,value為值

該方法的使用場(chǎng)景如下:

  • 只查部分列

當(dāng)某個(gè)表的列特別多,而SELECT的時(shí)候只需要選取個(gè)別列,查詢出的結(jié)果也沒必要封裝成Java實(shí)體類對(duì)象時(shí)(只查部分列時(shí),封裝成實(shí)體后,實(shí)體對(duì)象中的很多屬性會(huì)是null),則可以用selectMaps,獲取到指定的列后,再自行進(jìn)行處理即可

比如

@Test  public void test3() {  QueryWrapper<User> wrapper = new QueryWrapper<>();  wrapper.select("id","name","email").likeRight("name","黃");  List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);  maps.forEach(System.out::println);  }

進(jìn)行數(shù)據(jù)統(tǒng)計(jì)

比如

// 按照直屬上級(jí)進(jìn)行分組,查詢每組的平均年齡,最大年齡,最小年齡  /**  select avg(age) avg_age ,min(age) min_age, max(age) max_age from user group by manager_id having sum(age) < 500;  **/  @Test  public void test3() {  QueryWrapper<User> wrapper = new QueryWrapper<>();  wrapper.select("manager_id", "avg(age) avg_age", "min(age) min_age", "max(age) max_age")  .groupBy("manager_id").having("sum(age) < {0}", 500);  List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);  maps.forEach(System.out::println);  }

selectObjs

只會(huì)返回第一個(gè)字段(第一列)的值,其他字段會(huì)被舍棄

比如

@Test  public void test3() {  QueryWrapper<User> wrapper = new QueryWrapper<>();  wrapper.select("id", "name").like("name", "黃");  List<Object> objects = userMapper.selectObjs(wrapper);  objects.forEach(System.out::println);  }

得到的結(jié)果,只封裝了第一列的id

selectCount

查詢滿足條件的總數(shù),注意,使用這個(gè)方法,不能調(diào)用QueryWrapperselect方法設(shè)置要查詢的列了。這個(gè)方法會(huì)自動(dòng)添加select count(1)

比如

@Test  public void test3() {  QueryWrapper<User> wrapper = new QueryWrapper<>();  wrapper.like("name", "黃");  Integer count = userMapper.selectCount(wrapper);  System.out.println(count);  }

Service CRUD 接口

另外一套CRUD是Service層的,只需要編寫一個(gè)接口,繼承IService,并創(chuàng)建一個(gè)接口實(shí)現(xiàn)類,即可食用。(這個(gè)接口提供的CRUD方法,和Mapper接口提供的功能大同小異,比較明顯的區(qū)別在于IService支持了更多的批量化操作,如saveBatchsaveOrUpdateBatch等方法。

食用示例如下

1.首先,新建一個(gè)接口,繼承IService

package com.example.mp.service;  import com.baomidou.mybatisplus.extension.service.IService;  import com.example.mp.po.User;  public interface UserService extends IService<User> {  }

?2.創(chuàng)建這個(gè)接口的實(shí)現(xiàn)類,并繼承ServiceImpl,最后打上@Service注解,注冊(cè)到Spring容器中,即可食用

package com.example.mp.service.impl;  import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;  import com.example.mp.mappers.UserMapper;  import com.example.mp.po.User;  import com.example.mp.service.UserService;  import org.springframework.stereotype.Service;  @Service  public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { }

?3.測(cè)試代碼

package com.example.mp;  import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;  import com.baomidou.mybatisplus.core.toolkit.Wrappers;  import com.example.mp.po.User;  import com.example.mp.service.UserService;  import org.junit.Test;  import org.junit.runner.RunWith;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.boot.test.context.SpringBootTest;  import org.springframework.test.context.junit4.SpringRunner;  @RunWith(SpringRunner.class)  @SpringBootTest  public class ServiceTest {  @Autowired  private UserService userService;  @Test  public void testGetOne() {  LambdaQueryWrapper<User> wrapper = Wrappers.<User>lambdaQuery();  wrapper.gt(User::getAge, 28);  User one = userService.getOne(wrapper, false); // 第二參數(shù)指定為false,使得在查到了多行記錄時(shí),不拋出異常,而返回第一條記錄  System.out.println(one);  }  }

?4.結(jié)果

?另,IService也支持鏈?zhǔn)秸{(diào)用,代碼寫起來非常簡(jiǎn)潔,查詢示例如下

@Test  public void testChain() {  List<User> list = userService.lambdaQuery()  .gt(User::getAge, 39)  .likeRight(User::getName, "王")  .list();  list.forEach(System.out::println);  }

?更新示例如下

@Test  public void testChain() {  userService.lambdaUpdate()  .gt(User::getAge, 39)  .likeRight(User::getName, "王")  .set(User::getEmail, "w39@baomidou.com")  .update();  }

?刪除示例如下

@Test  public void testChain() {  userService.lambdaUpdate()  .like(User::getName, "青蛙")  .remove();  }

條件構(gòu)造器

mp讓我覺得極其方便的一點(diǎn)在于其提供了強(qiáng)大的條件構(gòu)造器Wrapper,可以非常方便的構(gòu)造WHERE條件。條件構(gòu)造器主要涉及到3個(gè)類,AbstractWrapperQueryWrapperUpdateWrapper,它們的類關(guān)系如下

AbstractWrapper中提供了非常多的方法用于構(gòu)建WHERE條件,而QueryWrapper針對(duì)SELECT語句,提供了select()方法,可自定義需要查詢的列,而UpdateWrapper針對(duì)UPDATE語句,提供了set()方法,用于構(gòu)造set語句。條件構(gòu)造器也支持lambda表達(dá)式,寫起來非常舒爽。

下面對(duì)AbstractWrapper中用于構(gòu)建SQL語句中的WHERE條件的方法進(jìn)行部分列舉

  • eq:equals,等于

  • allEq:all equals,全等于

  • ne:not equals,不等于

  • gt:greater than ,大于?>

  • ge:greater than or equals,大于等于

  • lt:less than,小于<

  • le:less than or equals,小于等于

  • between:相當(dāng)于SQL中的BETWEEN

  • notBetween

  • like:模糊匹配。like("name","黃"),相當(dāng)于SQL的name like '%黃%'

  • likeRight:模糊匹配右半邊。likeRight("name","黃"),相當(dāng)于SQL的name like '黃%'

  • likeLeft:模糊匹配左半邊。likeLeft("name","黃"),相當(dāng)于SQL的name like '%黃'

  • notLikenotLike("name","黃"),相當(dāng)于SQL的name not like '%黃%'

  • isNull

  • isNotNull

  • in

  • and:SQL連接符AND

  • or:SQL連接符OR

  • apply:用于拼接SQL,該方法可用于數(shù)據(jù)庫(kù)函數(shù),并可以動(dòng)態(tài)傳參

  • .......

使用示例

下面通過一些具體的案例來練習(xí)條件構(gòu)造器的使用。(使用前文創(chuàng)建的user表)

// 案例先展示需要完成的SQL語句,后展示W(wǎng)rapper的寫法  // 1. 名字中包含佳,且年齡小于25  
// SELECT * FROM user WHERE name like '%佳%' AND age < 25  
QueryWrapper<User> wrapper = new QueryWrapper<>();  
wrapper.like("name", "佳").lt("age", 25);  
List<User> users = userMapper.selectList(wrapper);  
// 下面展示SQL時(shí),僅展示W(wǎng)HERE條件;展示代碼時(shí), 僅展示W(wǎng)rapper構(gòu)建部分  // 2. 姓名為黃姓,且年齡大于等于20,小于等于40,且email字段不為空  
// name like '黃%' AND age BETWEEN 20 AND 40 AND email is not null  
wrapper.likeRight("name","黃").between("age", 20, 40).isNotNull("email");  // 3. 姓名為黃姓,或者年齡大于等于40,按照年齡降序排列,年齡相同則按照id升序排列  
// name like '黃%' OR age >= 40 order by age desc, id asc  
wrapper.likeRight("name","黃").or().ge("age",40).orderByDesc("age").orderByAsc("id");  // 4.創(chuàng)建日期為2021年3月22日,并且直屬上級(jí)的名字為李姓  
// date_format(create_time,'%Y-%m-%d') = '2021-03-22' AND manager_id IN (SELECT id FROM user WHERE name like '李%')  
wrapper.apply("date_format(create_time, '%Y-%m-%d') = {0}", "2021-03-22") // 建議采用{index}這種方式動(dòng)態(tài)傳參, 可防止SQL注入  .inSql("manager_id", "SELECT id FROM user WHERE name like '李%'");  
// 上面的apply, 也可以直接使用下面這種方式做字符串拼接,但當(dāng)這個(gè)日期是一個(gè)外部參數(shù)時(shí),這種方式有SQL注入的風(fēng)險(xiǎn)  
wrapper.apply("date_format(create_time, '%Y-%m-%d') = '2021-03-22'");  // 5. 名字為王姓,并且(年齡小于40,或者郵箱不為空)  
// name like '王%' AND (age < 40 OR email is not null)  
wrapper.likeRight("name", "王").and(q -> q.lt("age", 40).or().isNotNull("email"));  // 6. 名字為王姓,或者(年齡小于40并且年齡大于20并且郵箱不為空)  
// name like '王%' OR (age < 40 AND age > 20 AND email is not null)  
wrapper.likeRight("name", "王").or(  q -> q.lt("age",40)  .gt("age",20)  .isNotNull("email")  );  // 7. (年齡小于40或者郵箱不為空) 并且名字為王姓  
// (age < 40 OR email is not null) AND name like '王%'  
wrapper.nested(q -> q.lt("age", 40).or().isNotNull("email"))  .likeRight("name", "王");  // 8. 年齡為30,31,34,35  
// age IN (30,31,34,35)  
wrapper.in("age", Arrays.asList(30,31,34,35));  
// 或  
wrapper.inSql("age","30,31,34,35");  // 9. 年齡為30,31,34,35, 返回滿足條件的第一條記錄  
// age IN (30,31,34,35) LIMIT 1  
wrapper.in("age", Arrays.asList(30,31,34,35)).last("LIMIT 1");  // 10. 只選出id, name 列 (QueryWrapper 特有)  
// SELECT id, name FROM user;  
wrapper.select("id", "name");  // 11. 選出id, name, age, email, 等同于排除 manager_id 和 create_time  
// 當(dāng)列特別多, 而只需要排除個(gè)別列時(shí), 采用上面的方式可能需要寫很多個(gè)列, 可以采用重載的select方法,指定需要排除的列  
wrapper.select(User.class, info -> {  String columnName = info.getColumn();  return !"create_time".equals(columnName) && !"manager_id".equals(columnName);  });

Condition

條件構(gòu)造器的諸多方法中,均可以指定一個(gè)boolean類型的參數(shù)condition,用來決定該條件是否加入最后生成的WHERE語句中,比如

String name = "黃"; // 假設(shè)name變量是一個(gè)外部傳入的參數(shù)  
QueryWrapper<User> wrapper = new QueryWrapper<>();  
wrapper.like(StringUtils.hasText(name), "name", name);  
// 僅當(dāng) StringUtils.hasText(name) 為 true 時(shí), 會(huì)拼接這個(gè)like語句到WHERE中  
// 其實(shí)就是對(duì)下面代碼的簡(jiǎn)化  
if (StringUtils.hasText(name)) {  wrapper.like("name", name);  
}

實(shí)體對(duì)象作為條件

調(diào)用構(gòu)造函數(shù)創(chuàng)建一個(gè)Wrapper對(duì)象時(shí),可以傳入一個(gè)實(shí)體對(duì)象。后續(xù)使用這個(gè)Wrapper時(shí),會(huì)以實(shí)體對(duì)象中的非空屬性,構(gòu)建WHERE條件(默認(rèn)構(gòu)建等值匹配的WHERE條件,這個(gè)行為可以通過實(shí)體類里各個(gè)字段上的@TableField注解中的condition屬性進(jìn)行改變)

示例如下

@Test  public void test3() {  User user = new User();  user.setName("黃主管");  user.setAge(28);  QueryWrapper<User> wrapper = new QueryWrapper<>(user);  List<User> users = userMapper.selectList(wrapper);  users.forEach(System.out::println);  }

執(zhí)行結(jié)果如下??梢钥吹?#xff0c;是根據(jù)實(shí)體對(duì)象中的非空屬性,進(jìn)行了等值匹配查詢

若希望針對(duì)某些屬性,改變等值匹配的行為,則可以在實(shí)體類中用@TableField注解進(jìn)行配置,示例如下

package com.example.mp.po;  
import com.baomidou.mybatisplus.annotation.SqlCondition;  
import com.baomidou.mybatisplus.annotation.TableField;  
import lombok.Data;  
import java.time.LocalDateTime;  
@Data  
public class User {  private Long id;  @TableField(condition = SqlCondition.LIKE) // 配置該字段使用like進(jìn)行拼接  private String name;  private Integer age;  private String email;  private Long managerId;  private LocalDateTime createTime;  
}

運(yùn)行下面的測(cè)試代碼

@Test  public void test3() {  User user = new User();  user.setName("黃");  QueryWrapper<User> wrapper = new QueryWrapper<>(user);  List<User> users = userMapper.selectList(wrapper);  users.forEach(System.out::println);  }

?從下圖得到的結(jié)果來看,對(duì)于實(shí)體對(duì)象中的name字段,采用了like進(jìn)行拼接

?@TableField中配置的condition屬性實(shí)則是一個(gè)字符串,SqlCondition類中預(yù)定義了一些字符串以供選擇

package com.baomidou.mybatisplus.annotation;  public class SqlCondition {  //下面的字符串中, %s 是占位符, 第一個(gè) %s 是列名, 第二個(gè) %s 是列的值  public static final String EQUAL = "%s=#{%s}";  public static final String NOT_EQUAL = "%s&lt;&gt;#{%s}";  public static final String LIKE = "%s LIKE CONCAT('%%',#{%s},'%%')";  public static final String LIKE_LEFT = "%s LIKE CONCAT('%%',#{%s})";  public static final String LIKE_RIGHT = "%s LIKE CONCAT(#{%s},'%%')";  
}

?SqlCondition中提供的配置比較有限,當(dāng)我們需要<>等拼接方式,則需要自己定義。比如

package com.example.mp.po;  
import com.baomidou.mybatisplus.annotation.SqlCondition;  
import com.baomidou.mybatisplus.annotation.TableField;  
import lombok.Data;  
import java.time.LocalDateTime;  
@Data  
public class User {  private Long id;  @TableField(condition = SqlCondition.LIKE)  private String name;  @TableField(condition = "%s &gt; #{%s}") // 這里相當(dāng)于大于, 其中 &gt; 是字符實(shí)體  private Integer age;  private String email;  private Long managerId;  private LocalDateTime createTime;  
}

?測(cè)試如下

@Test  public void test3() {  User user = new User();  user.setName("黃");  user.setAge(30);  QueryWrapper<User> wrapper = new QueryWrapper<>(user);  List<User> users = userMapper.selectList(wrapper);  users.forEach(System.out::println);  }

從下圖得到的結(jié)果,可以看出,name屬性是用like拼接的,而age屬性是用>拼接的

allEq方法

allEq方法傳入一個(gè)map,用來做等值匹配

@Test  public void test3() {  QueryWrapper<User> wrapper = new QueryWrapper<>();  Map<String, Object> param = new HashMap<>();  param.put("age", 40);  param.put("name", "黃飛飛");  wrapper.allEq(param);  List<User> users = userMapper.selectList(wrapper);  users.forEach(System.out::println);  }

當(dāng)allEq方法傳入的Map中有value為null的元素時(shí),默認(rèn)會(huì)設(shè)置為is null

@Test  public void test3() {  QueryWrapper<User> wrapper = new QueryWrapper<>();  Map<String, Object> param = new HashMap<>();  param.put("age", 40);  param.put("name", null);  wrapper.allEq(param);  List<User> users = userMapper.selectList(wrapper);  users.forEach(System.out::println);  }

?若想忽略map中value為null的元素,可以在調(diào)用allEq時(shí),設(shè)置參數(shù)boolean null2IsNullfalse

@Test  public void test3() {  QueryWrapper<User> wrapper = new QueryWrapper<>();  Map<String, Object> param = new HashMap<>();  param.put("age", 40);  param.put("name", null);  wrapper.allEq(param, false);  List<User> users = userMapper.selectList(wrapper);  users.forEach(System.out::println);  }

若想要在執(zhí)行allEq時(shí),過濾掉Map中的某些元素,可以調(diào)用allEq的重載方法allEq(BiPredicate<R, V> filter, Map<R, V> params)

@Test  public void test3() {  QueryWrapper<User> wrapper = new QueryWrapper<>();  Map<String, Object> param = new HashMap<>();  param.put("age", 40);  param.put("name", "黃飛飛");  wrapper.allEq((k,v) -> !"name".equals(k), param); // 過濾掉map中key為name的元素  List<User> users = userMapper.selectList(wrapper);  users.forEach(System.out::println);  }

lambda條件構(gòu)造器

lambda條件構(gòu)造器,支持lambda表達(dá)式,可以不必像普通條件構(gòu)造器一樣,以字符串形式指定列名,它可以直接以實(shí)體類的方法引用來指定列。示例如下

@Test  public void testLambda() {  LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();  wrapper.like(User::getName, "黃").lt(User::getAge, 30);  List<User> users = userMapper.selectList(wrapper);  users.forEach(System.out::println);  }

像普通的條件構(gòu)造器,列名是用字符串的形式指定,無法在編譯期進(jìn)行列名合法性的檢查,這就不如lambda條件構(gòu)造器來的優(yōu)雅。

另外,還有個(gè)鏈?zhǔn)絣ambda條件構(gòu)造器,使用示例如下

@Test  public void testLambda() {  LambdaQueryChainWrapper<User> chainWrapper = new LambdaQueryChainWrapper<>(userMapper);  List<User> users = chainWrapper.like(User::getName, "黃").gt(User::getAge, 30).list();  users.forEach(System.out::println);  }

更新操作

上面介紹的都是查詢操作,現(xiàn)在來講更新和刪除操作。

BaseMapper中提供了2個(gè)更新方法

  • updateById(T entity)

根據(jù)入?yún)?code>entity的id(主鍵)進(jìn)行更新,對(duì)于entity中非空的屬性,會(huì)出現(xiàn)在UPDATE語句的SET后面,即entity中非空的屬性,會(huì)被更新到數(shù)據(jù)庫(kù),示例如下

@RunWith(SpringRunner.class)  @SpringBootTest  public class UpdateTest {  @Autowired  private UserMapper userMapper;  @Test  public void testUpdate() {  User user = new User();  user.setId(2L);  user.setAge(18);  userMapper.updateById(user);  }  }

  • update(T entity, Wrapper<T> wrapper)

根據(jù)實(shí)體entity和條件構(gòu)造器wrapper進(jìn)行更新,示例如下

@Test  public void testUpdate2() {  User user = new User();  user.setName("王三蛋");  LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();  wrapper.between(User::getAge, 26,31).likeRight(User::getName,"吳");  userMapper.update(user, wrapper);  }

?額外演示一下,把實(shí)體對(duì)象傳入Wrapper,即用實(shí)體對(duì)象構(gòu)造WHERE條件的案例

@Test  public void testUpdate3() {  User whereUser = new User();  whereUser.setAge(40);  whereUser.setName("王");  LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>(whereUser);  User user = new User();  user.setEmail("share@baomidou.com");  user.setManagerId(10L);  userMapper.update(user, wrapper);  }

注意到我們的User類中,對(duì)name屬性和age屬性進(jìn)行了如下的設(shè)置

@Data  
public class User {  private Long id;  @TableField(condition = SqlCondition.LIKE)  private String name;  @TableField(condition = "%s &gt; #{%s}")  private Integer age;  private String email;  private Long managerId;  private LocalDateTime createTime;  
}

?執(zhí)行結(jié)果

?再額外演示一下,鏈?zhǔn)絣ambda條件構(gòu)造器的使用


@Test  public void testUpdate5() {  LambdaUpdateChainWrapper<User> wrapper = new LambdaUpdateChainWrapper<>(userMapper);  wrapper.likeRight(User::getEmail, "share")  .like(User::getName, "飛飛")  .set(User::getEmail, "ff@baomidou.com")  .update();  }

反思

由于BaseMapper提供的2個(gè)更新方法都是傳入一個(gè)實(shí)體對(duì)象去執(zhí)行更新,這在需要更新的列比較多時(shí)還好,若想要更新的只有那么一列,或者兩列,則創(chuàng)建一個(gè)實(shí)體對(duì)象就顯得有點(diǎn)麻煩。針對(duì)這種情況,UpdateWrapper提供有set方法,可以手動(dòng)拼接SQL中的SET語句,此時(shí)可以不必傳入實(shí)體對(duì)象,示例如下

@Test  public void testUpdate4() {  LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();  wrapper.likeRight(User::getEmail, "share").set(User::getManagerId, 9L);  userMapper.update(null, wrapper);  }

刪除操作

BaseMapper一共提供了如下幾個(gè)用于刪除的方法

  • deleteById??根據(jù)主鍵id進(jìn)行刪除

  • deleteBatchIds??根據(jù)主鍵id進(jìn)行批量刪除

  • deleteByMap??根據(jù)Map進(jìn)行刪除(Map中的key為列名,value為值,根據(jù)列和值進(jìn)行等值匹配)

  • delete(Wrapper<T> wrapper)??根據(jù)條件構(gòu)造器Wrapper進(jìn)行刪除

與前面查詢和更新的操作大同小異,不做贅述

自定義SQL

當(dāng)mp提供的方法還不能滿足需求時(shí),則可以自定義SQL。

原生mybatis

示例如下

  • 注解方式

    package com.example.mp.mappers;  import com.baomidou.mybatisplus.core.mapper.BaseMapper;  
    import com.example.mp.po.User;  
    import org.apache.ibatis.annotations.Select;  import java.util.List;  /**  * @Author yogurtzzz  * @Date 2021/3/18 11:21  **/  
    public interface UserMapper extends BaseMapper<User> {  @Select("select * from user")  List<User> selectRaw();  
    }

  • xml方式

    <?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.example.mp.mappers.UserMapper">  <select id="selectRaw" resultType="com.example.mp.po.User">  SELECT * FROM user  </select>  
    </mapper>  
    package com.example.mp.mappers;  import com.baomidou.mybatisplus.core.mapper.BaseMapper;  
    import com.example.mp.po.User;  
    import org.apache.ibatis.annotations.Select;  
    import java.util.List;  public interface UserMapper extends BaseMapper<User> {  List<User> selectRaw();  
    }

    使用xml時(shí),若xml文件與mapper接口文件不在同一目錄下,則需要在application.yml中配置mapper.xml的存放路徑

    mybatis-plus:  mapper-locations: /mappers/*

    若有多個(gè)地方存放mapper,則用數(shù)組形式進(jìn)行配置

    
    mybatis-plus:  mapper-locations:   - /mappers/*  - /com/example/mp/*

    測(cè)試代碼如下

    
    @Test  public void testCustomRawSql() {  List<User> users = userMapper.selectRaw();  users.forEach(System.out::println);  }

    結(jié)果

mybatis-plus

也可以使用mp提供的Wrapper條件構(gòu)造器,來自定義SQL

示例如下

  • 注解方式

    package com.example.mp.mappers;  
    import com.baomidou.mybatisplus.core.conditions.Wrapper;  
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;  
    import com.baomidou.mybatisplus.core.toolkit.Constants;  
    import com.example.mp.po.User;  
    import org.apache.ibatis.annotations.Param;  
    import org.apache.ibatis.annotations.Select;  
    import java.util.List;  public interface UserMapper extends BaseMapper<User> {  // SQL中不寫WHERE關(guān)鍵字,且固定使用${ew.customSqlSegment}  @Select("select * from user ${ew.customSqlSegment}")  List<User> findAll(@Param(Constants.WRAPPER)Wrapper<User> wrapper);  
    }

  • xml方式

    package com.example.mp.mappers;  
    import com.baomidou.mybatisplus.core.conditions.Wrapper;  
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;  
    import com.example.mp.po.User;  
    import java.util.List;  public interface UserMapper extends BaseMapper<User> {  List<User> findAll(Wrapper<User> wrapper);  
    }  
    <!-- UserMapper.xml -->  
    <?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.example.mp.mappers.UserMapper">  <select id="findAll" resultType="com.example.mp.po.User">  SELECT * FROM user ${ew.customSqlSegment}  </select>  
    </mapper>

    分頁(yè)查詢

    BaseMapper中提供了2個(gè)方法進(jìn)行分頁(yè)查詢,分別是selectPageselectMapsPage,前者會(huì)將查詢的結(jié)果封裝成Java實(shí)體對(duì)象,后者會(huì)封裝成Map<String,Object>。分頁(yè)查詢的食用示例如下

    1. 創(chuàng)建mp的分頁(yè)攔截器,注冊(cè)到Spring容器中

    package com.example.mp.config;  import com.baomidou.mybatisplus.annotation.DbType;  import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;  import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;  import org.springframework.context.annotation.Bean;  import org.springframework.context.annotation.Configuration;  @Configuration  public class MybatisPlusConfig {  /** 新版mp **/  @Bean  public MybatisPlusInterceptor mybatisPlusInterceptor() {  MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();  interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));  return interceptor;  }  /** 舊版mp 用 PaginationInterceptor **/  }

    2. 執(zhí)行分頁(yè)查詢

    @Test  public void testPage() {  LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();  wrapper.ge(User::getAge, 28);  // 設(shè)置分頁(yè)信息, 查第3頁(yè), 每頁(yè)2條數(shù)據(jù)  Page<User> page = new Page<>(3, 2);  // 執(zhí)行分頁(yè)查詢  Page<User> userPage = userMapper.selectPage(page, wrapper);  System.out.println("總記錄數(shù) = " + userPage.getTotal());  System.out.println("總頁(yè)數(shù) = " + userPage.getPages());  System.out.println("當(dāng)前頁(yè)碼 = " + userPage.getCurrent());  // 獲取分頁(yè)查詢結(jié)果  List<User> records = userPage.getRecords();  records.forEach(System.out::println);  }

    3. 結(jié)果

  • 4. 其他

    注意到,分頁(yè)查詢總共發(fā)出了2次SQL,一次查總記錄數(shù),一次查具體數(shù)據(jù)。若希望不查總記錄數(shù),僅查分頁(yè)結(jié)果??梢酝ㄟ^Page的重載構(gòu)造函數(shù),指定isSearchCountfalse即可

    public?Page(long?current,?long?size,?boolean?isSearchCount)
    

    在實(shí)際開發(fā)中,可能遇到多表聯(lián)查的場(chǎng)景,此時(shí)BaseMapper中提供的單表分頁(yè)查詢的方法無法滿足需求,需要自定義SQL,示例如下(使用單表查詢的SQL進(jìn)行演示,實(shí)際進(jìn)行多表聯(lián)查時(shí),修改SQL語句即可)

    1. 在mapper接口中定義一個(gè)函數(shù),接收一個(gè)Page對(duì)象為參數(shù),并編寫自定義SQL

    //?這里采用純注解方式。當(dāng)然,若SQL比較復(fù)雜,建議還是采用XML的方式??
    @Select("SELECT?*?FROM?user?${ew.customSqlSegment}")??
    Page<User>?selectUserPage(Page<User>?page,?@Param(Constants.WRAPPER)?Wrapper<User>?wrapper);
    

    2. 執(zhí)行查詢

    @Test??
    public?void?testPage2()?{??LambdaQueryWrapper<User>?wrapper?=?new?LambdaQueryWrapper<>();??wrapper.ge(User::getAge,?28).likeRight(User::getName,?"王");??Page<User>?page?=?new?Page<>(3,2);??Page<User>?userPage?=?userMapper.selectUserPage(page,?wrapper);??System.out.println("總記錄數(shù)?=?"?+?userPage.getTotal());??System.out.println("總頁(yè)數(shù)?=?"?+?userPage.getPages());??userPage.getRecords().forEach(System.out::println);??
    }
    

    3. 結(jié)果

http://www.risenshineclean.com/news/2485.html

相關(guān)文章:

  • 云南做網(wǎng)站多少錢軟文營(yíng)銷文案
  • 用帝國(guó)cms系統(tǒng)怎么做網(wǎng)站b2b是什么意思
  • 有沒有專門做化妝品小樣的網(wǎng)站百度新聞網(wǎng)頁(yè)
  • 中國(guó)新聞社級(jí)別桌子seo關(guān)鍵詞
  • 鄭州購(gòu)物網(wǎng)站建設(shè)寫軟文怎么接單子
  • 網(wǎng)站沒有備案會(huì)怎么樣百度最新財(cái)報(bào)
  • 網(wǎng)站建設(shè)800元全包seo優(yōu)化排名工具
  • 網(wǎng)站建設(shè)與品牌策劃方案報(bào)價(jià)國(guó)際形勢(shì)最新消息
  • 深圳專業(yè)o2o網(wǎng)站設(shè)計(jì)公司長(zhǎng)春seo整站優(yōu)化
  • 福建城鄉(xiāng)建設(shè)部網(wǎng)站首頁(yè)競(jìng)價(jià)培訓(xùn)班
  • 紹興公司企業(yè)名單武漢seo優(yōu)化代理
  • 做汽車行業(yè)必須注冊(cè)際零件網(wǎng)站必應(yīng)搜索國(guó)際版
  • 邢臺(tái)商城類網(wǎng)站建設(shè)企業(yè)qq郵箱
  • 百度指數(shù)的網(wǎng)站谷歌搜索入口365
  • 網(wǎng)站制作的公司哪個(gè)好南寧seo營(yíng)銷推廣
  • 長(zhǎng)沙哪個(gè)網(wǎng)站建設(shè)最好重慶可靠的關(guān)鍵詞優(yōu)化研發(fā)
  • 網(wǎng)站開發(fā)常用的谷歌插件女教師遭網(wǎng)課入侵視頻大全播放
  • 高密市政府建設(shè)局網(wǎng)站臺(tái)州網(wǎng)站制作維護(hù)
  • 汕頭市門戶網(wǎng)站建設(shè)屬性詞 關(guān)鍵詞 核心詞
  • 深圳軟件有限公司企業(yè)網(wǎng)站優(yōu)化關(guān)鍵詞
  • 電商設(shè)計(jì)網(wǎng)站模板搜索引擎優(yōu)化seo公司
  • 做很多網(wǎng)站省委副書記
  • 頂呱呱網(wǎng)站做的怎么樣?xùn)|莞網(wǎng)站推廣大全
  • 深圳專業(yè)手機(jī)網(wǎng)站建設(shè)重慶seo按天收費(fèi)
  • 河北涿州網(wǎng)站建設(shè)黑科技推廣軟件
  • 前端做網(wǎng)站一般用什么框架中國(guó)十大搜索引擎網(wǎng)站
  • ps做旅游網(wǎng)站整合營(yíng)銷方案
  • 公司網(wǎng)站怎么做能被別人搜索到個(gè)人網(wǎng)頁(yè)
  • 做微網(wǎng)站的第三方登錄界面百度推廣費(fèi)用可以退嗎
  • 網(wǎng)站ui 特點(diǎn)建立免費(fèi)網(wǎng)站