Mybatis-Plus最優(yōu)化持久層開發(fā)過程
一:Mybatis-plus快速入門:
1.1:簡介:
Mybatis-plus(簡稱MP)是一個(gè)Mybatis的增強(qiáng)工具,在mybatis的基礎(chǔ)上只做增強(qiáng)不做改變; 提高效率;
自動(dòng)生成單表的CRUD功能;
提供了豐富的條件拼接方式;
全自動(dòng)ORM類型持久層框架;(不僅提供數(shù)據(jù)庫操作的方法,還會(huì)提供sql語句的實(shí)現(xiàn))
1.2:Mybatis-plus快速入門:
?。。。。。。。。。。。。。。。。。。。。。。。。。?!
如果我們想要對(duì)User表的數(shù)據(jù)進(jìn)行單表CRUD:
我們使用Mybatis-plus之后:我們只需要:
1.創(chuàng)建mapper接口
2.繼承 BaseMapper<User> (<>:要操作的表/實(shí)體類):我們就會(huì)擁有CRUD方法+CURD的sql語句
注意:
繼承的BaseMapper(它里面有單表的增刪改查方法),就不用寫mapper.xml文件了,
之后就可以直接使用mapper對(duì)象調(diào)用相應(yīng)的CRUD方法即可進(jìn)行數(shù)據(jù)庫的操作了?。?!
Mapper接口
public interface UserMapper extends BaseMapper<User>{
/*
原來Mybatis中:我們需要在mapper中自定義方法,然后在mapper.xml中使用sql實(shí)現(xiàn)方法
但是使用了Mybatis-plus之后,我們直接繼承 “BaseMapper<>”:它里面有單表的增刪改查各種方法以及實(shí)現(xiàn)
我們繼承它以后就擁有了這些方法,就不用寫mapper.xml文件了;
*/
}SpringBoot測試類
@SpringBootTest //這個(gè)注解:就會(huì)自動(dòng)完成ioc容器初始化,我們想要誰直接拿即可?。。。。。。。。。。。。。。。?!
public class SpringBootMybatisPlusTest {
@Autowired
private UserMapper userMapper; //拿到對(duì)象!??!
public void test(){
List<User> users = userMapper.selectList(null); //不傳參數(shù):直接寫null:代表查詢?nèi)繑?shù)據(jù);
直接調(diào)用baseMapper接口中相應(yīng)的方法即可
}
}二:Mybatis-plus的核心功能
Mybatis-plus是如何增強(qiáng)的
Mybatis-plus可以對(duì)三層架構(gòu)的兩層進(jìn)行增強(qiáng):
1.MapperC層:只要繼承,就擁有了crud方法
2.Service層:繼承
原理:!?。。。。。?!
mapper接口只要繼承BaseMapper<實(shí)體類> 接口:
接下來我們就能使用通過mapper對(duì)象和BaseMapper接口中提供的CRUD方法來對(duì) 實(shí)體類表 進(jìn)行操作;
2.1:基于Mapper接口的CRUD
(1)mapper接口
如果我們想要對(duì)User表的數(shù)據(jù)進(jìn)行單表CRUD:
我們使用Mybatis-plus之后:我們只需要:
1.創(chuàng)建mapper接口
2.繼承 BaseMapper<User> (要操作的表/實(shí)體類):我們就會(huì)擁有CRUD方法+CURD的sql語句
*/
public interface Use rMapper extends BaseMapper<User> {
//繼承之后:下面就相當(dāng)于有了方法
}
(2)測試類:
@SpringBootTest
public class MybatisPlusTest {
@Autowired
private UserMapper userMapper;
//(1)insert:
@Test
public void test(){
User user=new User();
user.setName("kun");
user.setAge(88);
user.setEmail("xxx");
//baseMapper提供的數(shù)據(jù)庫insert方法
int row = userMapper.insert(user);
}
//(2)delete:
@Test
public void test_delete(){
//1.根據(jù)id刪除:()內(nèi)裝值
int rows = userMapper.deleteById(1687124323556002889L);
//2.根據(jù)id刪除:age=20 name=jack; ()內(nèi)裝條件: -->拼接條件
Map param=new HashMap();
param.put("age",20); //-->刪除age=20 + name=jack
param.put("name","jack");
int i = userMapper.deleteByMap(param);
System.out.println("i = " + i);
//wrapper 條件封裝對(duì)象,無限封裝條件;
//userMapper.delete(wrapper)
}
//(3)Update()
@Test
public void test_update(){
//1.將主鍵userId為1的age改為30: ()內(nèi)裝值
//update user set age=30 where id=1:就等同于下方
User user=new User();
user.setId(1L);
user.setAge(30);
int i = userMapper.updateById(user);
//2.將所有人age改為20
User user1=new User();
user1.setAge(20); //
int update = userMapper.update(user1, null);// null:代表沒條件,該所有
System.out.println("update = " + update);
/*
TODO:update:當(dāng)屬性為null時(shí):代表不修改
updateById():實(shí)體類的id必須有值
update() :實(shí)體類可以沒有id值
*/
}
//(4)select a:根據(jù)主鍵查詢 b:根據(jù)主鍵集合查詢
public void test_select(){
//a:根據(jù)id查詢
User user = userMapper.selectById(1);
//b:根據(jù)集合查詢:eg:根據(jù)ids查詢
List<Long> ids=new ArrayList<>();
ids.add(1L);
ids.add(2L);
List<User> users = userMapper.selectBatchIds(ids); //selectBatchIds:批量ids
System.out.println("users = " + users);
}
}2.2:就Service接口的CRUD
service接口繼承:
2.3:分頁查詢實(shí)現(xiàn):
Mybatis-plus實(shí)現(xiàn)分頁查詢:!?。。?br /> 使用步驟:
1.導(dǎo)入分頁插件
2.使用分頁查詢
-04
@SpringBootApplication
@MapperScan("com.atguigu.mapper")
/*
啟動(dòng)類也是配置類:所以我們可以聲明帶@Bean的方法
1.配置一個(gè)分頁的插件:Mybatis-plus提供的,我們直接加進(jìn)來使用就行了;
在配置類/啟動(dòng)類:中使用@Bean返回
*/
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
@Bean
//1.將Mybatis-plus插件加到ioc容器
public MybatisPlusInterceptor plusInterceptor(){
//a:是所有Mybatis-plus的插件集合:我們想要使用任何插件都可以加到這個(gè)集合中去;eg:我們可以將分頁插件加到里面;
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
//b:加入分頁插件:
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
//指定數(shù)據(jù)庫
return mybatisPlusInterceptor;
}
}
/*
測試類:
2.之后就可以使用分頁插件了:
*/
@SpringBootTest
public class MybatisPlusTest {
@Autowired
private UserMapper userMapper; //注入U(xiǎn)serMapper對(duì)象:進(jìn)行數(shù)據(jù)庫操作
@Test
public void testPage(){
//a:創(chuàng)建Page對(duì)象: 參數(shù)解釋:(參數(shù)1:頁碼, 參數(shù)2:頁容量)
Page<User> page=new Page<>(1,3);
userMapper.selectPage(page,null); //需要放入Page對(duì)象
//最后分頁的結(jié)果也會(huì)被封裝到page里面:-->所以直接通過page對(duì)象獲取結(jié)果即可
long pages = page.getPages();
long current = page.getCurrent(); //獲取當(dāng)前頁碼、
List<User> records = page.getRecords(); //獲取當(dāng)前頁數(shù)據(jù)
long total = page.getTotal();//獲取總條數(shù)
}
}自定義mapper方法使用分頁
上面:我們是使用Mybatis提供的方法: userMapper.selectPage(page,null);
如果我們自定義的mapper方法想要使用分頁查詢:
1.在mapper接口中定義方法:
自定義方法想要分頁:在第一個(gè)參數(shù)加一個(gè)IPage對(duì)象,返回值也是IPage
2.在mapper文件中實(shí)現(xiàn):使用sql語句實(shí)現(xiàn):不要加limit和;
3.測試
public interface UserMapper extends BaseMapper<User> {
//繼承BaseMapper接口:里面有單表的方法
/*
演示:自定義mapper方法實(shí)現(xiàn)分頁:
eg:查詢
*/
//1.在mapper接口中定義抽象方法:但是:方法的第一個(gè)參數(shù):要傳一個(gè)IPage,返回值要是IPage,里面寫查詢集合的泛型即可
IPage<User> queryByAge(IPage<User>page, @Param("age") Integer age);
}
2.
<!--2.使用sql語句實(shí)現(xiàn)UserMapper接口的方法:不用在最后加limit,!-->
<select id="queryByAge" resultType="com.atguigu.pojo.User"> <!--resultType:泛型-->
select * from user where age>#{age}
</select>
3.
/*
3.測試自定義方法分頁
*/
public void test_MyPage(){
//a:傳一個(gè)分頁插件的值:
Page<User> page=new Page<>(1,3);
//b.
userMapper.queryByAge(page,1);
//c:
//最后分頁的結(jié)果也會(huì)被封裝到page里面:-->所以直接通過page對(duì)象獲取結(jié)果即可
long pages = page.getPages();
long current = page.getCurrent(); //獲取當(dāng)前頁碼、
List<User> records = page.getRecords(); //獲取當(dāng)前頁數(shù)據(jù)
long total = page.getTotal();//獲取總條數(shù)
System.out.println("total:"+total);
}
}2.4:條件構(gòu)造器使用:
2.4.1條件構(gòu)造器的作用:
warpper對(duì)象:動(dòng)態(tài)進(jìn)行 條件的拼接;
就相當(dāng)于在sql語句后面加條件,只是使用java代碼的格式;
---->:就不用在mapper.xml文件中使用sql語句實(shí)現(xiàn)了,直接使用java代碼來代替sql語句;?。。。。。。?!
warpper對(duì)象:動(dòng)態(tài)進(jìn)行 條件的拼接;
就相當(dāng)于在sql語句后面加條件,只是使用java代碼的格式;
---->:就不用在mapper.xml文件中使用sql語句實(shí)現(xiàn)了,直接使用java代碼來代替sql語句;?。。。。。。。?/p>
2.4.2條件構(gòu)造器的類結(jié)構(gòu):
一般使用:
第一種: UpdateWrapper(修改)、QueryWrapper(刪除、查詢、修改)
第二種: LambdaUpdateWrapper(修改)、 LambdaQueryWrapper(刪除、查詢、修改)
(1)第一種:基于queryWrapper組裝條件:增/刪/改
使用方法:
1.在mapper接口中定義方法,并繼承base接口(提供了各種方法的實(shí)現(xiàn))
2.直接使用java代碼實(shí)現(xiàn):不需要在mapper.xml文件中實(shí)現(xiàn)了
//a:創(chuàng)建QueryWrapper
QueryWrapper<實(shí)體類>queryWrapper=new QueryWrapper<>();
//b:條件拼接:調(diào)用queryWrapper方法
//c:使用mappper對(duì)象:調(diào)用CRUD方法,傳入對(duì)象即可1.mapper接口:
public interface UserMapper extends BaseMapper<User> {
//繼承BaseMapper接口:里面有單表的方法
/*
演示:自定義mapper方法實(shí)現(xiàn)分頁:
eg:查詢
*/
//1.在mapper接口中定義抽象方法:但是:方法的第一個(gè)參數(shù):要傳一個(gè)IPage,返回值要是IPage,里面寫查詢集合的泛型即可
IPage<User> queryByAge(IPage<User>page, @Param("age") Integer age);
}
2.
/*
演示條件構(gòu)造器使用:進(jìn)行條件的動(dòng)態(tài)拼接:
(1)QueryWrapper測試:
*/
@SpringBootTest
public class MybatisPlusQueryWrapper {
@Autowired
private UserMapper userMapper; //拿到對(duì)象:操作數(shù)據(jù)庫
@Test
public void test_01(){
//查詢用戶名包含 a,age在20到30之間的,且郵箱不為空的用戶;
//分析:查詢:返回的是集合List-->selectList
//a:創(chuàng)建一個(gè)QueryWrapper集合:相當(dāng)于容器來裝條件
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
//b:之后sql語句的條件:直接使用queryWrapper動(dòng)態(tài)調(diào)用wrapper的方法來完成動(dòng)態(tài)拼接;
queryWrapper.like("name","a"); //條件1:name種包含a的
queryWrapper.between("age",20,30); //條件2:age在20-30之間
queryWrapper.isNotNull("email"); //第三個(gè)條件:email不為null
List<User> users = userMapper.selectList(queryWrapper); ----->:因?yàn)槔^承了base接口,所以單表直接調(diào)用方法即可!
//queryWrapper就是sql條件,將它·傳進(jìn)去?。。?
//之后這個(gè)就會(huì)變成sql語句; ?。。。。。。。。。?!
//就相當(dāng)于:select * from user where name(like %a% and age>=20 and age<=30 and email is not null)
/*
!!!一個(gè)個(gè)調(diào)用麻煩,可以使用鏈?zhǔn)秸{(diào)用:?。。。?
queryWrapper.like("name","a").between("age",20,30).isNotNull("email");
*/
}
}@SpringBootTest
public class MybatisPlusQueryWrapper {
@Autowired
private UserMapper userMapper; //拿到對(duì)象:操作數(shù)據(jù)庫按照年齡降序查詢用戶,如果年齡age相同則按id升序排列
//(2)queryWrapper:按年齡降序查詢用戶,如果年齡相同則按id升序排列
@Test
public void test_02(){
//a:創(chuàng)建QueryMapper集合:裝條件
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
//b:使用條件構(gòu)造器進(jìn)行條件的拼接:
queryWrapper.orderByDesc("age").orderByAsc("id");
//a:條件1:age降序排列; b:條件2:id增序
//c:放到queryWrapper中,進(jìn)行條件拼接; ==order by age desc,id asc
List<User> users = userMapper.selectList(queryWrapper);
}
//(3)刪除email為null的用戶
@Test
public void test_03(){
//a:
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
//b:
queryWrapper.isNotNull("email");
//c:
int delete = userMapper.delete(queryWrapper);
}
//(4):將age>20且用戶名中包含a或email為null的用戶信息修改:
//分析:修改:--update:所以u(píng)sermapper調(diào)用update方法
:相應(yīng)的條件:age>20... 使用queryWrapper封裝,然后作為條件放入update方法形參中;!!!!!
@Test
public void test_04(){
//a:
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
//b:添加條件:
queryWrapper.gt("age",20).like("name","a") ---------->B:相當(dāng)于:where .......
.or().isNotNull("email");
//1.條件:age>20 name包含a,--->:條件直接調(diào)用時(shí):默認(rèn)自動(dòng)使用and進(jìn)行拼接;?。。。?!
//queryWrapper.gt("age",20).like("name","a") == where age>20 and ..
//2.如果想要在條件之后追加or關(guān)鍵字:可以使用: “or().條件”;
//c:創(chuàng)建User對(duì)象,進(jìn)行update修改
User user=new User();
user.setAge(88); ----->A:相當(dāng)于update user set name="" age=
user.setEmail("hehe");
//d:如果要修改:第一位傳入要修改的對(duì)象
userMapper.update(user, queryWrapper); //放入對(duì)象 + queryWrapper
}
//(5):查詢用戶信息的name和age字段; --->指定列查詢?。。?
//select name,age from t_user where id>1;
public void test_05() {
//a:
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//b:條件拼接:
queryWrapper.gt("age",1);
//!!!查詢時(shí):默認(rèn)是查詢?nèi)????。。。?!,但可以使用select指定
queryWrapper.select("name","age");
userMapper.selectList(queryWrapper);
}
//(6)前端傳入兩個(gè)參數(shù),name,age:---->:動(dòng)態(tài)條件組織判斷!?。?!
// 只要name不為null,就作為條件 來查詢符合的
//只要age>18作為條件,就作為條件 來查詢符合的
@Test
public void test_06(){
String name="xx";
Integer age=19;
//a:
QueryWrapper<User>queryWrapper=new QueryWrapper<>();
//b:進(jìn)行條件拼接:
//b.1:如果name!=null,就使用queryWrapper進(jìn)行條件拼接
if(StringUtils.isNotBlank(name)){ //調(diào)用isNotBlank進(jìn)行判斷
//動(dòng)態(tài)條件判斷:如果name不為null,就進(jìn)行條件的拼接
queryWrapper.eq("name",name); //使用queryWrapper進(jìn)行拼接
}
//b.2:如果age>18 進(jìn)行動(dòng)態(tài)拼接:
if (age>18 && age!=null){
queryWrapper.eq("age",age);
}
userMapper.selectList(queryWrapper);
/*
注意:!!!!!!!!!!!!!!!!
Wrapper每個(gè)方法都有:一個(gè)boolean類型的condition,允許我們第一個(gè)參數(shù)放一個(gè)比較表達(dá)式,
:如果condition為true-->整個(gè)條件為true,就執(zhí)行下面代碼
:如果condition為false-->整個(gè)條件為false,就失效,不執(zhí)行下面代碼
-->condition里面有動(dòng)態(tài)判斷,就不用我們?cè)谕獠繉懪袛嗔?
eg:
*/
queryWrapper.eq(StringUtils.isNotBlank(name),"name",name);
queryWrapper.eq(age>18 && age!=null,"age",age);
}(2)queryWrapper實(shí)戰(zhàn)使用:
@SpringBootTest
public class MybatisPlusQueryWrapper {
@Autowired
private UserMapper userMapper; //拿到對(duì)象:操作數(shù)據(jù)庫按照年齡降序查詢用戶,如果年齡age相同則按id升序排列
//(2)queryWrapper:按年齡降序查詢用戶,如果年齡相同則按id升序排列
@Test
public void test_02(){
//a:創(chuàng)建QueryMapper集合:裝條件
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
//b:使用條件構(gòu)造器進(jìn)行條件的拼接:
queryWrapper.orderByDesc("age").orderByAsc("id");
//a:條件1:age降序排列; b:條件2:id增序
//c:放到queryWrapper中,進(jìn)行條件拼接; ==order by age desc,id asc
List<User> users = userMapper.selectList(queryWrapper);
}
//(3)刪除email為null的用戶
@Test
public void test_03(){
//a:
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
//b:
queryWrapper.isNotNull("email");
//c:
int delete = userMapper.delete(queryWrapper);
}
//(4):將age>20且用戶名中包含a或email為null的用戶信息修改:
//分析:修改:--update:所以u(píng)sermapper調(diào)用update方法
:相應(yīng)的條件:age>20... 使用queryWrapper封裝,然后作為條件放入update方法形參中;!!!!!
@Test
public void test_04(){
//a:
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
//b:添加條件:
queryWrapper.gt("age",20).like("name","a") ---------->B:相當(dāng)于:where .......
.or().isNotNull("email");
//1.條件:age>20 name包含a,--->:條件直接調(diào)用時(shí):默認(rèn)自動(dòng)使用and進(jìn)行拼接;?。。。?!
//queryWrapper.gt("age",20).like("name","a") == where age>20 and ..
//2.如果想要在條件之后追加or關(guān)鍵字:可以使用: “or().條件”;
//c:創(chuàng)建User對(duì)象,進(jìn)行update修改
User user=new User();
user.setAge(88); ----->A:相當(dāng)于update user set name="" age=
user.setEmail("hehe");
//d:如果要修改:第一位傳入要修改的對(duì)象
userMapper.update(user, queryWrapper); //放入對(duì)象 + queryWrapper
}
//(5):查詢用戶信息的name和age字段; --->指定列查詢?。?!
//select name,age from t_user where id>1;
public void test_05() {
//a:
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//b:條件拼接:
queryWrapper.gt("age",1);
//!!!查詢時(shí):默認(rèn)是查詢?nèi)????。。。。?,但可以使用select指定
queryWrapper.select("name","age");
userMapper.selectList(queryWrapper);
}
//(6)前端傳入兩個(gè)參數(shù),name,age:---->:動(dòng)態(tài)條件組織判斷?。。?!
// 只要name不為null,就作為條件 來查詢符合的
//只要age>18作為條件,就作為條件 來查詢符合的
@Test
public void test_06(){
String name="xx";
Integer age=19;
//a:
QueryWrapper<User>queryWrapper=new QueryWrapper<>();
//b:進(jìn)行條件拼接:
//b.1:如果name!=null,就使用queryWrapper進(jìn)行條件拼接
if(StringUtils.isNotBlank(name)){ //調(diào)用isNotBlank進(jìn)行判斷
//動(dòng)態(tài)條件判斷:如果name不為null,就進(jìn)行條件的拼接
queryWrapper.eq("name",name); //使用queryWrapper進(jìn)行拼接
}
//b.2:如果age>18 進(jìn)行動(dòng)態(tài)拼接:
if (age>18 && age!=null){
queryWrapper.eq("age",age);
}
userMapper.selectList(queryWrapper);
/*
注意:!!!!!!!!!!!!!!!!
Wrapper每個(gè)方法都有:一個(gè)boolean類型的condition,允許我們第一個(gè)參數(shù)放一個(gè)比較表達(dá)式,
:如果condition為true-->整個(gè)條件為true,就執(zhí)行下面代碼
:如果condition為false-->整個(gè)條件為false,就失效,不執(zhí)行下面代碼
-->condition里面有動(dòng)態(tài)判斷,就不用我們?cè)谕獠繉懪袛嗔?
eg:
*/
queryWrapper.eq(StringUtils.isNotBlank(name),"name",name);
queryWrapper.eq(age>18 && age!=null,"age",age);
}updateWrapper:改
進(jìn)行修改時(shí):使用updateWrapper:?。。?!
//a:
UpdateWrapper<User> queryWrapper=new UpdateWrapper<>();
//b:
queryWrapper.gt("age",20).like("name","a").isNotNull("email")
.set("email",null).set("age",100);
//c:
userMapper.update(null,queryWrapper);在修改時(shí)updateWrapper和queryWrapper區(qū)別:
(參數(shù)1:條件; 參數(shù)2:修改的數(shù)據(jù)) queryWrapper修改:參數(shù)1只能放條件,且列名不能為null updateWrapper修改:參數(shù)1可以放條件, 且列名可以設(shè)置為null; 且可以直接調(diào)用set方法進(jìn)行修改
(2)第二種:
和第一種用法一樣,只是對(duì)第一種的增強(qiáng)
eg:
Lambda:避免列寫錯(cuò)的機(jī)制:傳入的列名可以是” 方法引用的表達(dá)式 “:類名::getName -->相當(dāng)于找方法對(duì)應(yīng)的列名LambdaQueryWrapper:增/刪/改
eg: 查詢用戶名包含 a like,年齡在20-30之間,并且郵箱不為null的用戶信息; LambdaQueryWrapper<User>lambdaQueryWrapper=new LambdaQueryWrapper<>(); //即只要將原來的列名,變?yōu)長ambda方法引用即可,其余不變?。。。。。。。。?! lambdaQueryWrapper.like(User::getName,"a").between(User::getAge,20,30).isNotNull(User::getEmail); userMapper.selectList(queryWrapper);
LambdaupdateWrapper:改
eg: LambdaUpdateWrapper<User>lambdaUpdateWrapper=new LambdaUpdateWrapper<>(); //即只要將原來的列名,變?yōu)長ambda方法引用即可,其余不變?。。。。。。。。?! lambdaUpdateWrapper.gt(User::getAge,20).like(User::getName,"a").isNotNull(User::getEmail) .set(User::getEmail,null).set(User::getAge,100); userMapper.update(null,lambdaUpdateWrapper);
(3)總結(jié):
Wrapper:里面:完成了動(dòng)態(tài)條件封裝
最終推薦使用Lambda;(不用寫列名,只需類名::方法即可)
如果復(fù)雜的sql:qg:嵌套、子查詢 不會(huì)使用Wrapper怎么辦:
我們?nèi)匀皇褂迷瓉淼模憾xmapper
如果為單表的話:直接使用mapper對(duì)象調(diào)用CRUD方法即可;
如果為多表的話:在mapper.xml文件中實(shí)現(xiàn);
2.5Mybatis-plus核心注解的使用:
注解的作用:指定實(shí)體類和表之間的映射;
1.@TableName
作用:指定數(shù)據(jù)庫表名;(當(dāng)【BaseMapper<實(shí)體類>】 實(shí)體類名 和 數(shù)據(jù)庫表名不同時(shí));
使用:@TableName("數(shù)據(jù)庫表名")
a:位置:加到實(shí)體類上
b:可以不加,不加的話默認(rèn)使用實(shí)體類的名字作為 表名! 忽略大小寫;
eg:BaseMapper<User>:默認(rèn)將實(shí)體類名:User,作為表名 來進(jìn)行操作;
c:使用@TableName注解場景:
當(dāng)數(shù)據(jù)庫的表名和實(shí)體類名稱不同時(shí)(忽略大小寫),需要使用@TableName來指定 表名:
eg:數(shù)據(jù)庫名:t_user; 實(shí)體類名:User
兩個(gè)名稱不同,此時(shí)我們需要在實(shí)體類上方使用: ”@TableName("t_user")“ 來指定表名;
d: 如果表名命名規(guī)范:eg:都以 "t_"開頭,且除了”t_“以外,實(shí)體類名=表名
我們可以將前綴統(tǒng)一提取到配置文件中(application.yml),這樣就不需要每個(gè)實(shí)體類都加@TableName注解來指定表名了
它會(huì)自動(dòng)查找相應(yīng)的表;
mybatis-plus:
global-config:
db-config:
table-prefix: t_ #表名前綴;
#加了這個(gè)之后,我們就不需要在每個(gè)實(shí)體類加@TableName注解了,它就會(huì)自己根據(jù)前綴"t_"進(jìn)行查找;
#前提:數(shù)據(jù)庫的表都是以 “t_”開頭的
2.@TableId:
作用:描述主鍵的一些特性;
eg: value:指定表主鍵名; type:設(shè)置主鍵type策略
使用:在實(shí)體類的主鍵屬性上:+@TableId(value="主鍵列名",type="主鍵策略");
b:位置:加到實(shí)體類的主鍵屬性上
c:使用@TableId的場景:
場景1:
表 主鍵的列名 和 實(shí)體類的屬性名 不一致時(shí),使用這個(gè)注解來指定表的列名;!!!
eg: 1:如果 實(shí)體類屬性名:id; 數(shù)據(jù)庫主鍵列名:x_id; --->兩個(gè)名稱不一樣,我們可以在實(shí)體類主鍵的屬性上方加
@TableId(value="x_id")
場景2:
設(shè)置表主鍵增長:
type主鍵策略:
type增長策略:
@SpringBootTest
public class MybatisPlusTableIdTest {
@Autowired
private UserMapper userMapper;
@Test
public void test_01(){
//以插入數(shù)據(jù)舉例:
User user=new User();
user.setName("坤坤");
user.setAge(20);
user.setEmail("xxx@qq.com");
//插入的時(shí)候:主鍵id不要賦值; 主鍵自增長 或者 type策略 進(jìn)行賦值?。。。。。。。。。。?!
/*
1.默認(rèn)主鍵的type(策略)是:雪花算法;--->:它會(huì)生成一個(gè)不重復(fù)的long類型的數(shù)字; eg:123456789
雪花算法:
a:要求數(shù)據(jù)庫主鍵是 bigint / varchar(64) 類型; -->:eg:varchar(64)/bigint money;!!!
b:要求實(shí)體類相應(yīng)屬性:使用Long/String接值(int接不到) -->:eg:Long/String money;!!!
c:隨機(jī)生成一個(gè)數(shù)字,給予主鍵值(不重復(fù))
2.但我們想要把主鍵type(策略)變成auto自增長,
方式1:直接在實(shí)體類的主鍵上方加:@TableId(type= IdType.AUTO); 前提是mysql數(shù)據(jù)庫必須設(shè)置了主鍵自增長(auto_increment)
auto:
a:要求mysql數(shù)據(jù)庫的 表主鍵 必須設(shè)置了 自增長
b:插入數(shù)據(jù)就是自增長了
方式2:全局設(shè)置主鍵自增長策略:如果每個(gè)表都設(shè)置為自增長(auto),在配置文件(application.yml)中配置
*/
userMapper.insert(user); //之間調(diào)用BaseMapper中的insert方法;
}
}
User視圖類:
public class User(){
@TableId(type = IdType.AUTO)
private Long id;
}3.@TableFiled
作用:描述非主鍵字段
使用:在實(shí)體類的非主鍵字段上:+@TableFiled(value="",exist="")
a:使用場景1:value="" (不是必須指定的,String類型)
:當(dāng)實(shí)體類的屬性名 和 列名 不同的時(shí)候 使用@TableFiled指定數(shù)據(jù)庫表名;
使用場景2:esist=ture/false; (默認(rèn)為true)
:eg:@TableFiled(value="name",exist=false):
private String name;
-->:false代表:認(rèn)為name沒有數(shù)據(jù)庫對(duì)應(yīng)的列,因此在查詢等時(shí)候不會(huì)對(duì)他進(jìn)行操作;
三:Mybatis-plus高級(jí)擴(kuò)展
3.1邏輯刪除實(shí)現(xiàn):
(1)邏輯刪除概念:
邏輯刪除:是 "假刪除數(shù)據(jù)":是將想要?jiǎng)h除數(shù)據(jù)的狀態(tài)修改為 "被刪除狀態(tài)",但是數(shù)據(jù)并沒有消失,之后在查詢時(shí),查詢沒有 刪除狀態(tài) 的數(shù)據(jù),也是一種刪除;
物理刪除:delete from:刪除之后就沒有了相應(yīng)的數(shù)據(jù);
(2)邏輯刪除的實(shí)現(xiàn):
方式1:單個(gè)表邏輯刪除的實(shí)現(xiàn):
a:在數(shù)據(jù)庫表中 插入一個(gè)邏輯刪除字段(int類型,有1/0狀態(tài)字段!):
alert table User add deleted int default 1/0; -->: 1/0:邏輯刪除的狀態(tài)字段:1代表:邏輯刪除; 0代表:未邏輯刪 除;!!!!
b:在實(shí)體類的對(duì)應(yīng)屬性上加:@TableLogic
eg:
@TableLogic //代表這個(gè)屬性對(duì)應(yīng)的列是 :邏輯刪除狀態(tài)字段
//當(dāng)我們刪除數(shù)據(jù)時(shí)候,自動(dòng)變成修改此列的屬性值(即將deleted變?yōu)?); 默認(rèn):0是未刪除,1是刪除
//當(dāng)我們查詢數(shù)據(jù)時(shí)候:默認(rèn)只查詢 deleted=0 的列的數(shù)據(jù)
private Integer deleted;
方式2:多個(gè)表邏輯刪除的實(shí)現(xiàn)(全局指定):
a:同上
b:在配置文件(application.yml)中:配置
mybatis-plus:
global-config:
db-config:
logic-delete-field: deleted # 全局邏輯刪除的實(shí)體屬性名
注意:這種就不需要在類的屬性名上 + @TableLogic了
但是仍然需要在實(shí)體類中創(chuàng)建一個(gè)和列名deleted 對(duì)應(yīng)的屬性名;
代碼演示:
以單個(gè)表實(shí)現(xiàn)邏輯刪除為例:
@TableLogic
private Integer deleted;
@SpringBootTest
public class MybatisPlusTableLogicTest {
@Autowired
private UserMapper userMapper;
public void test_01(){
//a:之前是物理刪除:delete from user where id=5;
//b:現(xiàn)在:邏輯刪除:相當(dāng)于:update user set deleted=1 where id=5
userMapper.deleteById(5);
//eg:
userMapper.selectList(null); -->之后在查詢時(shí):就只會(huì)查詢deleted=0的了:?。。。。。ㄗ詣?dòng)在條件位置加上where deleted=0)
}3.2樂觀鎖的實(shí)現(xiàn)
1.樂觀鎖 和悲觀鎖 都是在 并發(fā)編程 中用于處理并發(fā)訪問和資源競爭的兩種不同機(jī)制; 2.(1)悲觀鎖: 同步鎖/互斥鎖:線程在訪問共享資源之前會(huì)獲取到鎖,在數(shù)據(jù)訪問時(shí)只允許一個(gè)線程訪問資源,只有當(dāng)前線程訪問完成只后,才會(huì)釋放鎖,讓其它線程繼續(xù)操作資源; (2)樂觀鎖:不需要提前加鎖,而是在數(shù)據(jù)更新階段進(jìn)行檢測 樂觀鎖和悲觀鎖是兩種解決并發(fā)數(shù)據(jù)問題的思路,不是技術(shù)??! 3.具體的技術(shù)和方案: 1.樂觀鎖實(shí)現(xiàn)方案和技術(shù) 版本號(hào)/時(shí)間戳 CAS 無鎖數(shù)據(jù)結(jié)構(gòu) 2.悲觀鎖的實(shí)現(xiàn)方案和技術(shù) 鎖機(jī)制 數(shù)據(jù)庫鎖 信號(hào)量 4. 現(xiàn)在主要學(xué)習(xí)如何使用樂觀鎖(版本號(hào))解決并發(fā)問題?。。。?!!! (1)版本號(hào):解決數(shù)據(jù)并發(fā)更新出現(xiàn)錯(cuò)誤數(shù)據(jù)的問題;--->保證數(shù)據(jù)一致性; (2)樂觀鎖技術(shù)的實(shí)現(xiàn)流程: a:每條數(shù)據(jù)添加一個(gè)版本號(hào)字段version b:取出記錄時(shí),獲取當(dāng)前version c:更新時(shí),檢查獲取版本號(hào)是不是數(shù)據(jù)庫當(dāng)前最新版本號(hào) d:如果是(代表沒人修改過數(shù)據(jù)),執(zhí)行更新:set數(shù)據(jù)更新,version=version+1 e:如果不是(證明已經(jīng)修改過了),更新失敗 5.使用mybatis-plus數(shù)據(jù)使用樂觀鎖 步驟: 1.數(shù)據(jù)庫插入一個(gè)version字段:alert table user add version int default 1 (int類型 樂觀鎖字段) 2 實(shí)體類創(chuàng)建相應(yīng)的屬性: private Integer version; + 在屬性上方使用@Version注解 3.添加攔截器(添加版本號(hào)更新插件) 之后在更新的時(shí)候就會(huì)檢查版本,檢查數(shù)據(jù)錯(cuò)誤的問題;
樂觀鎖測試:
1.
alter table user add version int default 1; #int 類型 樂觀鎖字段
2.
public class User {
@Version
private Integer version; //版本號(hào)字段
}
//注意:之后在數(shù)據(jù)修改時(shí)都會(huì)檢查樂觀鎖;
3.在配置類/Main類中加入攔截器
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
@Bean
public MybatisPlusInterceptor plusInterceptor(){
//攔截器2:樂觀鎖【版本號(hào)插件】 mybatis-plus在每次更新時(shí)候,每次幫我們對(duì)比版本號(hào)字段和增加版本號(hào)+1
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mybatisPlusInterceptor;
}
4.
/*
測試樂觀鎖實(shí)現(xiàn)
*/
@SpringBootTest
public class MybatisPlusVersionTest {
private UserMapper userMapper;
@Test
public void testById(){
//步驟1:先查詢,再更新 獲取version數(shù)據(jù)
//同時(shí)查詢兩條,但是version唯一,最后更新的失敗、
User user=new User(); //user 版本號(hào)為:1
User user1=new User(); //user1 版本號(hào)為:1
user.setAge(20);
user.setAge(30);
userMapper.updateById(user); //20-->:此時(shí)數(shù)據(jù)庫的version ->2
//樂觀鎖生效:失敗
userMapper.updateById(user1);
//因?yàn)閡ser1的版本號(hào)為1,但是數(shù)據(jù)庫的版本號(hào)為2,證明不是最新數(shù)據(jù) -->1!=2,樂觀鎖生效,更新失敗
//所以最終age為:20
}
}3.3防止全表更新和刪除
在開發(fā)中一般不會(huì)出現(xiàn)全表的更新/刪除:
Mybatis-plus提供一種防御插件:一旦檢測到是全表的update/delete:就會(huì)報(bào)異常;
實(shí)現(xiàn)方法:添加防止全表更新和刪除的攔截器:
代碼測試:
1.加入攔截器/插件:
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
@Bean
public MybatisPlusInterceptor plusInterceptor(){
//攔截器3:防止全表刪除和更新的攔截器
mybatisPlusInterceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
return mybatisPlusInterceptor;
}
2.測試類中:
public void test(){
@Au..
private UserMapper userMapper; //拿到mapper對(duì)象,進(jìn)行數(shù)據(jù)庫操作?。?!;
//a:全表刪除!
mapper.delete(null); ----->:null,代表沒有寫條件,代表:全表刪除;
//b:全表更新:
mapper.update(null); ------>: null,代表沒有條件,代表全表更新!
----------->:之后就會(huì)拋出異常:不允許全表delete/update!?。。。。。?
}四:Mybatis-Plus代碼生成器(MybatisX插件)!!!!!!!!!!!!!
學(xué)習(xí)目標(biāo):
1.如何使用MybatisX插件: 逆向工程 生成Mybatis-Plus代碼;
//逆向工程:根據(jù)表自動(dòng)生成實(shí)體類、mapper、service;!!!!!!!!!!!!!!!!!!!!!!
2. 使用MybatisX插件 動(dòng)態(tài)生成自定義的sql語句
4.1Mybatis插件逆向工程
//逆向工程:根據(jù)表自動(dòng)生成實(shí)體類、mapper、service;!!!!!!!!!!!!!!!!!!!!!!
步驟:
連接數(shù)據(jù)庫;
.....
4.2Mybatis-plus快速生成單表CRUD代碼(自定義sql)?。。。。。。。?/h3>
如果我們需要自己定義一些sql語句:
eg:批量查詢、根據(jù)id查詢......
//步驟:
1.直接在mapper接口中書寫相應(yīng)的 ” 方法名 “ (//按照mybatisX的方法命名規(guī)則)
eg:批量插入:insertBatch
根據(jù)條件查詢:selectByNameAndAgeAndAge
2.然后鼠標(biāo)放在方法名上,點(diǎn)擊MybatisX,
--->MybatisX 就會(huì)在mapper接口自動(dòng)寫好 且 在mapper.xml文件中自動(dòng)生成sql語句!?。。。。。。?
//之后有關(guān)單表的CRUD我們就不需要自己寫了?。。。。。。。。?!
//我們可以看mybatisX的官方文檔:介紹了如何寫
如果我們需要自己定義一些sql語句: eg:批量查詢、根據(jù)id查詢...... //步驟: 1.直接在mapper接口中書寫相應(yīng)的 ” 方法名 “ (//按照mybatisX的方法命名規(guī)則) eg:批量插入:insertBatch 根據(jù)條件查詢:selectByNameAndAgeAndAge 2.然后鼠標(biāo)放在方法名上,點(diǎn)擊MybatisX, --->MybatisX 就會(huì)在mapper接口自動(dòng)寫好 且 在mapper.xml文件中自動(dòng)生成sql語句!?。。。。。。? //之后有關(guān)單表的CRUD我們就不需要自己寫了?。。。。。。。。?! //我們可以看mybatisX的官方文檔:介紹了如何寫
到此這篇關(guān)于Mybatis-Plus最優(yōu)化持久層開發(fā)的文章就介紹到這了,更多相關(guān)Mybatis-Plus持久層開發(fā)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java Fluent Mybatis實(shí)戰(zhàn)之構(gòu)建項(xiàng)目與代碼生成篇下
Java中常用的ORM框架主要是mybatis, hibernate, JPA等框架。國內(nèi)又以Mybatis用的多,基于mybatis上的增強(qiáng)框架,又有mybatis plus和TK mybatis等。今天我們介紹一個(gè)新的mybatis增強(qiáng)框架 fluent mybatis2021-10-10
SpringCloud超詳細(xì)講解負(fù)載均衡組件Ribbon源碼
在微服務(wù)中,對(duì)服務(wù)進(jìn)行拆分之后,必然會(huì)帶來微服務(wù)之間的通信需求,而每個(gè)微服務(wù)為了保證高可用性,又會(huì)去部署集群,那么面對(duì)一個(gè)集群微服務(wù)進(jìn)行通信的時(shí)候,如何進(jìn)行負(fù)載均衡也是必然需要考慮的問題2022-07-07
基于UDP協(xié)議實(shí)現(xiàn)聊天系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了基于UDP協(xié)議實(shí)現(xiàn)聊天系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04
springboot 定時(shí)任務(wù)@Scheduled實(shí)現(xiàn)解析
這篇文章主要介紹了springboot 定時(shí)任務(wù)@Scheduled實(shí)現(xiàn)解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09
Springboot工具類FileCopyUtils使用教程
這篇文章主要介紹了Springboot內(nèi)置的工具類之FileCopyUtils的使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-12-12
Java中Set與List的關(guān)系與區(qū)別介紹
這篇文章主要介紹了Java中Set與List的關(guān)系與區(qū)別介紹,本文總結(jié)它們兩個(gè)接口都是繼承自Collection、它們之間的存儲(chǔ)方式不一樣,需要的朋友可以參考下2015-03-03

