mybatisplus快速使用

MP入门

mybatis增求,简化开发

  1. 创建数据库和表,添加数据

    create database mybatis_plus;
    user mybatis_plus;
    
    
    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)
    );
    
    DELETE FROM user;
    INSERT INTO user (id, name, age, email) VALUES
    (1, 'Jone', 18, '[email protected]'),
    (2, 'Jack', 20, '[email protected]'),
    (3, 'Tom', 28, '[email protected]'),
    (4, 'Sandy', 21, '[email protected]'),
    (5, 'Billie', 24, '[email protected]');
    
  2. 创建SpringBoot工程

  3. 引入mybatis-plus相关依赖

    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.0.5</version>
    </dependency>
    
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
    
  4. 配置数据库对应的属性

    # mysql8+ 用com.mysql.cj.jdbc.Driver 和 serverTimezone=GMT%2B8时区
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.url=jdbc:mysql://localhost:3306/mybatisplus?serverTimezone=GMT%2B8
    spring.datasource.username=root
    spring.datasource.password=
    
  5. 编写实体类

    package com.jerry.mpdemo.pojo;
    
    import lombok.Data;
    
    @Data
    public class User {
          
          
        private Long id;
        private String name;
        private Integer age;
        protected String email;
    }
    
  6. 编写Mapper文件

    package com.jerry.mpdemo.mapper;
    
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.jerry.mpdemo.pojo.User;
    
    public interface UserMapper extends BaseMapper<User> {
          
          
    }
    
  7. 扫描mapper

    @SpringBootApplication
    @MapperScan("com.jerry.mpdemo.mapper")
    public class MpdemoApplication {
          
          
    
        public static void main(String[] args) {
          
          
            SpringApplication.run(MpdemoApplication.class, args);
        }
    
    }
    
  8. 测试

    @SpringBootTest
    class MpdemoApplicationTests {
          
          
    
        @Autowired
        private UserMapper userMapper;
    
        @Test
        void contextLoads() {
          
          
            List<User> users = userMapper.selectList(null);
            users.forEach((User user) -> {
          
          
                System.out.println(user);
            });
        }
    
    }
    

主键

MP自动生成19位的ID

自动增长

@Data
public class User {
    
    
    @TableId(type = IdType.AUTO) // 加注解
    private Long id;
    private String name;
    private Integer age;
    protected String email;
}

更新

@Test
public void updateUser() {
    
    
    User user = new User();
    user.setId(2L);
    user.setAge(21);
    int row = userMapper.updateById(user);
    System.out.println(row);
}

自动填充

  1. 表添加两个字段

    • create_time
    • update_time
  2. 实体类添加属性

    private Date createTime;
    private Date updateTime;
    
  3. 添加注解@TableField(fill = FieldFill.INSERT)

  4. 实现接口MetaObjectHandler

    @Component // 放在spring容器中,很重要!!
    public class MyMetaObjectHandler implements MetaObjectHandler {
          
          
        // 使用mp实现更新操作,这个方法执行
        @Override
        public void updateFill(MetaObject metaObject) {
          
          
            this.setFieldValByName("updateTime", new Date(), metaObject);
        }
    
        // 使用mp实现添加操作,这个方法执行
        @Override
        public void insertFill(MetaObject metaObject) {
          
          
            this.setFieldValByName("createTime", new Date(), metaObject);
            this.setFieldValByName("updateTime", new Date(), metaObject);
        }
    }
    
  5. 正常添加更新即可,不用再写这两个字段

乐观锁

主要解决丢失更新,如果不考虑事务隔离性,产生读问题:

  1. 脏读
  2. 不可重复读
  3. 幻读s

写问题:丢失更新问题

比如id = 1 salary = 500,两个人都想修改这个工资

两人都需要开启事务,A500改为了800B500改成200

事务最终需要提交,如果A先提交了事务,表中工资就会变为800

B随后提交事务,工资变为了200,此时A看到了就会发现不对劲,

自己提交的数据被覆盖了。正常应该是B800改成200

解决方法:

  1. 悲观锁:串行,A用的时候别人不能用,隔离级别max

  2. 乐观锁:获取当前version,A提交时比较版本号和数据库中的是否一样,然后将版本号+1,B在看到版本号不一样就无法提交

  3. 添加字段,作为版本号

  4. 实体类添加版本号private Integer version;

  5. 添加@Version注解

    @Version
    private Integer version;
    
  6. 配置乐观锁的插件

    @Configuration
    @MapperScan("com.jerry.mpdemo.mapper")
    public class MpConfig {
          
          
    
        @Bean
        public OptimisticLockerInterceptor optimisticLockerInterceptor() {
          
          
            return new OptimisticLockerInterceptor();
        }
    }
    
  7. 测试

    @Test
    public void addUser() {
          
          
        User user = new User();
        user.setAge(18);
        user.setName("xxx");
        user.setEmail("[email protected]");
    
        int insert = userMapper.insert(user);
        System.out.println("insert: ---------- " + insert);
    }
    
    // 乐观锁必须先查再改
    @Test
    public void testLock() {
          
          
        User user = userMapper.selectById(1355352835969359878L);
        user.setAge(666);
        int row = userMapper.updateById(user);
        System.out.println(row);
    }
    

查询

多个id的批量查询

 @Test
public void testSelect() {
    
    
    List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3)); // 将1,2,3查询出来
    for (User user : users) {
    
    
        System.out.println(user);
    }
}

分页查询:

  1. 配置分页插件

    @Bean
    public PaginationInterceptor paginationInterceptor() {
          
          
        return new PaginationInterceptor();
    }
    
  2. 使用

    @Test
    public void testPage() {
          
          
        Page<User> page = new Page<>(1, 3); // 当前页, 每页记录数
        IPage<User> userIPage = userMapper.selectPage(page, null);
        System.out.println(userIPage.getCurrent());
        System.out.println(userIPage.getSize());
        System.out.println(userIPage.getTotal());
        System.out.println(userIPage.getPages());
        List<User> records = userIPage.getRecords();
        for (User record : records) {
          
          
            System.out.println(record);
        }
    }
    

删除

物理删除

@Test
public void testDelete() {
    
    
    int count = userMapper.deleteById(1L);
    System.out.println("成功删除了" + count + "行");
}

批量删除

@Test
public void testBatchDelete() {
    
    
    userMapper.deleteBatchIds(Arrays.asList(1, 2, 3));
}

逻辑删除,数据真实存在,但是查询不出来

  1. 添加deleted字段

  2. 添加字段并且添加注解@TableLogic

  3. 配置逻辑删除插件

    @Bean
    public ISqlInjector sqlInjector() {
          
          
        return new LogicSqlInjector();
    }
    

性能分析

@Bean
@Profile({
    
    "dev", "test"})
public PerformanceInterceptor performanceInterceptor() {
    
    
    PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
    performanceInterceptor.setMaxTime(200); // 超过100ms的sql不执行
    performanceInterceptor.setFormat(true);
    return performanceInterceptor;
}

条件查询

@Test
public void testSelectQuery() {
    
    
    QueryWrapper queryWrapper = new QueryWrapper();
    // ge大于等于 gt大于 le小于等于 lt小于
    queryWrapper.ge("age", 20);
    List<User> list = userMapper.selectList(queryWrapper);
    list.forEach((user) -> System.out.println(user));

    // eq等于 ne不等于

    // between在范围内 like模糊查询会->自动帮忙传递%

    // orderBy排序

    // last拼接到sql的最后,有sql注入风险

    // 查询指定列
    queryWrapper.select("id", "name", "age");


}

猜你喜欢

转载自blog.csdn.net/weixin_43795939/article/details/113430956