mybatisplus学习笔记

mybatisplus笔记

一、基本crud

1、BaseMapper

所有基本的crud都在BaseMapper接口中定义,用户只需要继承该接口即可实现基本的crud操作

@Repository
//需要指定泛型为哪一个实体类
public interface UserMapper extends BaseMapper<User> {
}

insert操作

@Test
public void testUserMapper(){
    
    QueryWrapper<User> userWrapper = new QueryWrapper<>();
    userWrapper.between("id",1,3);
    List<User> users = userMapper.selectList(userWrapper);
    users.forEach(System.out::println);
}

delete操作

mybatisplus学习笔记_第1张图片

public void testUserDeleteById(){
    userMapper.deleteById(5);//根据id删除
}
public void testUserDeleteByMap(){
    Map<String, Object> map = new HashMap<>();
    map.put("name","lisi");
    map.put("age",14);
    //DELETE FROM user WHERE name = ? AND age = ?
    //根据map中的条件匹配删除
    userMapper.deleteByMap(map);
}
public void testDeleteBatchIds(){
    List<Integer> list = new ArrayList<>();
    list.add(14);
    list.add(34);
    //根据id批量删除
    userMapper.deleteBatchIds(list);
}

update操作

mybatisplus学习笔记_第2张图片

public void updateById(){
    //根据id修改
    userMapper.updateById(new User(1,"zhangsan",14,"[email protected]"));
}

select操作

mybatisplus学习笔记_第3张图片

public void selectById(){
    //根据id查询
        User user = userMapper.selectById(1);
        System.out.println(user);
    }
public void selectBatchIds(){
    ArrayList<Integer> list = new ArrayList<>();
    list.add(1);
    list.add(2);
    //根据id批量查询
    List<User> users = userMapper.selectBatchIds(list);
    users.forEach(System.out::println);
}
public void selectByMap(){
    Map<String,Object> map = new HashMap<>();
    map.put("name","lisi");
    List<User> users = userMapper.selectByMap(map);
    users.forEach(System.out::println);
}

2、通用的Service

1、Mybatis-plus中有IService接口及其实现类ServiceImpl,里面封装了简单的业务逻辑

2、继承IService接口

/**
 * * UserService继承IService模板提供的基础功能
 */
public interface UserService extends IService<User> {
}

3、实现接口

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}

如果接口中的方法不够用则需要自己定义

二、常用注解

1、 @TableName

我们在实现crud的时候,我们只是在BaseMapper中指定了泛型类User,没有指定在数据库中的表,便可以查询User表中的数据,因为Mybatis-plus默认是表名和实体类一致,如果不一致的话,则会报异常,所以需要@TableName指定实体类对应的表明

mybatisplus学习笔记_第4张图片

或者通过全局配置前缀

mybatis-plus:
	configuration:
		# 配置MyBatis日志
		log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
	global-config:
		db-config:
		# 配置MyBatis-Plus操作表的默认前缀
		table-prefix: t_
		# 配置MyBatis-Plus的主键策略
		id-type: auto

2、@TableId

MyBatis-Plus在实现CRUD时,会默认将id作为主键列,并在插入数据时,默认 基于雪花算法的策略生成id

如果实体类中的主键不是id,而是其他名称,如uid,Mybatis-plus识别不了,则会出现异常

这时候需要在uid上加上@TableId,表示将字段设置为主键

@TableId(value = "id",type= IdType.AUTO)
private Integer id;
value属性

设置表中主键的名称

type属性

指定主键的策略

mybatisplus学习笔记_第5张图片

mybatis-plus:
	configuration:
	# 配置MyBatis日志
		log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
	global-config:
		db-config:
		# 配置MyBatis-Plus的主键策略
		id-type: auto

3、@TableField

Mybatis-plus在执行的时候,需要保证实体类的属性名和数据库表中的字段名一致

可以使用@TableField标识实体类中的属性名并指定对应的字段名

    @TableField("name")
    private String name;

如果没有使用注解标注的话,Mybatis-plus默认属性名为对应的字段名

4、@TableLogic

  • 物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除的数据
  • 逻辑删除:假删除,将对应数据中代表是否被删除字段的状态修改为“被删除状态”,之后在数据库 中仍旧能看到此条数据记录
  • 可以用于数据恢复

实现逻辑删除

  • 创建逻辑删除状态列,默认为0

mybatisplus学习笔记_第6张图片

  • 实体类中添加逻辑删除属性

mybatisplus学习笔记_第7张图片

  • 测试

在这里插入图片描述

在这里插入图片描述

三、条件构造器及其常见接口

1、wrapper介绍

用于封装各种条件

mybatisplus学习笔记_第8张图片

  • Wrapper : 条件构造抽象类,最顶端父类
    • AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
      • QueryWrapper : 查询条件封装
      • UpdateWrapper : Update 条件封装
      • AbstractLambdaWrapper : 使用Lambda 语法
        • LambdaQueryWrapper :用于Lambda语法使用的查询
        • Wrapper LambdaUpdateWrapper : Lambda 更新封装Wrapper

组装条件

    @Test
    public void test(){
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        //lambda表达式先执行
        userQueryWrapper
                .like("name","J")
                .and(i->{
                    i.eq("id","5")
                            .or()
                            .eq("id","6");
                });
        //SELECT id,name,age,email,is_deleted FROM user WHERE is_deleted=0 AND (name LIKE ? AND (id = ? OR id = ?))
        List<User> users = userMapper.selectList(userQueryWrapper);
        users.forEach(System.out::println);
    }

组装select子句

    @Test
    public void test02(){
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        //查询用户的name和age字段
        //SELECT name,age FROM user WHERE is_deleted=0
        userQueryWrapper.select("name","age");
        //select搭配selectMaps使用避免User对象中出现属性值为空的现象
        List<Map<String, Object>> list = userMapper.selectMaps(userQueryWrapper);
        list.forEach(System.out::println);

    }

嵌套查询/子查询

    @Test
    public void test03(){
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        //嵌套查询/子查询
        //SELECT id,name,age,email,is_deleted FROM user WHERE is_deleted=0 AND (id IN (select id from user where `name` like '%J%'))
        userQueryWrapper.inSql("id","select id from user where `name` like '%J%'");
        List<User> users = userMapper.selectList(userQueryWrapper);
        users.forEach(System.out::println);
    }

修改功能

实现修改功能有以下两种

1、使用实体类加上QueryWrapper
@Test
    public void test04(){
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("name","jack");
        User user = new User();
        user.setAge(10);
        // UPDATE user SET age=? WHERE is_deleted=0 AND (name = ?)
        // 10(Integer), jack(String)
        int update = userMapper.update(user, userQueryWrapper);
        System.out.println(update);
    }
2、使用UpdateWrapper
    @Test
    public void test05(){
        UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();

        userUpdateWrapper.eq("name","jack");
        userUpdateWrapper.set("age",15);
        // UPDATE user SET age=? WHERE is_deleted=0 AND (name = ?)
        // 15(Integer), jack(String)
        int update = userMapper.update(null,userUpdateWrapper);
        System.out.println(update);
    }

使用condition组装条件

    @Test
    public void test06(){
        String name = "j";
        Integer ageBegin = 20;
        Integer ageEnd = 50;
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.like(StringUtils.isNotBlank(name),"name",name)
                .gt(ageBegin != null,"age",ageBegin)
                .lt(ageEnd != null,"age",ageEnd);

        //SELECT id,name,age,email,is_deleted FROM user WHERE is_deleted=0 AND (name LIKE ? AND age > ? AND age < ?)
        //%j%(String), 30(Integer), 50(Integer)
        List<User> users = userMapper.selectList(userQueryWrapper);
        users.forEach(System.out::println);
    }

LambdaQueryWrapper

防止写错数据库中的字段名,所以封装了支持Lambda表达式的条件查询类

    @Test
    public void test07(){
        Integer ageBegin = 10;
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //使用Lambda表达式构造查询条件
        userLambdaQueryWrapper.gt(ageBegin != null,User::getAge,ageBegin);
        List<User> users = userMapper.selectList(userLambdaQueryWrapper);
        users.forEach(System.out::println);
    }

LambdaUpdateWrapper

使用方法与LambdaQueryWrapper相似

四、插件

1、分页插件

添加MybatisPlus配置类

在配置类中添加拦截器组件MybatisPlusInterceptor,并在这个拦截器中添加一个内部拦截器PaginationInnerInterceptor,指定数据库类型为MySql

@Configuration
@MapperScan("com.lin.mapper")
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return mybatisPlusInterceptor;
    }
}

测试

    @Test
    public void testPage(){
        //指定当前页码和每页数据量
        Page<User> userPage = new Page<>(2,3);
        userMapper.selectPage(userPage,null);
        //页中的数据
        System.out.println("getRecords:"+userPage.getRecords());
        //获取页码总数
        System.out.println("getPages:"+userPage.getPages());
        //获取当前页码数
        System.out.println("getCurrent:"+userPage.getCurrent());
        //获取总数据量
        System.out.println("getTotal:"+userPage.getTotal());
        //获取每页的数据量
        System.out.println("getSize:"+userPage.getSize());
        //是否存在上一页
        System.out.println(userPage.hasPrevious());
        //是否存在下一页
        System.out.println(userPage.hasNext());
        ...
    }

自定义sql语句并使用分页插件

1、在接口中自定义方法

方法的第一个参数和返回值必须为Page类

@Mapper
public interface UserMapper extends BaseMapper<User> {
    Page<User> queryAgePage(@Param("page") Page<User> page, @Param("age") Integer age);
}
2、在mapper映射文件中编写sql语句

    <select id="queryAgePage" resultType="user">
        select `id`,`name`,`age`,email from user where age>#{age}
    select>
3、测试
    @Test
    public void testQueryAgePage(){
        Page<User> userPage = new Page<>(2,3);
        userMapper.queryAgePage(userPage,10);
        System.out.println(userPage.getRecords());
    }

2、乐观锁插件

在MybatisPlus拦截器中添加内部拦截器OptimisticLockerInnerInterceptor

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        //添加分页插件
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        //添加乐观锁插件
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mybatisPlusInterceptor;
    }

在实体类的版本号属性上标注@Version

@Data
@TableName("t_product")
public class Product {
    @TableId
    private Long id;
    private String name;
    private Integer price;
    //每当执行一次修改操作时,版本号version自加一
    @Version
    private Integer version;
}

每当执行修改操作的时候,都会检查一下版本号是否一致,如果不一致则执行不成功

测试

//测试数据冲突
    @Test
    public void test(){
        Product productLi = productMapper.selectById(1);
        Integer priceLi = productLi.getPrice();
        System.out.println("小李查出的数据:"+priceLi);

        Product productWang = productMapper.selectById(1);
        Integer priceWang = productWang.getPrice();
        System.out.println("小王查出的数据:"+priceWang);
        //小李修改数据
        productLi.setPrice(priceLi+50);
        productMapper.updateById(productLi);
        //小王修改数据
        productWang.setPrice(priceWang-30);
        int i = productMapper.updateById(productWang);
        while (i == 0){
            System.out.println("修改失败,重新修改");
            Product productNew = productMapper.selectById(1);
            productNew.setPrice(productNew.getPrice() - 30);
            i = productMapper.updateById(productNew);
        }
        System.out.println("老板查看的价格:"+ productMapper.selectById(1).getPrice());
    }

五、通用枚举

1、创建枚举类型SexEnum

@Getter
public enum SexEnum {

    MALE(1,"男"),FEMALE(2,"女");
	//表示将此属性的值设置到数据库表中
    @EnumValue
    private Integer sex;

    private String sexName;
    SexEnum(Integer sex, String sexName) {
        this.sex = sex;
        this.sexName = sexName;
    }
}

2、在实体类和数据库User表中添加sex属性

@Data
@AllArgsConstructor
@NoArgsConstructor
//指定在数据库中所映射的表名
@TableName("user")
public class User {
    @TableId(value = "id",type= IdType.AUTO)
    private Long id;
    @TableField("name")
    private String name;
    //sex属性
    private SexEnum sex;
    private Integer age;
    private String email;
    //逻辑删除
    @TableLogic
    private Integer isDeleted;
}

3、配置扫描通用枚举

mybatis-plus:
  configuration:
    # 配置MyBatis日志
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      #通过全局配置idtType为auto
      id-type: auto
  #设置别名
  type-aliases-package: com.lin.bean
  #配置扫描通用枚举
  type-enums-package: com.lin.enums

4、测试

    @Test
    public void test(){
        User user = new User();
        user.setName("zhaoliu");
        user.setAge(18);
        user.setSex(SexEnum.MALE);
        user.setEmail("[email protected]");
        int insert = userMapper.insert(user);
        System.out.println(insert);
    }

六、代码生成器

1、引入依赖

		<dependency>
            <groupId>com.baomidougroupId>
            <artifactId>mybatis-plus-generatorartifactId>
            <version>3.5.1version>
        dependency>
        <dependency>
            <groupId>org.freemarkergroupId>
            <artifactId>freemarkerartifactId>
            <version>2.3.31version>
        dependency>

2、从官网中复制模板,快速生成

执行此方法

    public static void main(String[] args) {
        FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3306/mybatis_plus?characterEncoding = utf-8 & userSSL = false", "root", "0911")
                .globalConfig(builder -> {
                    builder.author("lin") // 设置作者
                            // .enableSwagger() // 开启 swagger 模式
                            .fileOverride() // 覆盖已生成文件
                            .outputDir("D://mybatis_plus"); // 指定输出目录
                })
                .packageConfig(builder -> {
                    builder.parent("com.lin") // 设置父包名
                            .moduleName("mybatisplus") // 设置父包模块名
                            .pathInfo(Collections.singletonMap(OutputFile.mapperXml, "D://mybatis_plus"));// 设置mapperXml生成路径
                })
                .strategyConfig(builder -> {
                    builder.addInclude("user") // 设置需要生成的表名
                            .addTablePrefix("t_", "c_"); // 设置过滤表前缀
                })
                .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker 引擎模板,默认的是Velocity引擎模板
                .execute();
    }

3、生成结果文件

在这里插入图片描述

七、多数据源

1、引入依赖

<dependency>
	<groupId>com.baomidougroupId>
	<artifactId>dynamic-datasource-spring-boot-starterartifactId>
	<version>3.5.0version>
dependency>

2、配置

spring:
  datasource:
    dynamic:
      # 严格匹配数据源,默认为false。true表示未匹配到指定数据源时抛异常,false表示如果未匹配则使用默认数据源
      strict: false
      # 设置默认的数据源或者数据源组,默认值即为master
      primary: master
      datasource:
        master:
          url: jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false
          driver-class-name: com.mysql.cj.jdbc.Driver
          username: root
          password: 0911
        slave_1:
          url: jdbc:mysql://localhost:3306/mybatis_plus_1?characterEncoding=utf-8&useSSL=false
          driver-class-name: com.mysql.cj.jdbc.Driver
          username: root
          password: 0911

3、创建Service

在Service实现类上标注@DS,,指定数据源

@Service
@DS("master")//指定数据源为master
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService{
}
@Service
@DS("slave_1")
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService{
}

八、MyBatisX插件

自动生成代码

自动生成bean,mapper,service

mybatisplus学习笔记_第9张图片

mybatisplus学习笔记_第10张图片

mybatisplus学习笔记_第11张图片mybatisplus学习笔记_第12张图片

       driver-class-name: com.mysql.cj.jdbc.Driver
          username: root
          password: 0911

自动生成mapper中方法的sql语句

mybatisplus学习笔记_第13张图片

mybatisplus学习笔记_第14张图片

自动在mapperxml文件中生成的insert语句

	<insert id="insertSelective">
        insert into user
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="id != null">id,if>
            <if test="name != null">name,if>
            <if test="sex != null">sex,if>
            <if test="age != null">age,if>
            <if test="email != null">email,if>
            <if test="isDeleted != null">is_deleted,if>
        trim>
        values
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="id != null">#{id,jdbcType=BIGINT},if>
            <if test="name != null">#{name,jdbcType=VARCHAR},if>
            <if test="sex != null">#{sex,jdbcType=INTEGER},if>
            <if test="age != null">#{age,jdbcType=INTEGER},if>
            <if test="email != null">#{email,jdbcType=VARCHAR},if>
            <if test="isDeleted != null">#{isDeleted,jdbcType=INTEGER},if>
        trim>
    insert>

你可能感兴趣的:(学习,笔记,java,mybatis)