Mybatis-plus介绍

Mybatis-plus

MyBatis-Plus 是基于 MyBatis 的扩展,它提供了更多的功能和优化,并且减少了开发人员需要手动编写的 SQL 代码,从而提高了效率和代码质量。MyBatis-Plus 还提供了一些高级功能,例如自动生成代码,分页查询,数据库字段自动映射等。

一.源码

简要介绍MyBatis的源码分析。

SqlSessionFactoryBuilder类:该类用于构建SqlSessionFactory对象,负责解析MyBatis的配置文件、创建DataSource数据源对象和创建Transaction事务管理器对象。

SqlSessionFactory类:该类是MyBatis的核心类,负责创建SqlSession对象,管理MyBatis的所有配置信息和资源,提供了对数据库的操作接口和方法。

SqlSession类:该类是MyBatis的数据访问层接口,封装了对数据库的所有操作和管理,包括查询、插入、更新和删除等,同时支持事务和缓存管理。

Mapper接口:该接口是MyBatis的映射接口,用于定义数据访问的方法和SQL语句,通过注解或XML文件实现与数据库的映射关系。

MapperProxy类:该类是MyBatis的Mapper接口的动态代理类,通过反射机制实现了Mapper接口的具体方法调用,可以在Mapper接口上面实现事务和缓存管理。

Configuration类:该类是MyBatis的配置类,包括了MyBatis的所有配置信息和资源,例如DataSource、Mapper接口、SQL语句等。

Executor类:该类是MyBatis的执行器类,负责执行Mapper接口定义的方法,解析SQL语句、处理参数、执行查询和更新等操作。

StatementHandler类:该类是MyBatis的SQL语句处理类,负责处理SQL语句、参数绑定、结果集映射等操作。

ParameterHandler类:该类是MyBatis的参数处理类,负责处理SQL语句中的参数绑定、转换和处理,支持多种数据类型和对象。

ResultSetHandler类:该类是MyBatis的结果集处理类,负责将数据库的结果集映射成Java对象或集合,支持多种映射方式和数据类型。

二.优势

注意事项:

1.ServiceImpl父类已经注入了UserMapper对象,名称叫做baseMapper,所以当前实现类直接可以使用baseMapper完成操作 2.因为ServiceImpl已经实现了IService下的方法,所以当前服务类没有必要再次实现

思想:共性的业务代码交给框架封装维护,非共性的业务,在接口UserService定义,然后在当前的服务类下实现;

 快速使用

一.自定义一个接口继承IService接口

二.自定义一个类继承ServiceImpl类和实现自定义的接口

/**
 * 自定义一个服务层实现类,实现自定义的服务层接口
 * 因为这个服务层接口继承的公共服务层接口,有许多待实现的方法
 * 所以我们还有继承一个ServiceImpl类,这个类实现了IService接口的所有方法
 * 第一个泛型是要使用的dao层mapper,ServiceImpl会自动注入这个mapper bean,所以自定义的实现类就不用注入mapper了
 * 注入的这个mapper成员变量叫baseMapper
 */


MP封装Service实现CRUD操作



  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响。
  • 损耗小:启动即会自动注入基本CURD,性能基本无损耗,直接面向对象操作。
  • 强大的CRUD操作:内置通用Mapper、通用Service,仅仅通过少量配置即可实现单表大部分CRUD操作,更有强大的条件构造器,满足各类使用需求。
  • 支持Lambda形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写

    错。

  • 支持主键自动生成:支持多达4种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题。

  • 支持ActiveRecord模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作。
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )。

  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用。

  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询。

  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、

    Postgre、SQLServer 等多种数据库。

  • 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询。

  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作。

  • (二)常用的Lombok注解介绍

    @Data

     注在类上,提供类的get、set、equals、hashCode、toString等方法

    @Getter加在类上,可以自动生成参数的getter方法
    @Setter加在类上,可以自动生成参数的setter方法
    @ToString加在类上,调用toString()方法,可以输出实体类中所有属性的值
    @RequiredArgsConstructor生成一个包含常量,和标识了NotNull的变量的构造方法。生成的构造方法是私有的private
    @EqualsAndHashCode

    生成equals和hashCode方法,

    默认使用非静态的属性,

    可以通过exclude参数排除不需要生成的属性。

    通过of参数来指定需要生成的属性

    @NoArgsConstructor

    生成一个无参数的构造方法

    @AllArgsConstructor

    生成一个包含所有变量的构造方法。

    @Value

    这个注解要和Spring的@Value注解区分,Spring的是从配置文件读取内容,这个注解是在类中的所有字段默认全部声明为private final类型,只会生成Getter方法,不会生成Setter方法。

    @Cleanup

    主要用于关闭资源使用。

  • 使用注解@TableId指定id生成策略,让其使用主键自增,而不是使用雪花算法生成一个不重复的Long型id
  • 查询功能

    MP实现分页查询 

    MP的分页拦截器并没有自动装配,所以需要我们在配置类自己维护一个分页拦截器的bean

  • @Test

  • public void test05(){

  • int page=2;

  • int pageSize=4;

  • //构建分页对象

  • IPage<User> pageInfo = new Page<>(page, pageSize);

  • //pageInfo==userIPage-->true,这两个对象是同一个,地址相同

  • //null为无条件查询

  • // IPage<User> userIPage = userMapper.selectPage(pageInfo, null);

  • //TODO:因为这两是同一个对象,所以可以直接不定义一个新对象

  • userMapper.selectPage(pageInfo,null);

  • //获取分页参数

  • long total =pageInfo.getTotal();//获取总记录数

  • long pages =pageInfo.getPages();//获取总页数

  • long size = pageInfo.getSize();//获取当前页大小

  • long current= pageInfo.getCurrent();//获取当前的页数

  • List<User> users =pageInfo.getRecords();//获取当前页的对象集合

  • QueryWrapper模糊查询like 
    模糊查询常用方法
  • like("表列名","条件值"); 作用:查询包含关键字的信息,底层会自动添加匹配关键字,比如:%条件值%
  • likeLeft("表列名","条件值"); 作用:左侧模糊搜索,也就是查询以指定条件值结尾的数据,比如:%条件值
  • likeRight("表列名","条件值");作用:右侧模糊搜索,也就是查询以指定条件值开头的数据,比如:条件值%
  • MP实现Service封装 

    MybatisPlus为了开发更加快捷,对业务层也进行了封装,直接提供了相关的接口和实现类; 我们在进行业务层开发时,可以继承它提供的接口和实现类,使得编码更加高效;

    实现流程

  • 定义一个服务扩展接口,该接口继承公共接口IService;
  • 定义一个服务实现类,该类继承ServiceImpl<Mapper,Entity>,并实现自定义的扩展接口;
  • /**

  • * 自定义一个服务层接口继承公共服务接口,泛型是实体类对象(通过@TableName注解知道要操作的数据表)

  • */

  • public interface UserService extends IService<User> {

  • IPage<User> getUserGtId(IPage<User>page,Long id);

  • }

  • /**

  • * 自定义一个服务层实现类,实现自定义的服务层接口

  • * 因为这个服务层接口继承的公共服务层接口,有许多待实现的方法

  • * 所以我们还有继承一个ServiceImpl类,这个类实现了IService接口的所有方法

  • * 第一个泛型是要使用的dao层mapper,ServiceImpl会自动注入这个mapper bean,所以自定义的实现类就不用注入mapper了

  • * 注入的这个mapper成员变量叫baseMapper

  • */

  • @Service

  • public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

  • /**

  • * 只需要实现UserService接口的方法

  • */

  • @Override

  • public IPage<User> getUserGtId(IPage<User> page, Long id) {

  • //直接使用ServiceImpl注入的mapper bean即可

  • return baseMapper.findUserGtId(page,3L);

  • }

  • }

  • /**

  • * @Description 测试条件查询,且仅返回一个

  • * getOne:sql查询的结果必须为1条或者没有,否则报错 !!!!

  • */

  • @Test

  • public void test2(){

  • LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery(User.class);

  • wrapper.gt(User::getAge,20);

  • User one = userService.getOne(wrapper);

  • System.out.println(one);

  • }

  • /**

  • * @Description 根据条件批量查询

  • */

  • @Test

  • public void test3(){

  • LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery(User.class);

  • wrapper.gt(User::getAge,20);

  • List<User> list = userService.list(wrapper);

  • System.out.println(list);

  • }

  • /**

  • * @Description 根据条件批量查询并分页

  • */

  • @Test

  • public void test4(){

  • LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery(User.class);

  • wrapper.gt(User::getAge,20);

  • //构建分页对象

  • IPage<User> page=new Page<>(2,3);

  • userService.page(page,wrapper);

  • System.out.println(page.getRecords());

  • System.out.println(page.getPages());

  • System.out.println(page.getTotal());

  • }

  • /**

  • * @Description 测试服务层save保存单条操作

  • */

  • @Test

  • public void test5(){

  • User user1 = User.builder().name("wangwu").userName("laowang4").

  • email("444@163.com").age(20).password("333").build();

  • boolean isSuccess = userService.save(user1);

  • System.out.println(isSuccess?"保存成功":"保存失败");

  • }

  • /**

  • * @Description 测试服务层批量保存

  • */

  • @Test

  • public void test6(){

  • User user2 = User.builder().name("wangwu2").userName("laowang2").

  • email("444@163.com").age(20).password("333").build();

  • User user3 = User.builder().name("wangwu3").userName("laowang3").

  • email("444@163.com").age(20).password("333").build();

  • boolean isSuccess = userService.saveBatch(Arrays.asList(user2, user3));

  • System.out.println(isSuccess?"保存成功":"保存失败");

  • }

  • /**

  • * @Description 根据id删除操作

  • */

  • @Test

  • public void test7(){

  • boolean isSuccess = userService.removeById(17l);

  • System.out.println(isSuccess?"保存成功":"保存失败");

  • }

  • /**

  • * @Description 根据条件批量删除

  • */

  • @Test

  • public void test8(){

  • LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery(User.class);

  • wrapper.gt(User::getId,12)

  • .gt(User::getAge,20);

  • boolean remove = userService.remove(wrapper);

  • System.out.println(remove);

  • }

  • /**

  • * @Description 测试根据id更新数据

  • */

  • @Test

  • public void test9(){

  • //UPDATE tb_user SET password=?, t_name=? WHERE id=?

  • User user2 = User.builder().name("wangwu2").password("333").id(3l).build();

  • boolean success = userService.updateById(user2);

  • System.out.println(success);

  • }

  • /**

  • * @Description 测试根据条件批量更新

  • */

  • @Test

  • public void test10(){

  • LambdaUpdateWrapper<User> wrapper = Wrappers.lambdaUpdate(User.class);

  • //UPDATE tb_user SET age=? WHERE (id IN (?,?,?))

  • wrapper.in(User::getId,Arrays.asList(1l,3l,5l)).set(User::getAge,40);

  • boolean update = userService.update(wrapper);

  • System.out.println(userService);

  • }

  • @Test

  • public void test02(){

  • User user1 = User.builder().name("wangwu2").realName("laowang2").

  • email("444@163.com").age(20).password("333").build();

  • userService.saveOrUpdate(user1);//没有设置主键id就是save(新增操作)

  • User user2 = User.builder().id(user1.getId()).name("wangwu3").realName("laowang3").

  • email("444@163.com").age(20).password("333").build();

  • userService.saveOrUpdate(user2);//设置了主键id就是update(修改操作)

一.添加成员变量


  1. /**

  2. * 插入时给这个成员变量赋值

  3. */

  4. @TableField(fill = FieldFill.INSERT)

  5. private Date createTime;

  6. /**

  7. * 插入或者更新时给这个成员变量赋值

  8. */

  9. @TableField(fill = FieldFill.INSERT_UPDATE)

  10. private Date updateTime;

 二.配置拦截器实现MetaObjectHandler


  1. /**

  2. * 一个拦截器,在数据准备插入数据库时进行拦截

  3. */

  4. @Component

  5. public class FillHandler implements MetaObjectHandler {

  6. /**

  7. * 在进行插入数据时进行拦截

  8. * @param metaObject 封装了准备插入数据库的entity对象

  9. */

  10. @Override

  11. public void insertFill(MetaObject metaObject) {

  12. //第一个参数时类的成员变量名

  13. metaObject.setValue("createTime",new Date());

  14. metaObject.setValue("updateTime",new Date());

  15. }

  16. /**

  17. * 在进行更新数据时进行拦截

  18. * @param metaObject 封装了准备更新数据库数据的entity对象

  19. */

  20. @Override

  21. public void updateFill(MetaObject metaObject) {

  22. metaObject.setValue("updateTime",new Date());

  23. }

  24. }

三.测试


  1. @Test

  2. public void test02(){

  3. User user=User.builder()

  4. .realName("hah")

  5. .email("153@qq.com")

  6. .age(18)

  7. .name("a")

  8. .password("123")

  9. .build();

  10. int insert = userMapper.insert(user);

  11. System.out.println(insert);

  12. }

拦截到的数据,此时createTime和updateTime成员变量没有值 

赋值后,再进行插入 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值