学习日志day71(2021-11-12)(1、Mybatis-Plus的注解 2、条件构造器 3、分页查询 4、动态sql 5、代码自动生成 )

学习内容:学习Mybatis-Plus(Day71)

1、Mybatis-Plus的注解
2、条件构造器
3、分页查询
4、动态sql
5、代码自动生成


1、Mybatis-Plus的注解

(1)@TableId,设置主键映射,value 映射主键字段名,type 设置主键类型,主键的生成策略。

public class User {
    @TableId(value = "id",type = IdType.AUTO) //设置id自增(默认)
    private Long id;
    private String name;
    private Integer age;
}

NONE,无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)。
INPUT 如果开发者没有手动赋值,则数据库通过自增的方式给主键赋值,如果开发者手动赋值,则存入该值。
ASSIGN_ID MP 自动赋值,雪花算法。
ASSIGN_UUID 主键的数据类型必须是 String,自动生成 UUID 进行赋值。

(2)@TableField,映射非主键字段
1.value 映射字段名
2.exist 表示是否为数据库表字段,默认true,如果实体类中的成员变量在数据库中没有对应的字段,则可以使用 exist=false,VO、DTO
3.select 表示是否查询该字段,默认true
4.fill 表示是否自动填充,默认FieldFill.DEFAULT将对象存入数据库的时候,由 MyBatis Plus 自动给某些字段赋值,如create_time、update_time

编写实体类,数据库添加createTime和updateTime字段

@Data
@ToString
@TableName(value = "user") //设置表名,如果表名和实体类名相同可省略
public class User {
    @TableId(value = "id", type = IdType.AUTO) //设置id自增
    private Long id;
    private String name;
    private Integer age;
    @TableField(value = "email",select = false) //映射字段名为email,不查询该字段
    private String email;
    @TableField(exist = false) //表中不存在此字段
    private String gender;

    @TableField(fill = FieldFill.INSERT)//插入字段的值时自动填充
    private Date createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)//插入或修改时自动填充
    private Date updateTime;
}

创建自动填充处理器

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}

在添加和修改数据后会自动填充添加时间和修改时间。

(3)@Version,OptimisticLockerInnerInterceptor乐观锁
当要更新一条记录的时候,希望这条记录没有被别人更新。
乐观锁实现方式:取出记录时,获取当前version。更新时,带上这个version。执行更新时, set version = newVersion where version = oldVersion。如果version不对,就更新失败。

数据库表添加 version 字段,默认值为 1,实体类添加 version 成员变量,并且添加 @Version

@Data
@ToString
@TableName(value = "user") //设置表名,如果表名和实体类名相同可省略
public class User {
    ...
    @Version
    private Integer version;
}

注册配置类

@Configuration
public class MyBatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }

}

测试,先查再改才能对比version值

@Test
    public void testVersion() {
        User user = userMapper.selectById(5);
        user.setName("黄蓉");
        int result = userMapper.updateById(user);
        System.out.println(user);
    }

查看sql语句:

UPDATE user SET name=?, age=?, update_time=?, version=? WHERE id=? AND version=?

修改后数据库version字段加1

(4)@EnumValue,通用枚举类注解,将数据库字段映射成实体类的枚举类型成员变量。

声明通用枚举属性
方式一: 使用 @EnumValue 注解枚举属性 完整示例

public enum GradeEnum {

    PRIMARY(1, "小学"),  SECONDORY(2, "中学"),  HIGH(3, "高中");

    GradeEnum(int code, String descp) {
        this.code = code;
        this.descp = descp;
    }

    //方式一: 使用 @EnumValue 注解枚举属性 完整示例
    @EnumValue//标记数据库存的值是code
    private final int code;
    private final String descp;
}
//方式二: 枚举属性,实现 IEnum 接口
public enum AgeEnum implements IEnum<Integer> {
    ONE(1, "一岁"),
    TWO(2, "二岁"),
    THREE(3, "三岁");

    private int value;
    private String desc;

    AgeEnum(int i, String desc) {
        this.value = i;
        this.desc = desc;
    }

    @Override
    public Integer getValue() {
        return this.value;
    }
}

实体属性使用枚举类型

@Data
@ToString
@TableName(value = "user") //设置表名,如果表名和实体类名相同可省略
public class User {
	...

    /**
     * 年龄,IEnum接口的枚举处理
     * 数据库字段:age INT(3)
     */
    private AgeEnum age1;

    /**
     * 年级,原生枚举(带{@link com.baomidou.mybatisplus.annotation.EnumValue}):
     * 数据库字段:grade INT(2)
     */
    private GradeEnum grade;
}

配置扫描通用枚举

mybatis-plus:
  type-enums-package: com.hisoft.enums  #扫描枚举包

测试

@Test
public void testEnum() {
    User user = new User();
    user.setName("杨过");
    user.setAge(16);
    user.setEmail("333@qq.com");
    user.setGrade(GradeEnum.HIGH);
    user.setAge1(AgeEnum.THREE);   
    int result = userMapper.insert(user); //成功返回1
    System.out.println(user);
    System.out.println("result = " + result);
}

(5)@TableLogic,映射逻辑删除
只对自动注入的sql起效:
插入: 不作限制
查找: 追加where条件过滤掉已删除数据,且使用 wrapper.entity 生成的where条件会忽略该字段
更新: 追加where条件防止更新到已删除数据,且使用 wrapper.entity 生成的where条件会忽略该字段
删除: 转变为更新

配置com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: flag  # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

实体类字段上加上@TableLogic注解

@TableLogic
private Integer deleted;

测试

@Test
public void testLogicDelete() {
    int result = userMapper.deleteById(1458703975678332931L);
    Assertions.assertEquals(result,1);//检查结果是否为1,不为1则报错
}

查看sql语句
删除:

update user set deleted=1 where id = 1458703975678332931L and deleted=0 

查找:

select id,name,deleted from user where deleted=0

2、条件构造器

(1)AbstractWrapper
QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件。
注意: entity 生成的 where 条件与 使用各个 api 生成的 where 条件没有任何关联行为。

(2)allEq,全部eq(或个别isNull)
params : key为数据库字段名,value为字段值
null2IsNull : 为true则在map的value为null时调用 isNull 方法,为false时则忽略value为null的。

@Test
public void testWrapper() {
    QueryWrapper wrapper = new QueryWrapper<>();
    Map<String,Object> map = new HashMap<>();
    map.put("id",1458703975678332932L);
    map.put("name","郭靖");
    wrapper.allEq(map,false);//为false时则忽略value为null的
    userMapper.selectList(wrapper);
}

查看sql

SELECT id,name,age FROM user WHERE name = "郭靖" AND id = 1458703975678332932

(3)eq,等于 = ;ne,不等于 <> ;gt,大于 > ;ge,大于等于 >= ; lt,小于 < ;le,小于等于 <= ;between,BETWEEN 值1 AND 值2 ;like,LIKE ‘%值%’ ;
or,拼接 OR

@Test
public void testWrapper() {
    QueryWrapper wrapper = new QueryWrapper<>();

    wrapper.eq("name","郭靖");
    wrapper.or();
    wrapper.ge("age",21);
    userMapper.selectList(wrapper).forEach(System.out::println);

    /*wrapper.like("name","a");
    wrapper.or();
    wrapper.likeRight("name",'杨');
    userMapper.selectList(wrapper).forEach(System.out::println);*/

查看sql

SELECT id,name,age FROM user WHERE name = "郭靖" OR age >= 21
SELECT id,name,age FROM user WHERE name LIKE "a" OR name LIKE '杨'

(4)in

wrapper.in("id", 1,2,3,4);//条件之间会自动加上and
wrapper.in("id", Arrays.asList(1,2,3,4));
wrapper.inSql("id","1,2,3,4");
wrapper.inSql("id","select id from user where id < 4");
userMapper.selectList(wrapper).forEach(System.out::println);

查看sql

SELECT id,name,age FROM user WHERE 
    id IN (1,2,3,4) AND id IN (1,2,3,4) AND id IN (1,2,3,4) 
    AND id IN (select id from user where id < 4)

3、分页查询

(1)注册配置类

@Configuration
public class MyBatisPlusConfig {

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

}

测试

@Test
public void testPage() {
    Page page = new Page(3,3); //查询第3页,每页3条
    Page result = userMapper.selectPage(page, null);//条件构造器为null
    System.out.println("当前页:" + result.getCurrent());
    System.out.println("总条数:" + result.getTotal());
    System.out.println("总页数:" + result.getPages());
    System.out.println("页面大小:" + result.getSize());
    result.getRecords().forEach(System.out::println);//具体信息
}

4、动态sql

(1)mybatis-plus无法单独实现动态sql,需要创建mapper.xml映射文件来实现动态sql。

在yml配置文件设置驼峰匹配

mybatis-plus:
  type-aliases-package: com.hisoft.entity #别名,驼峰匹配

mapper接口

@Repository
public interface UserMapper extends BaseMapper<User> {
    List<User> queryUserByNameAndEmail(@Param("name")String name,@Param("email")String email);
}

mapper.xml映射文件

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.hisoft.mapper.UserMapper">
    <select id="queryUserByNameAndEmail" resultType="user">
        select * from user
        <where>
            <if test="name != null and name != ''">
                and name like concat('%',#{name},'%')
            </if>
            <if test="email != null and email != ''">
                and name like concat('%',#{email},'%')
            </if>
        </where>
    </select>
</mapper>

测试

@Test
public void testSql() {
    List<User> users = userMapper.queryUserByNameAndEmail("郭", null);
    users.forEach(System.out::println);
}

(2)若果不创建mapper.xml映射文件,也可以通过注解来实现动态sql

@Repository
public interface UserMapper extends BaseMapper<User> {

    @Select("<script>"+
            "select * from user\n" +
            "<where>" +
            "    <if test=\"name != null and name != ''\">" +
            "        and name like concat('%',#{name},'%')" +
            "    </if>" +
            "    <if test=\"email != null and email != ''\">" +
            "        and name like concat('%',#{email},'%')" +
            "    </if>" +
            "</where>"+
            "</script>")
    List<User> queryUserByNameAndEmail(@Param("name")String name,@Param("email")String email);
}

5、代码自动生成

(1)添加依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.4.1</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-velocity</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>

(2)测试

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
@Test
public void testGenerator() {
    //创建generator对象
    AutoGenerator autoGenerator = new AutoGenerator();
    //数据源
    DataSourceConfig dataSourceConfig = new DataSourceConfig();
    dataSourceConfig.setDbType(DbType.MYSQL);
    dataSourceConfig.setUrl("jdbc:mysql:///exam?useUnicode=true&characterEncoding=UTF-8");
    dataSourceConfig.setUsername("root");
    dataSourceConfig.setPassword("root");
    dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");
    autoGenerator.setDataSource(dataSourceConfig);
    //全局配置
    GlobalConfig globalConfig = new GlobalConfig();
    globalConfig.setOutputDir("E:\\IntelliJ IDEA\\WorkSpace\\Project01\\Mybatis-plusDemo\\src\\main\\java");
    globalConfig.setOpen(false);
    globalConfig.setAuthor("huzige");
    globalConfig.setServiceName("%sService");
    autoGenerator.setGlobalConfig(globalConfig);
    //包信息
    PackageConfig packageConfig = new PackageConfig();
    packageConfig.setParent("com.hisoft2");
    packageConfig.setModuleName("user");
    packageConfig.setController("controller");
    packageConfig.setService("service");
    packageConfig.setServiceImpl("service.impl");
    packageConfig.setMapper("mapper");
    packageConfig.setEntity("entity");
    autoGenerator.setPackageInfo(packageConfig);
    //配置策略
    StrategyConfig strategyConfig = new StrategyConfig();
    strategyConfig.setEntityLombokModel(true);
    strategyConfig.setNaming(NamingStrategy.underline_to_camel);
    strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);
    autoGenerator.setStrategy(strategyConfig);

    autoGenerator.execute();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值