mybatis与mybatisplus的区别:
mybatisplus顾名思义时mybatis的升级版,提供了更多的API和方法,是基于mybatis框架基础上的升级,更加方便开发。mybatisplus继承BaseMapper接口并调用其中提供的方法来操作数据库,不需要再写mapper映射文件和sql语句。
一:基本入门案例
Dao层:
package com.itheima.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.domain.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserDao extends BaseMapper<User> {
}
实体类:
package com.itheima.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
//lombok
@Data
//指定表名(映射匹配兼容性)
@TableName("tbl_user")
public class User {
private long id;
private String name;
//字段名和属性名不一致
@TableField(value = "pwd")
private String password;
private Integer age;
private String tel;
//数据库中没有该字段不参与查询
@TableField(exist = false)
private Integer online;
}
application.yml配置文件信息:
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatisplus?serverTimezone=UTC
username: root
password: root
# 关闭日志
main:
banner-mode: off
# 开启mp的日志(输出到控制台可以得到sql语句)
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#清除日志中多余的标志
global-config:
banner: false
logback.xml文件用于减少代码运行时的日志信息
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
</configuration>
测试类:
@SpringBootTest
class Mybatisplus01QuickstartApplicationTests {
@Autowired
private UserDao userDao;
@Test
void testSave(){
User user=new User();
user.setName("弗拉唐");
user.setPassword("123456");
user.setAge(20);
user.setTel("123456789");
userDao.insert(user);
}
@Test
void testDelete(){
userDao.deleteById(4);
}
@Test
void testUpdate(){
User user=new User();
user.setId(3L);
user.setPassword("654321");
user.setName("李华");
userDao.updateById(user);
}
@Test
void testGetById(){
User user = userDao.selectById(3);
System.out.println(user);
}
@Test
void testAll() {
List<User> users = userDao.selectList(null);
users.stream().forEach(System.out::println);
}
二:条件查询
@Test
void testGetAll(){
//按条件查询方式一:使用QueryWrapper
QueryWrapper wrapper=new QueryWrapper();
//查询18岁以下的人
wrapper.lt("age",19);
List list = userDao.selectList(wrapper);
System.out.println(list );
//按条件查询方式二:使用lambda表达式
QueryWrapper<User> wrapper1=new QueryWrapper<User>();
wrapper1.lambda().lt(User::getAge,20);
List<User> users = userDao.selectList(wrapper1);
System.out.println(users);
//按条件查询方式三:使用
LambdaQueryWrapper<User> lqw=new LambdaQueryWrapper<>();
lqw.lt(User::getAge,20);
List<User> users1 = userDao.selectList(lqw);
System.out.println(users1);
//多条件查询
LambdaQueryWrapper<User> lqw1=new LambdaQueryWrapper<>();
//and关系
// lqw1.lt(User::getAge,20);
// lqw1.gt(User::getAge,18);
//or关系
lqw1.lt(User::getAge,18).or().gt(User::getAge,20);
List<User> users2 = userDao.selectList(lqw1);
System.out.println(users2);
//模拟页面传过来的数值
UserQuery uq=new UserQuery();
uq.setAge(18);
uq.setAge2(20);
//null值判定方法
LambdaQueryWrapper<User> lqw2=new LambdaQueryWrapper<>();
//添加参数判断是否为null,如果不为null,则添加该条件
lqw2.lt(uq.getAge2()!=null,User::getAge,uq.getAge2());
lqw2.gt(uq.getAge()!=null,User::getAge,uq.getAge());
List<User> users4 = userDao.selectList(lqw2);
System.out.println(users4);
// 查询投影(只显示某一些字段或者某一个字段)
LambdaQueryWrapper<User> lqw3=new LambdaQueryWrapper<>();
//只查询名字和年龄
lqw3.select(User::getName,User::getAge);
List<User> users5 = userDao.selectList(lqw3);
System.out.println(users5);
// 查询数量和年龄统计
QueryWrapper<User> qw=new QueryWrapper<>();
qw.select("count(*) as count,age");
qw.groupBy("age");
List<Map<String, Object>> maps = userDao.selectMaps(qw);
System.out.println(maps);
//条件查询
LambdaQueryWrapper<User> lqw4=new LambdaQueryWrapper<>();
//等同于(登录验证)
lqw4.eq(User::getName,"张三").eq(User::getPassword,"123");
User loginuser = userDao.selectOne(lqw4);
System.out.println(loginuser);
//范围查询
LambdaQueryWrapper<User> lqw5=new LambdaQueryWrapper<>();
lqw5.between(User::getAge,18,20);
List<User> users6 = userDao.selectList(lqw5);
System.out.println(users6);
//模糊匹配
LambdaQueryWrapper<User> lqw6=new LambdaQueryWrapper<>();
lqw6.like(User::getName,"三");
//这里的额left或者right指的是前后模糊匹配,也就是百分号在左边还是右边
// lqw6.likeLeft(User::getName,"三");
// lqw6.likeRight(User::getName,"三");
List<User> users7 = userDao.selectList(lqw6);
System.out.println(users7);
}
三:分页操作
分页拦截器:
定义一个Mp(mmybatisplus)拦截器,然后在里面设置具体的拦截器
package com.itheima.config;
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 MpConfig {
@Bean
public MybatisPlusInterceptor mpInterceptor(){
//1.定义Mp拦截器
MybatisPlusInterceptor mpInterceptor = new MybatisPlusInterceptor();
//2.添加具体的拦截器
mpInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mpInterceptor;
}
}
测试类:
@Test
void testGetByPage(){
//这里需要一个分页拦截器,否则数据还是会被全部打印
IPage page = new Page(1,3);
userDao.selectPage(page,null);
System.out.println("当前页码"+page.getCurrent());
System.out.println("一共多少页:"+page.getPages());
System.out.println("一共多少条数据:"+page.getTotal());
System.out.println("当前页数据:"+page.getRecords());
System.out.println("每页显示数"+page.getSize());
}
测试结果:
online为null是因为数据库中没有该字段
四:添加和删除操作:
//Id生成策略:自增,none不设置策略,Input手动添加, // ASSIGN_ID雪花算法生成id,第一位占位符,接着41位时间戳,10位机器码,12位序列号, // ASSIGN_UUID,UUID生成算法
package com.itheima.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
//lombok
@Data
//指定表名(映射匹配兼容性)
@TableName("tbl_user")
public class User {
//Id生成策略:自增,none不设置策略,Input手动添加,
// ASSIGN_ID雪花算法生成id,第一位占位符,接着41位时间戳,10位机器码,12位序列号,
// ASSIGN_UUID,UUID生成算法
@TableId(type = IdType.AUTO)
private long id;
private String name;
//字段名和属性名不一致
@TableField(value = "pwd")
private String password;
private Integer age;
private String tel;
//数据库中没有该字段不参与查询
@TableField(exist = false)
private Integer online;
}
yml全局配置,简化代码
批量删除:
@Test
void testDelete(){
// userDao.deleteById(4);
List<Long> list = new ArrayList<>();
list.add(1L);
list.add(2L);
userDao.deleteBatchIds(list);
}
逻辑删除:
因为两个表的连接,可能会导致一个人的数据的删除,另一张表的数据也丢失或者说成为脏数据。
所以逻辑删除就是在字段中添加了一个标记,避免删除操作对业务的影响
全局配置
单个配置
五:更新操作中的乐观锁(修改操作中的并发现象):
乐观锁是为了防止同一条数据被多个线程争抢,原理时在执行更新操作的sql时添加一个字段version(示例),让版本号更新,那样其他的线程就会找不到这个数据。
这时候就需要使用mp中的拦截器
@Test
void testUpdate(){
// User user=new User();
// user.setId(3L);
// user.setVersion(1);
// user.setPassword("654321");
// user.setName("jack666");
// userDao.updateById(user);
//先通过id查询出该对象
User user = userDao.selectById(3);
User user1 = userDao.selectById(3);
//将要求改的数据一起添加进去
//模拟两个用户修改
user1.setName("jack a");
userDao.updateById(user1);//version+=1
//此时下面的version找不到version=3就不会再执行成功
user.setName("jack b");
userDao.updateById(user);
}