飞道的博客

MyBatis-Plus(详解)

463人阅读  评论(0)

🍁博客主页:👉不会压弯的小飞侠
✨欢迎关注:👉点赞👍收藏⭐留言✒
✨系列专栏:👉MyBatis-Plus专栏
✨如果觉得博主的文章还不错的话,请三连支持一下博主。
🔥欢迎大佬指正,一起 学习!一起加油!


🍁MyBatisPlus简介

  • MyBatisPlus(简称MP)是基于MyBatis框架基础上开发的增强型工具,旨在简化开发、提高效率。

  • 开发方式

    • 基于MyBatis使用MyBatisPlus
    • 基于Spring使用MyBatisPlus
    • 基于SpringBoot使用MyBatisPlus

🍁MyBatisPlus快速入门案例

  • 本案例采用SpringBoot整合MyBatis开发
  • 创建SpringBoot工程
  1. 创建过程在这就不过多描述,详细过程在Springboot专栏里👉点击直接查看
  2. 勾选配置使用的技

  1. 手动添加MP依赖:
        <dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-boot-starter</artifactId>
			<version>3.4.1</version>
		</dependency>

⭐⭐⭐注意:阿里云版本可以直接勾选MyBatisPlus

  1. 设置dataSource相关属性(JDBC参数)
spring:
  datasource:
    driver-class-name=com: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatisplus?serverTimezone=UTC
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

使用Druid数据源,需要导入坐标:

	<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.2.11</version>
		</dependency>
  1. 创建实体类(User)
package com.jkj.domain;
import lombok.Data;
@Data
public class User {
   
    private Long id;
    private String name;
    private String password;
    private Integer age;
    private String tel;
}

  1. 创建表结构

  1. 定义数据接口继承BaseMapper
package com.jkj.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jkj.domain.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserDao extends BaseMapper<User> {
   
}

  1. 创建测试类
@SpringBootTest
class Mybatisplus01ApplicationTests {
   

	@Autowired
	private UserDao userDao;
	@Test
	void findAll(){
   
		
		List<User> users = userDao.selectList(null);
		System.out.println(users);
       }
  }

  • 测试

🍁标准数据层开发

🔥MP接口

  • 新增:int insert(T t)
  • 删除:int deleteById(Serializable id)
  • 修改:int updateById(T t)
  • id查询:T selectById(Serializable id)
  • 查询全部:List<T> selectList()
  • 分页查询:IPage<T> selectPage( IPage<T> page)
  • 条件查询:Page<T> selectPage(Wrapper<T> querywrapper)

🔥 id查询

   @Test
    void findById(){
   
        User user = userDao.selectById(3L);
        System.out.println(user);
    }

测试:

🔥修改

@Test
    void updateById(){
   
        User user=new User();
        user.setId(2L);
        user.setName("老二");
        user.setTel("212121");
       userDao.updateById(user);
    }

测试:

🔥删除

   @Test
    void deleteById(){
   
        userDao.deleteById(4L);
    }

测试:

🔥保存

   @Test
    void save(){
   
        User user=new User();
        user.setId(4L);
        user.setName("老四");
        user.setPassword("444");
        user.setAge(67);
        user.setTel("555222");
        userDao.insert(user);
    }

测试:

🔥分页

  1. 设置分页拦截器作为Spring管理的bean
package com.jkj.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 pageInterceptor(){
   
       //定义MP拦截器
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //添加具体的拦截器
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }
}

 
  1. 执行分页查询
  @Test
    void selectPage(){
   
        IPage page = new Page(1, 2);
        userDao.selectPage(page,null);
        System.out.println("当前页码"+page.getCurrent());
        System.out.println("每页数据总量"+page.getSize());
        System.out.println("总页数"+page.getPages());
        System.out.println("数据总量"+page.getTotal());
        System.out.println("当前页数据"+page.getRecords());

    }

测试:

🔥开启日志

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

🍁DQL控制

  • MyBatisPlus将书写复杂的sQL查询条件进行了封装,使用编程的形式完成查询条件的组合。
    • selectOneWrapper):T
    • selectCountWrapper): Integer
    • selectListWrapper): List
    • selectMapsWrapper): List<Map<String, Object> >
    • selectObjsWrapper): List
    • selectPage(IPage,Wrapper): IPage
    • selectMapsPage(IPage,Wrapper): lPage<Map<String, Object>>

🔥条件查询

🔥方式一按条件查询

		QueryWrapper qw = new QueryWrapper();
		qw.lt("age",20);
		List<User> users = userDao.selectList(qw);
		System.out.println(users);

🔥方式二:lambda格式按条件查询

		QueryWrapper<User> qw = new QueryWrapper<User>();
		qw.lambda().lt(User::getAge,20);
		List<User> users = userDao.selectList(qw);
		System.out.println(users);

🔥方式三:lambda格式按条件查询

		LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
		lqw.lt(User::getAge,20);
		List<User> users = userDao.selectList(lqw);
		System.out.println(users);

测试:

🔥并且and

  • 年龄大于20小于35
		LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
		lqw.lt(User::getAge,35).gt(User::getAge,20);
		List<User> users = userDao.selectList(lqw);
		System.out.println(users);

测试:

🔥或者or

  • 小于20大于35
		LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
		lqw.lt(User::getAge,20).or().gt(User::getAge,35);
		List<User> users = userDao.selectList(lqw);
		System.out.println(users);

测试:

🔥条件查询—null值处理

  • if语句控制条件追加
        LambdaQuerywrapper<User> lqw = new LambdaQuerywrapper<User>();
        if(null != userQuery.getAge()(
                  lqwn .ge(User::getAge,userQuery.getAge());
                   }
        if(null != userQuery.getAge2()){
   
                   lqw .lt(User::getAge,userQuery.getAge2());
                   }
        List<User> userList = userDao.selectList(lqw);
        System.out.print1n(userList);

  • 条件参数控制
        LambdaQuerywrapper<User> lqw = new LambdaQuerywrapper<User>();
        lqw.ge(null != userQuery.getAge(),User::getAge,userQuery.getAge());
        lqw.1t(null != userQuery.getAge2( ),User::getAge,userQuery.getAge2());
        List<User> userList = userDao.selectList( 1qw ) ;
        System.out.println(userList);
  • 条件参数控制(链式编程)
        LambdaQuerywrapper<User> lqw = new LambdaQuerywrapper<User>();
        lqw.ge(null != userQuery.getAge(),User::getAge,userQuery.getAge())
        .1t(null != userQuery.getAge2( ),user::getAge,userQuery.getAge2());
        List<User> userList = userDao.selectList( 1qw ) ;
        System.out.println(userList);

🔥查询投影

  • 查询结果包含模型类中部分属性
        //查询投影(方式一)
		LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
		lqw.select(User::getId,User::getName,User::getAge);
		List<User> users = userDao.selectList(lqw);
		System.out.println(users);

		//查询投影(方式二)
		QueryWrapper qw = new QueryWrapper();
		qw.select("id","name","age");
		List<User> users = userDao.selectList(qw);
		System.out.println(users);

测试:

🔥 分组统计

		QueryWrapper qw = new QueryWrapper();
		qw.select("count(*) as count","tel");
		qw.groupBy("tel");
		List<Map<String,Object>> list = userDao.selectMaps(qw);
		System.out.println(list);

测试:

🔥 查询条件

  • 查询条件
    • 范围匹配(> = between )
    • 模糊匹配( like)
    • 空判定(null)
    • 包含性匹配 ( in )
    • 分组( group)
    • 排序( order)
  • 模拟用户登录
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
		lqw.eq(User::getName,"老二").eq(User::getPassword,"222");
		User user = userDao.selectOne(lqw);
		System.out.println(user);

测试:

🔥 范围查询

        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
		lqw.between(User::getAge,10,35);
		List<User> users = userDao.selectList(lqw);
		System.out.println(users);

测试:

🔥 字段映射与表明映射

  • 当实体类属性和字段不一致时
    • @TableField
    • 属性注解
    • 设置当前属性对应的数据库表中的字段关系
    • value (默认〕:设置数据库表字段名称
@TableField(value = "psw")
    private String password;
  • 编码中添加了数据库中未定义的属性
  • exist:设置属性在数据表字段中是否存在,默认是true
@TableField(exist = false)
    private String address;
  • 查询字段的权限
  • select: 设置属性是否参与查询
 @TableField(value = "psw",select = false)
    private String password;
  • 表名与实体类名不一致
  • @TableName
  • 类注解
  • 设置当前类对应数据库表关系
@TableName("xfx_user")
public class User {
   
}
  • 在配置中解决表名与实体类名不一致的问题
mybatis-plus:
  global-config:
    db-config:
      id-type: auto
      table-prefix: xfx

🍁DML控制

🔥id生成策越

  • 名称:@TableId
  • 类型:属性注解
  • 位置:模型类中用于表示主键的属性定义上方
  • 作用:设置当前类中主键属性的生成策略
  • 相关属性
    • value:设置数据库主键名称
    • type:设置主键属性的生成策略,值参照IdType枚举值
    • AUTO(0):使用数据库id自增策略控制id生成
    • NONE(1):不设置id生成策略
    • INPUT(2):用户手工输入id
    • ASSIGN_ID(3):雪花算法生成id(可兼容数值型与字符串型)
    • ASSIGN_UUID(4):以UUID生成算法作为id生成策略
 @TableId(type = IdType.AUTO)
    private Integer id;

测试:

    @Test
	void save(){
   
		User user=new User();
		user.setName("老八");
		user.setAge(88);
		user.setPassword("888");
		user.setTel("6888867");
		userDao.insert(user);
	}

🔥多数据操作(删除)

    @Test
	void all(){
   
		List<Integer> list = new ArrayList<>();
		list.add(7);
		list.add(8);
		list.add(9);
		list.add(10);
		userDao.deleteBatchIds(list);
	}

删除前:

删除后:

🔥多数据操作(查询)

测试:

@Test
	void all(){
   
		List<Integer> list = new ArrayList<>();
		list.add(1);
		list.add(3);
		list.add(5);
		list.add(6);
		userDao.selectBatchIds(list);
	}

🔥逻辑删除

  • 数据表中添加删除标记字段

  • 实体类添加对应的字段,并设定字段为逻辑删除标记字段
    @TableLogic(value = "0",delval = "1")
    private Integer deleted;
  • 或者配置逻辑删除字面值
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      id-type: auto
      table-prefix: xfx
      logic-delete-field: deleted
      logic-not-delete-value: 0
      logic-delete-value: 1
  • 测试
	@Test
	void contextLoads() {
   
		userDao.deleteById(5);
	}
  • 执行sql语句

  • 测试结果

🔥乐观锁

乐观锁是对于数据冲突保持一种乐观态度,操作数据时不会对操作的数据进行加锁,只有到数据提交的时候才通过一种机制来验证数据是否存在冲突。乐观锁是通过在表中增加一个版本(version)或时间戳(timestamp)来实现,版本最为常用。乐观锁每次在执行数据的修改操作时,都会带上一个版本号,一旦版本号和数据的版本号一致就可以执行修改操作并对版本号执行 +1 操作,否则就执行失败。

  • 数据表中添加锁

  • 实体类添加对应的字段,并设定字段为逻辑删除标记字段
   @Version
   private Integer version;
  • 配置乐观锁拦截器机制对应的动态SQL语句拼装
@Configuration
public class MpConfig {
   
   @Bean
   //设置分页拦截器
    public MybatisPlusInterceptor pageInterceptor(){
   
       //定义MP拦截器
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //添加具体的拦截器
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        //乐观锁拦截器
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}
  • 使用乐观锁机制在修改前必须获取到对应数据的version方可正常运行
	@Test
	void contextLoads() {
   
		User user = userDao.selectById(1);
		user.setName("老大");
		userDao.updateById(user);
	}

  • 执行修改前先执行查询语句
SELECT id,name,age,tel,deleted,version FROM xfx_user WHERE id=? 
  • 执行修改时使用version字段作为乐观锁检查依据。
 UPDATE xfx_user SET name=?, age=?, tel=?, version=? WHERE id=? AND version=?

转载:https://blog.csdn.net/qq_43514330/article/details/125897239
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场