MyBatisPlus整理笔记

Mybatis-plus:对Mybatis做增强,简化开发

一、快速入门

1、创建user表:

DROP TABLE IF EXISTS user;

CREATE TABLE user
(
	id BIGINT(20) NOT NULL COMMENT '主键ID',
	name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
	age INT(11) NULL DEFAULT NULL COMMENT '年龄',
	email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
	PRIMARY KEY (id)
);

2、加入对应数据:

DELETE FROM user;

INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');

3、创建Springboot工程

4、引入相关依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <!--lombok-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <!--引入mybatis-plus依赖-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.4.1</version>
    </dependency>
    <!--mysql-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
</dependencies>

5、配置application.yml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=UTC
    username: root
    password: 12341234
    
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  //配置日志

6、代码部分

  • 创建实体类

    @Data
    public class User {
        private Long id;
        private String name;
        private Integer age;
        private String email;
    }
    
  • 创建Mapper接口,继承BaseMapper<泛型>。

    在主启动类中加入@MapperScan(“全限定名”),扫描Mapper接口

7、测试

@SpringBootTest
class MpdemoApplicationTests {

    @Autowired
    private UserMapper userMapper;

    @Test
    void contextLoads() {
        List<User> users = userMapper.selectList(null);
        for (User user : users) {
            System.out.println(user);
        }
    }
}

//测试结果:
    User(id=1, name=Jone, age=18, email=test1@baomidou.com)
    User(id=2, name=Jack, age=20, email=test2@baomidou.com)
    User(id=3, name=Tom, age=28, email=test3@baomidou.com)
    User(id=4, name=Sandy, age=21, email=test4@baomidou.com)
    User(id=5, name=Billie, age=24, email=test5@baomidou.com)

Idea在第一次启动的时候会将代码编译,启动较慢!

二、mp实现添加操作

代码操作:

@Test
public void addUser(){
    User user = new User();
    user.setName("Lucy");  //未设置主键值
    user.setAge(18);
    user.setEmail("12356@qq.com");
    int insert = userMapper.insert(user);
}

通过日志查看执行结果

==>  Preparing: INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? )
==> Parameters: 1329331831785492482(Long), Lucy(String), 18(Integer), 12356@qq.com(String)
<==    Updates: 1
  • 未设置主键值mp自动生成19位IP值

添加操作实现主键策略

ID生成策略具体参考这篇文章:https://www.cnblogs.com/haoxinyue/p/5208136.html

  • 自动增长:AUTO_INCREMENT

  • UUID:每次生成随机唯一的值

  • Redis实现

  • mp自带策略 :snowflake算法

在实体类主键ID上添加注解如下

@Data
public class User {

    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

//AUTO:自动增长
//INPUT:设置id值
//NONE:输入
//ASSGIN_UUID:随机生成值

三、mp实现修改操作

代码操作:

@Test
public void updateUser(){
    User user = new User();
    user.setId(2L);
    user.setAge(40);
    userMapper.updateById(user);
}

通过日志查看执行结果:

==>  Preparing: UPDATE user SET age=? WHERE id=?
==> Parameters: 40(Integer), 2(Long)
<==    Updates: 1

自动填充:

不需要set到对象里面的值,使用mp方式实现数据添加

准备工作:

1、表中添加两个字段

create_time、update_time

2、添加实体类属性

具体实现过程:

  1. 在需要自动填充的属性上添加注解
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
  1. 创建类,实现接口MetaObjectHandler,并实现方法

    //注册到容器中
    @Component
    public class MyMetaObjectHandler implements MetaObjectHandler {
        //使用mp实现添加方法,该方法执行
        @Override
        public void insertFill(MetaObject metaObject) {
            this.setFieldValByName("createTime",new Date(),metaObject);
            this.setFieldValByName("updateTime",new Date(),metaObject);
        }
    
        //使用mp实现修改方法,该方法执行
        @Override
        public void updateFill(MetaObject metaObject) {
            this.setFieldValByName("updateTime",new Date(),metaObject);
        }
    }
    

乐观锁:

  • 乐观锁主要解决丢失更新问题!

丢失更新:多个人修改同一条数据的时候,最后一个提交事务的提交数据会覆盖前面的数据。

  • 解决丢失更新主要可以用悲观锁(串行,只能单人使用)

乐观锁实现方式

  • 取出纪录时,获取当前Version
  • 更新时,带上这个version
  • 执行更新时,set version = new Version where version = Oldversion
  • 如果version不匹配,则更新失败

案例操作

  1. 在数据库中加入version字段

  2. 实体类添加version字段,并添加@version注解

    @Version
    private Integer version;
    
  3. 配置乐观锁插件到spring容器

    //乐观锁插件
    @Bean
    public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor(){
        return new OptimisticLockerInnerInterceptor();
    }
    
  4. 用自动填充添加version初始值

    this.setFieldValByName("version",1,metaObject);
    

测试结果:

//测试乐观锁,一定要先查再改
@Test
    public void testOptimisticLocker(){
        User user = userMapper.selectById(1329347964622127105L);
        user.setAge(235);
        userMapper.updateById(user);
    }

version结果+1

四、更多查询

  • 多个ID查询:List selectBatchIds(@Param(“coll”) Collection<? extends Serializable> idList);
@Test
public void testSelectDemo1(){
    List<User> users = userMapper.selectBatchIds(Arrays.asList(1L, 2L, 3L));//传入集合
    for (User user : users) {
        System.out.println(user);
    }
}
  • 简单条件查询:
@Test
public void testSelectDemo2(){

    HashMap<String,Object> map = new HashMap<>();
    map.put("name","Jone");//传入键值对作为条件
    map.put("age","18");
    List<User> users = userMapper.selectByMap(map);
    for (User user : users) {
        System.out.println(user);
    }
}

五、分页(重点)

  • 配置分页插件
//分页插件
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor page = new PaginationInterceptor();
        page.setDialectType("mysql");
        return page;
    }
  • 编写分写代码
    • 直接new page对象,传入两个参数:当前页、每页记录数
    • 调用mp方法实现分页查询
@Test
public void testPage(){
    //传入两个参数:当前页和每页显示记录数
    Page<User> page = new Page<>(1, 3);
    //调用mp分页查询方法
    //调用mp分页查询过程中,底层封装
    //把分页所有数据封装到page中
    userMapper.selectPage(page,null);
    System.out.println(page.getCurrent()); //获取当前页
    System.out.println(page.getRecords()); //每页数据List集合
    System.out.println(page.getSize()); //每页显示记录数
    System.out.println(page.getTotal()); //总记录数
    System.out.println(page.getPages()); //总页数

    System.out.println(page.hasNext()); //是否有下一页
    System.out.println(page.hasPrevious()); //是否有上一页
}


日志打印:
    ==>  Preparing: SELECT COUNT(1) FROM user
    ==> Parameters: 
    <==    Columns: COUNT(1)
    <==        Row: 7
    ==>  Preparing: SELECT id,name,age,email,create_time,update_time,version FROM user LIMIT ?,?   //这里有limit查询
    ==> Parameters: 3(Long), 3(Long)
    <==    Columns: id, name, age, email, create_time, update_time, version
    <==        Row: 4, Sandy, 21, test4@baomidou.com, null, null, null
    <==        Row: 5, Billie, 24, test5@baomidou.com, null, null, null
    <==        Row: 7, Lisa, 235, 412345@qq.com, 2020-11-19 08:37:43, 2020-11-19 09:05:35, 1
    <==      Total: 3
    Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@314a31b0]
        
        
        
        
    2
    [User{id=4, name='Sandy', age=21, email='test4@baomidou.com', createTime=null, updateTime=null, version=null}, User{id=5, name='Billie', age=24, email='test5@baomidou.com', createTime=null, updateTime=null, version=null}, User{id=7, name='Lisa', age=235, email='412345@qq.com', createTime=Thu Nov 19 16:37:43 CST 2020, updateTime=Thu Nov 19 17:05:35 CST 2020, version=1}]
    3
    7
    3
    true
    true

六、逻辑删除

  • 物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除的数据

    //删除操作,物理删除
    @Test
    public void testDeleteById(){
        //单个删除
        userMapper.deleteById(1);
        
        //批量删除
        userMapper.deleteBatchIds(Arrays.asList(1,2,3));
    }
    
  • 逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态“,之后数据库能看到此条数据。

    • 数据库表中添加逻辑删除字段,对应实体类添加逻辑删除属性

      @TableLogic
      private Integer deleted;
      
    • 配置逻辑删除插件

      //逻辑删除插件,3.1.1新版本不用配置插件
      @Bean
      public ISqlInjector sqlInjector(){
          return new LogicSqlInjector();
      }
      
    • 添加配置信息

      logic-delete-value: 1
      logic-not-delete-value: 0 #配置不删除是0,删除是1
      
    • 执行删除方法!

      @Test
      public void testDeleteById(){
          userMapper.deleteById(1329410275504369665L);
      }
      
      日志输出:
          ==>  Preparing: UPDATE user SET deleted=1 WHERE id=? AND deleted=0
          ==> Parameters: 1329410275504369665(Long)
          <==    Updates: 1
      
    • 执行查询方法语句中多一个WHERE deleted=0!!!逻辑删除!!

七、实现复杂条件查询操作

——使用QuerryWapper构建条件查询

代码详解(注释详细)

//创建QueryWrapper对象
QueryWrapper<User> wrapper = new QueryWrapper<>();
//通过QueryWrapper设置条件



//ge(大于等于)、gt(大于)、le(小于等于)、lt(小于)
//查询大于等于30的人
wrapper.ge("age",100);//参数段名称,值
List<User> users = userMapper.selectList(wrapper);//传入wrapper
System.out.println(users);


//eq(等于)、ne(不等于)
//查询名称是Tom的人
QueryWrapper<User> eq = wrapper.eq("name", "Tom");
List<User> users = userMapper.selectList(wrapper);
System.out.println(users);

//between(查范围中的值)
//查询年龄20-100中的人
QueryWrapper<User> age = wrapper.between("age", 20, 100);
List<User> users = userMapper.selectList(wrapper);
System.out.println(users);

//like(模糊查询)
wrapper.like("name", "a" );
List<User> users = userMapper.selectList(wrapper);
System.out.println(users);

//orderByDesc(通过条件排序查询)
wrapper.orderByDesc("id");
List<User> users = userMapper.selectList(wrapper);
System.out.println(users);

//last(拼接sql语句)
wrapper.last("limit 1");
List<User> users = userMapper.selectList(wrapper);
System.out.println(users);

//select(查询指定的列)
wrapper.select("name","age");
List<User> users = userMapper.selectList(wrapper);
System.out.println(users);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值