MyBatisPlus講解

轉(zhuǎn)載于:https://mp.weixin.qq.com/s/wyymQUcK1QeCRfoxhd_d7w

1 簡介

MyBatis-plus 是一款 Mybatis 增強(qiáng)工具,用于簡化開發(fā)陌粹,提高效率料皇。下文使用縮寫 mp來簡化表示MyBatis-plus箱歧,本文主要介紹 mp 搭配 Spring Boot 的使用

官方網(wǎng)站:https://mp.baomidou.com/

1.1 核心注解

MyBatis-plus 一共提供了8個(gè)注解鬓梅,這些注解是用在Java的實(shí)體類上面的:

  • @TableName
    注解在類上,指定類和數(shù)據(jù)庫表的映射關(guān)系藤巢。實(shí)體類的類名(轉(zhuǎn)成小寫后)和數(shù)據(jù)庫表名相同時(shí)鼠次,可以不指定該注解
  • @TableId
    注解在實(shí)體類的某一字段上,表示這個(gè)字段對應(yīng)數(shù)據(jù)庫表的主鍵邢笙。當(dāng)主鍵名為id時(shí)(表中列名為id啸如,實(shí)體類中字段名為id),無需使用該注解顯式指定主鍵氮惯,mp會自動關(guān)聯(lián)叮雳。若類的字段名和表的列名不一致,可用value屬性指定表的列名妇汗。另帘不,這個(gè)注解有個(gè)重要的屬性type,用于指定主鍵策略杨箭。
  • @TableField
    注解在某一字段上寞焙,指定Java實(shí)體類的字段和數(shù)據(jù)庫表的列的映射關(guān)系。這個(gè)注解有如下幾個(gè)應(yīng)用場景互婿。
  1. 排除非表字段
    Java實(shí)體類中某個(gè)字段捣郊,不對應(yīng)表中的任何列,它只是用于保存一些額外的擒悬,或組裝后的數(shù)據(jù)模她,則可以設(shè)置exist屬性為false,這樣在對實(shí)體對象進(jìn)行插入時(shí)懂牧,會忽略這個(gè)字段侈净。排除非表字段也可以通過其他方式完成尊勿,如使用static或transient關(guān)鍵字,不做贅述
  2. 字段驗(yàn)證策略
    通過insertStrategy畜侦,updateStrategy元扔,whereStrategy屬性進(jìn)行配置,可以控制在實(shí)體對象進(jìn)行插入旋膳,更新澎语,或作為WHERE條件時(shí),對象中的字段要如何組裝到SQL語句中验懊。
  3. 字段填充策略
    通過fill屬性指定擅羞,字段為空時(shí)會進(jìn)行自動填充
  • @Version
    樂觀鎖注解
  • @EnumValue
    注解在枚舉字段上
  • @TableLogic
    邏輯刪除
  • KeySequence
    序列主鍵策略(oracle)
  • InterceptorIgnore
    插件過濾規(guī)則

1.2 CRUD接口

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

1.2.1 mapper接口

只需定義好實(shí)體類怕篷,然后創(chuàng)建一個(gè)接口历筝,繼承mp提供的BaseMapper,即可食用廊谓。mp會在mybatis啟動時(shí)梳猪,自動解析實(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电抚,Mapkey為結(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)

主要方法介紹,如下:

1.2.1.2 selectMaps

BaseMapper接口還提供了一個(gè)selectMaps方法蝙叛,這個(gè)方法會將查詢結(jié)果封裝為一個(gè)Map俺祠,Mapkey為結(jié)果的列,value為值
該方法的使用場景如下:

  1. 只查部分列
    當(dāng)某個(gè)表的列特別多借帘,而SELECT的時(shí)候只需要選取個(gè)別列蜘渣,查詢出的結(jié)果也沒必要封裝成Java實(shí)體類對象時(shí)(只查部分列時(shí),封裝成實(shí)體后肺然,實(shí)體對象中的很多屬性會是null)蔫缸,則可以用selectMaps,獲取到指定的列后际起,再自行進(jìn)行處理即可
    比如
@Test
   public void test3() {
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.select("user_id","user_name","user_address").likeRight("user_name","黃");
    List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
    maps.forEach(System.out::println);
   }
在這里插入圖片描述
  1. 數(shù)據(jù)統(tǒng)計(jì)
    按照直屬上級進(jìn)行分組拾碌,查詢每組的平均年齡吐葱,最大年齡,最小年齡
@Test
    public void test4() {
     QueryWrapper<UserInfoEntity> wrapper = new QueryWrapper<>();
     wrapper.select("user_id", "avg(user_age) avg_age", "min(user_age) min_age", "max(user_age) max_age")
       .groupBy("user_id").having("sum(user_age) < {0}", 25);
       //或者這樣 having("sum(user_age) <  10")--->having sum(age) > 10
     List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
     System.out.println("==============");
     maps.forEach(System.out::println);
    }
在這里插入圖片描述

1.2.1.3 selectObjs

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

@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);
 }
在這里插入圖片描述

1.2.1.4 selectCount

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

@Test
 public void test3() {
  QueryWrapper<User> wrapper = new QueryWrapper<>();
  wrapper.like("name", "黃");

  Integer count = userMapper.selectCount(wrapper);
  System.out.println(count);
 }
在這里插入圖片描述

1.2.2 service接口

另外一套CRUDService層的,只需要編寫一個(gè)接口蔫敲,繼承IService饲嗽,并創(chuàng)建一個(gè)接口實(shí)現(xiàn)類,即可食用奈嘿。(這個(gè)接口提供的CRUD方法喝噪,和Mapper接口提供的功能大同小異,比較明顯的區(qū)別在于IService支持了更多的批量化操作指么,如saveBatchsaveOrUpdateBatch等方法榴鼎。
使用示例如下:
首先伯诬,新建一個(gè)接口,繼承IService

public interface UserInfoService extends IService<UserInfoEntity> {
    //自己定義sql
    List<UserInfoEntity> queryAllBySelf();
}

創(chuàng)建這個(gè)接口的實(shí)現(xiàn)類巫财,并繼承ServiceImpl盗似,最后打上@Service注解,注冊到Spring容器中平项,即可使用

@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfoEntity> implements UserInfoService {

    @Autowired
    UserInfoMapper mapper;
    @Override
    public List<UserInfoEntity> queryAllBySelf() {
        // TODO Auto-generated method stub
        return mapper.queryAllBySelf(); 
    }
}

測試?yán)樱?/p>

@Autowired
    private UserService userService;
    @Test
    public void testGetOne() {
     LambdaQueryWrapper<UserInfoEntity> wrapper = Wrappers.<UserInfoEntity>lambdaQuery();
     wrapper.gt(User::getAge, 28);
     User one = userService.getOne(wrapper, false); // 第二參數(shù)指定為false,使得在查到了多行記錄時(shí),不拋出異常,而返回第一條記錄
     System.out.println(one);
    }

1.2.2.1 鏈?zhǔn)秸{(diào)用

鏈?zhǔn)秸{(diào)用查詢:

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

鏈?zhǔn)秸{(diào)用更新:

@Test
    public void testChainUpdate() {
     userService.lambdaUpdate()
       .gt(UserInfoEntity::getUserAge, 39)
       .likeRight(UserInfoEntity::getUserName, "王")
       .set(UserInfoEntity::getUserAccount, "w39@baomidou.com")
       .update();
    }

鏈?zhǔn)秸{(diào)用刪除:

@Test
    public void testChainDelete() {
     userService.lambdaUpdate()
       .like(UserInfoEntity::getUserName, "王")
       .remove();
    }

1.3 條件構(gòu)造器

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

在這里插入圖片描述

AbstractWrapper中提供了非常多的方法用于構(gòu)建WHERE條件缺猛,而QueryWrapper針對SELECT語句,提供了select()方法椭符,可自定義需要查詢的列荔燎,而UpdateWrapper針對UPDATE語句,提供了set()方法销钝,用于構(gòu)造set語句有咨。條件構(gòu)造器也支持lambda表達(dá)式

1.3.1 AbstractWrapper

下面對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 '%黃'
  • notLike:notLike("name","黃"),相當(dāng)于SQL的name not like '%黃%'
  • isNull
  • isNotNull
  • in
  • and:SQL連接符AND
  • or:SQL連接符OR
  • apply:用于拼接SQL匠童,該方法可用于數(shù)據(jù)庫函數(shù)埂材,并可以動態(tài)傳參

使用示例:

示例先展示需要完成的SQL語句,后展示W(wǎng)rapper的寫法

// 1. 名字中包含佳汤求,且年齡小于25
// SELECT * FROM user WHERE user_name like '%佳%' AND user_age < 25
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.like("user_name", "佳").lt("user_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字段不為空
// user_name like '黃%' AND user_age BETWEEN 20 AND 40 AND user_email is not null
wrapper.likeRight("user_name","黃").between("user_age", 20, 40).isNotNull("user_email");

// 3. 姓名為黃姓挤牛,或者年齡大于等于40莹痢,按照年齡降序排列,年齡相同則按照id升序排列
// user_name like '黃%' OR user_age >= 40 order by user_age desc, user_id asc
wrapper.likeRight("user_name","黃").or().ge("user_age",40).orderByDesc("user_age").orderByAsc("user_id");

// 4.創(chuàng)建日期為2021年3月22日墓赴,并且直屬上級的名字為李姓
// date_format(create_time,'%Y-%m-%d') = '2021-03-22' AND user_id IN (SELECT id FROM user WHERE name like '李%')
wrapper.apply("date_format(create_time, '%Y-%m-%d') = {0}", "2021-03-22") // 建議采用{index}這種方式動態(tài)傳參, 可防止SQL注入
    .inSql("user_id", "SELECT user_id FROM user WHERE user_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坦辟,或者郵箱不為空)
// user_name like '王%' AND (user_age < 40 OR user_email is not null)
wrapper.likeRight("user_name", "王").and(q -> q.lt("user_age", 40).or().isNotNull("user_email"));

// 6. 名字為王姓,或者(年齡小于40并且年齡大于20并且郵箱不為空)
// user_name like '王%' OR (user_age < 40 AND age > 20 AND user_email is not null)
wrapper.likeRight("user_name", "王").or(
    q -> q.lt("user_age",40)
      .gt("user_age",20)
      .isNotNull("user_email")
  );

// 7. (年齡小于40或者郵箱不為空) 并且名字為王姓
// (user_age < 40 OR user_email is not null) AND user_name like '王%'
wrapper.nested(q -> q.lt("user_age", 40).or().isNotNull("user_email"))
    .likeRight("user_name", "王");

// 8. 年齡為30章办,31长窄,34,35
// user_age IN (30,31,34,35)
wrapper.in("user_age", Arrays.asList(30,31,34,35));
// 或
wrapper.inSql("user_age","30,31,34,35");

// 9. 年齡為30纲菌,31挠日,34,35, 返回滿足條件的第一條記錄
// user_age IN (30,31,34,35) LIMIT 1
wrapper.in("user_age", Arrays.asList(30,31,34,35)).last("LIMIT 1");

// 10. 只選出id, name 列 (QueryWrapper 特有)
// SELECT user_id, user_name FROM user;
wrapper.select("user_id", "user_name");

// 11. 選出id, name, age, email, 等同于排除 user_id 和 create_time
// 當(dāng)列特別多, 而只需要排除個(gè)別列時(shí), 采用上面的方式可能需要寫很多個(gè)列, 可以采用重載的select方法翰舌,指定需要排除的列
wrapper.select(User.class, info -> {
   String columnName = info.getColumn();
   return !"create_time".equals(columnName) && !"user_id".equals(columnName);
  });

1.3.2 使用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í), 會拼接這個(gè)like語句到WHERE中
// 其實(shí)就是對下面代碼的簡化
if (StringUtils.hasText(name)) {
 wrapper.like("name", name);
}

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

調(diào)用構(gòu)造函數(shù)創(chuàng)建一個(gè)Wrapper對象時(shí)懂算,可以傳入一個(gè)實(shí)體對象只冻。后續(xù)使用這個(gè)Wrapper時(shí),會以實(shí)體對象中的非空屬性计技,構(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);
 }

例如:

@TableField(condition = SqlCondition.LIKE) // 配置該字段使用like進(jìn)行拼接
 private String name;

1.3.4 allEq

allEq方法傳入一個(gè)map,用來做等值匹配
當(dāng)allEq方法傳入的Map中有valuenull的元素時(shí)垮媒,默認(rèn)會設(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", "黃飛飛");
  wrapper.allEq(param);
  List<User> users = userMapper.selectList(wrapper);
  users.forEach(System.out::println);
 }

1.3.5 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);
 }

1.4 更新操作

上面介紹的都是查詢操作,現(xiàn)在來講更新和刪除操作
BaseMapper中提供了2個(gè)更新方法

1.4.1 updateById(T entity)

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

@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);
   }
  }

1.4.2 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í)體對象傳入Wrapper芯急,即用實(shí)體對象構(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);
   }

1.4.3 set更新

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

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

1.5 刪除操作

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)行刪除
    與前面查詢和更新的操作大同小異辑舷,不做贅述

1.6 分頁查詢

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

1.6.1 注冊分頁攔截器

創(chuàng)建mp的分頁攔截器,注冊到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 **/
   }

1.6.2 執(zhí)行查詢

執(zhí)行分頁查詢

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

mapper中一般寫法

IPage<Map> queryNeedByMeLaunch(IPage<Map> page, @Param("params") Map map);

在service中使用Page<Map> page = new Page<>(pageIndex,pageSize);來封裝對象

1.7 AR模式

ActiveRecord模式碌廓,通過操作實(shí)體對象传轰,直接操作數(shù)據(jù)庫表。與ORM有點(diǎn)類似
示例如下
讓實(shí)體類User繼承自Model

package com.example.mp.po;
   
   import com.baomidou.mybatisplus.annotation.SqlCondition;
   import com.baomidou.mybatisplus.annotation.TableField;
   import com.baomidou.mybatisplus.extension.activerecord.Model;
   import lombok.Data;
   import lombok.EqualsAndHashCode;
   import java.time.LocalDateTime;
   
   @EqualsAndHashCode(callSuper = false)
   @Data
   public class User extends Model<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;
   }

直接調(diào)用實(shí)體對象上的方法

@Test
    public void insertAr() {
     User user = new User();
     user.setId(15L);
     user.setName("我是AR");
     user.setAge(1);
     user.setEmail("ar@baomidou.com");
     user.setManagerId(1L);
     boolean success = user.insert(); // 插入
     System.out.println(success);
    }

其他示例:

其他示例
// 查詢
 @Test
 public void selectAr() {
  User user = new User();
        user.setId(15L);
  User result = user.selectById();
  System.out.println(result);
 }
 // 更新
 @Test
 public void updateAr() {
  User user = new User();
  user.setId(15L);
  user.setName("王全蛋");
  user.updateById();
 }
 //刪除
 @Test
 public void deleteAr() {
  User user = new User();
  user.setId(15L);
  user.deleteById();
 }

1.8 主鍵策略

在定義實(shí)體類時(shí)谷婆,用@TableId指定主鍵慨蛙,而其type屬性,可以指定主鍵策略波材。
mp支持多種主鍵策略股淡,默認(rèn)的策略是基于雪花算法的自增id。全部主鍵策略定義在了枚舉類IdType中廷区,IdType有如下的取值

1.8.1 AUTO

數(shù)據(jù)庫ID自增唯灵,依賴于數(shù)據(jù)庫。在插入操作生成SQL語句時(shí)隙轻,不會插入主鍵這一列
User上對id屬性加上注解埠帕,然后將MYSQL的user表修改其主鍵為自增

@EqualsAndHashCode(callSuper = false)
  @Data
  public class User extends Model<User> {
   @TableId(type = IdType.AUTO)
   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;
  }

測試

@Test
   public void testAuto() {
    User user = new User();
    user.setName("我是青蛙呱呱");
    user.setAge(99);
    user.setEmail("frog@baomidou.com");
    user.setCreateTime(LocalDateTime.now());
    userMapper.insert(user);
          System.out.println(user.getId());
   }

1.8.2 NONE

未設(shè)置主鍵類型。若在代碼中沒有手動設(shè)置主鍵玖绿,則會根據(jù)主鍵的全局策略自動生成(默認(rèn)的主鍵全局策略是基于雪花算法自增ID
MYSQLuser表中敛瓷,去掉主鍵自增。然后修改User類(若不配置@TableId注解斑匪,默認(rèn)主鍵策略也是NONE

@TableId(type = IdType.NONE)
  private Long id;

插入時(shí)呐籽,若實(shí)體類的主鍵ID有值,則使用之蚀瘸;若主鍵ID為空狡蝶,則使用主鍵全局策略,來生成一個(gè)ID贮勃。

1.8.3 其他生成策略

  • INPUT
    需要手動設(shè)置主鍵贪惹,若不設(shè)置。插入操作生成SQL語句時(shí)寂嘉,主鍵這一列的值會是null奏瞬。oracle的序列主鍵需要使用這種方式
  • ASSIGN_ID
    當(dāng)沒有手動設(shè)置主鍵,即實(shí)體類中的主鍵屬性為空時(shí)泉孩,才會自動填充硼端,使用雪花算法
  • ASSIGN_UUID
    當(dāng)實(shí)體類的主鍵屬性為空時(shí),才會自動填充寓搬,使用UUID

可以針對每個(gè)實(shí)體類显蝌,使用@TableId注解指定該實(shí)體類的主鍵策略,這可以理解為局部策略。若希望對所有的實(shí)體類曼尊,都采用同一種主鍵策略酬诀,挨個(gè)在每個(gè)實(shí)體類上進(jìn)行配置,則太麻煩了骆撇,此時(shí)可以用主鍵的全局策略瞒御。只需要在application.yml進(jìn)行配置即可。比如神郊,配置了全局采用自增主鍵策略

# application.yml
mybatis-plus:
  global-config:
    db-config:
      id-type: auto

附錄:mybatis-plus使用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末肴裙,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子涌乳,更是在濱河造成了極大的恐慌蜻懦,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件夕晓,死亡現(xiàn)場離奇詭異宛乃,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蒸辆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進(jìn)店門征炼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人躬贡,你說我怎么就攤上這事谆奥。” “怎么了拂玻?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵酸些,是天一觀的道長。 經(jīng)常有香客問我檐蚜,道長魄懂,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任熬甚,我火速辦了婚禮逢渔,結(jié)果婚禮上肋坚,老公的妹妹穿的比我還像新娘乡括。我一直安慰自己,他們只是感情好智厌,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布诲泌。 她就那樣靜靜地躺著,像睡著了一般铣鹏。 火紅的嫁衣襯著肌膚如雪敷扫。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天,我揣著相機(jī)與錄音葵第,去河邊找鬼绘迁。 笑死,一個(gè)胖子當(dāng)著我的面吹牛卒密,可吹牛的內(nèi)容都是我干的缀台。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼哮奇,長吁一口氣:“原來是場噩夢啊……” “哼膛腐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起鼎俘,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤哲身,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后贸伐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體勘天,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年棍丐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了误辑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,703評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡歌逢,死狀恐怖巾钉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情秘案,我是刑警寧澤砰苍,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站阱高,受9級特大地震影響赚导,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜赤惊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一吼旧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧未舟,春花似錦圈暗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至昼扛,卻和暖如春寸齐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工渺鹦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留扰法,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓毅厚,卻偏偏與公主長得像迹恐,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子卧斟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評論 2 353

推薦閱讀更多精彩內(nèi)容

  • MyBatisPlus MyBatisPlus簡稱mp,是mybatis的增強(qiáng)工具,在mybatis的基礎(chǔ)上只做增...
    幻如常閱讀 460評論 0 0
  • 一殴边、MybatisPlus簡介 1.1.簡介 Mybatis-Plus(簡稱MP)是一個(gè) Mybatis 的增強(qiáng)工...
    Waldeinsamkeit4閱讀 18,232評論 3 76
  • 1. MyBatisPlus概述 為什么要學(xué)習(xí)它呢?MyBatisPlus可以節(jié)省我們大量工作時(shí)間珍语,所有的CRUD...
    彈鋼琴的崽崽閱讀 1,989評論 0 3
  • 一锤岸、MP 是什么 MP全稱Mybatis-Plus,套用官方的解釋便是成為 MyBatis 最好的搭檔,簡稱基友板乙。...
    陳二狗想吃肉閱讀 1,505評論 0 4
  • MyBatisPlus概述 需要的基礎(chǔ):把我的MyBatis,Spring, SpringMVC就可以學(xué)習(xí)這個(gè)了是偷!...
    Raral閱讀 653評論 0 4