轉(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)用場景互婿。
- 排除非表字段
若Java
實(shí)體類中某個(gè)字段捣郊,不對應(yīng)表中的任何列,它只是用于保存一些額外的擒悬,或組裝后的數(shù)據(jù)模她,則可以設(shè)置exist
屬性為false
,這樣在對實(shí)體對象進(jìn)行插入時(shí)懂牧,會忽略這個(gè)字段侈净。排除非表字段也可以通過其他方式完成尊勿,如使用static或transient關(guān)鍵字,不做贅述- 字段驗(yàn)證策略
通過insertStrategy
畜侦,updateStrategy
元扔,whereStrategy
屬性進(jìn)行配置,可以控制在實(shí)體對象進(jìn)行插入旋膳,更新澎语,或作為WHERE
條件時(shí),對象中的字段要如何組裝到SQL
語句中验懊。- 字段填充策略
通過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
电抚,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)
主要方法介紹,如下:
1.2.1.2 selectMaps
BaseMapper
接口還提供了一個(gè)selectMaps
方法蝙叛,這個(gè)方法會將查詢結(jié)果封裝為一個(gè)Map
俺祠,Map
的key
為結(jié)果的列,value
為值
該方法的使用場景如下:
- 只查部分列
當(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);
}
- 數(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)用QueryWrapper
的select
方法設(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接口
另外一套CRUD
是Service
層的,只需要編寫一個(gè)接口蔫敲,繼承IService
饲嗽,并創(chuàng)建一個(gè)接口實(shí)現(xiàn)類,即可食用奈嘿。(這個(gè)接口提供的CRUD
方法喝噪,和Mapper
接口提供的功能大同小異,比較明顯的區(qū)別在于IService
支持了更多的批量化操作指么,如saveBatch
,saveOrUpdateBatch
等方法榴鼎。
使用示例如下:
首先伯诬,新建一個(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
接癌。QueryWrapper
,UpdateWrapper
扣讼,它們的類關(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中有value
為null
的元素時(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)行分頁查詢,分別是selectPage
和selectMapsPage
槽片,前者會將查詢的結(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 > #{%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 > #{%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
)
在MYSQL
的user
表中敛瓷,去掉主鍵自增。然后修改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