MybatisPlus

MybatisPlus

一、注解

1.@TableName
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
public @interface TableName {
    String value() default "";

    String schema() default "";

    boolean keepGlobalPrefix() default false;

    String resultMap() default "";

    boolean autoResultMap() default false;

    String[] excludeProperty() default {};
}

标注在实体类上,声明实体类对应的表

excludeProperty设置需要排除的属性名(不是表中的字段)

2.@TableId
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface TableId {
    String value() default "";

    IdType type() default IdType.NONE;
}

标注在实体类的字段上,声明主键

type表示主键策略

public enum IdType {
    AUTO(0), // 主键自增,数据库中主键必须为自增才生效
    NONE(1), // 未设置主键,默认使用ASSIGN_ID(雪花算法)
    INPUT(2), // insert前自己设置主键
    ASSIGN_ID(3), // 使用雪花算法分配主键
    ASSIGN_UUID(4); // 使用UUID分配主键

    private final int key;

    private IdType(int key) {
        this.key = key;
    }

    public int getKey() {
        return this.key;
    }
}
3.@TableField
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface TableField {
    String value() default "";

    boolean exist() default true;

    String condition() default "";

    String update() default "";

    FieldStrategy insertStrategy() default FieldStrategy.DEFAULT;

    FieldStrategy updateStrategy() default FieldStrategy.DEFAULT;

    FieldStrategy whereStrategy() default FieldStrategy.DEFAULT;

    FieldFill fill() default FieldFill.DEFAULT;

    boolean select() default true;

    boolean keepGlobalFormat() default false;

    String property() default "";

    JdbcType jdbcType() default JdbcType.UNDEFINED;

    Class<? extends TypeHandler> typeHandler() default UnknownTypeHandler.class;

    boolean javaType() default false;

    String numericScale() default "";
}

标注实体类的字段上,表示表中的字段非主键

exists设置该属性是否为数据库的字段

fill设置字段自动填充策略

public enum FieldFill {
    DEFAULT, // 默认不处理
    INSERT, // 插入时填充字段
    UPDATE, // 更新时填充字段
    INSERT_UPDATE; // 插入和更新时填充字段

    private FieldFill() {
    }
}
4.@Version

标注实体类的字段上,表示乐观锁字段

5.@TableLogic
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface TableLogic {
    String value() default ""; //逻辑未删除值

    String delval() default ""; //逻辑删除值
}

标注实体类的字段上,表示逻辑删除字段

二、主键策略

IdType

描述
AUTO主键自增,数据库中主键必须为自增才生效
NONE**(默认)**未设置主键,相当于ASSIGN_ID(雪花算法)
INPUTinsert前自己设置主键
ASSIGN_ID使用雪花算法分配主键
ASSIGN_UUID使用UUID分配主键

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

pojo类:

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("user")
public class User {

    @TableId // 相等于@TableId(type = IdType.ASSIGN_ID)
    private String username;

    private String password;

    @TableLogic
    @TableField(fill = FieldFill.INSERT)
    private Integer deleted;

    @TableField(fill = FieldFill.INSERT)
    private Date createTime;

    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;

    @Version
    private Long version;
}
@Autowired
private UserMapper userMapper;

/**
 * 插入用户
 */
@Test
void contextLoads1() {
    User user = new User();
    user.setPassword("123");
    int insert = userMapper.insert(user);
    System.out.println(insert == 1 ? "添加用户成功!" : "添加用户失败!!!");
}

在这里插入图片描述

当主键策略为IdType.NONE,插入数据时未设置主键,则使用雪花算法生成主键,若设置了主键则根据设置的值插入

修改主键策略为IdType.AUTO

@TableId(type = IdType.AUTO)
private String username;

在这里插入图片描述

数据库对应的User表的username字段不是自增长的,所以报错

修改主键策略为IdType.INPUT

@TableId(type = IdType.INPUT)
private String username;

插入数据时需要自己设置主键

修改主键策略为IdType.ASSIGN_UUID

@TableId(type = IdType.ASSIGN_UUID)
private String username;

在这里插入图片描述

当主键策略为IdType.ASSIGN_UUID,插入数据时未设置主键,则使用UUID算法生成主键,若设置了主键则根据设置的值插入

三、条件构造器Wrapper

AbstractWrapper函数:

函数名解释
allEq全部属性相等或个别属性为空
eq等于
ne不等于
gt大于
ge大于等于
lt小于
le小于等于
between在两值之间
notBetween不在两值之间
like包括某个值(%值%)
notLike不包括某个值
likeLeft以某个值结尾(%值)
likeRight以某个值开头(值%)
isNull字段为空
isNotNull字段不为空
groupBy分组
orderByAsc升序排序
orderByDesc降序排序

四、自动填充

在实体类逻辑删除字段上标记@TableField,设置fill属性

public enum FieldFill {
    DEFAULT, //默认不处理
    INSERT, //插入时填充字段
    UPDATE, //更新时填充字段
    INSERT_UPDATE; //插入和更新时填充字段

    private FieldFill() {
    }
}

自动填充创建时间createTime、修改时间updateTime和是否删除deleted初始值0

@TableLogic
@TableField(fill = FieldFill.INSERT)
private Integer deleted;

@TableField(fill = FieldFill.INSERT)
private Date createTime;

@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;

向容器中注入组件MetaObjectHandler

@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill ....");
        //插入数据时间初始化
        this.setFieldValByName("createTime", new Date(), metaObject);
        this.setFieldValByName("updateTime", new Date(), metaObject);
        //插入数据deleted初始值0
        this.setFieldValByName("deleted", 0, metaObject); 
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill ....");
        //修改数据更新时间
        this.setFieldValByName("updateTime", new Date(), metaObject); 
    }

}

添加用户:
在这里插入图片描述

修改用户信息:
在这里插入图片描述

五、逻辑删除

在实体类逻辑删除字段上标记@TableLogic

/**
 * 逻辑删除
 */
@Test
void contextLoads2() {
    User user = new User();
    user.setUsername("admin");
    int delete = userMapper.deleteById(user);
    System.out.println(delete == 1 ? "删除用户成功!" : "删除用户失败!!!");
}

在这里插入图片描述

六、分页插件

配置分页插件(拦截器实现):

@Configuration
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

        //分页
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());

        return interceptor;
    }
}
/**
 * 分页
 */
@Test
void contextLoads5() {
    Page<User> page = new Page<>(1, 5);
    Page<User> userPage = userMapper.selectPage(page, null);
    userPage.getRecords().forEach(System.out::println);
    System.out.println("记录总数:" + userPage.getTotal());
    System.out.println("总页数:" + userPage.getPages());
}

在这里插入图片描述

在这里插入图片描述

七、乐观锁插件

乐观锁:当要更新一条记录的时候,希望这条记录没有被别人更新

在实体类的字段上加上@Version注解

@Version
private Long version;

配置乐观锁插件(拦截器实现):

@Configuration
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

        //乐观锁
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        
        return interceptor;
    }
}
/**
 * 乐观锁修改(需要先查询出数据然后对其修改,乐观锁才生效)
 */
@Test
void contextLoads3() {
    User user = userMapper.selectById("1520683956281499649");
    user.setPassword("asd");
    int update = userMapper.updateById(user);
    System.out.println(update == 1 ? "修改用户成功!" : "修改用户失败!!!");
}

在这里插入图片描述

八、防止全表更新删除插件

配置防全表更新删除插件(拦截器实现):

@Configuration
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        
        //阻止恶意的全表更新删除
        interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());

        return interceptor;
    }
}
/**
 * 阻止恶意的全表更新删除
 */
@Test
void contextLoads4() {
    int delete = userMapper.delete(null);
    System.out.println(delete >= 1 ? "删除表成功!" : "删除表失败!!!");
}

在这里插入图片描述

九、p6spy组件打印Sql分析

导入依赖:

<dependency>
    <groupId>p6spy</groupId>
    <artifactId>p6spy</artifactId>
    <version>3.9.1</version>
</dependency>

修改数据库连接urldriver-class-name

spring:
  datasource:
    username: root
    password: 1234
    # 添加 p6spy:
    url: jdbc:p6spy:mysql://localhost:3306/jdbc?useSSL=false&serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF8
    driver-class-name: com.p6spy.engine.spy.P6SpyDriver

添加spy.properties

#3.2.1以上使用
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定义日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#日志输出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 使用日志系统记录 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 设置 p6spy driver 代理
deregisterdrivers=true
# 取消JDBC URL前缀
useprefix=true
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
# 是否开启慢SQL记录
outagedetection=true
# 慢SQL记录标准 1 秒
outagedetectioninterval=1

测试:

在这里插入图片描述

在这里插入图片描述

十、数据库连接加密

@SpringBootTest
public class AESEncryptTest {

    
    
    @Test
    void test1(){
        //String randomKey = AES.generateRandomKey(); //生成 16 位随机 AES 密钥
        //System.out.println(randomKey); //记录下这个秘钥用于加密
        String randomKey = "77775f697e419128";
        String url = "jdbc:p6spy:mysql://localhost:3306/jdbc" +
                "?useSSL=false&serverTimezone=GMT%2B8&useUnicode=true&" +
                "characterEncoding=UTF8";
        String username = "root";
        String password = "1234";
        // 随机密钥加密
        String result_url = AES.encrypt(url, randomKey);
        String result_username = AES.encrypt(username, randomKey);
        String result_password = AES.encrypt(password, randomKey);
        System.out.println(randomKey+"||"+result_url);
        System.out.println(randomKey+"||"+result_username);
        System.out.println(randomKey+"||"+result_password);
    }
}

修改数据库连接配置:

# 添加mpw:前缀,后面为加密后的值
spring:
  datasource:
    # 数据库连接加密
    username: mpw:279X16wMW5LQXIP/EjLpdA==
    password: mpw:os4s3WqyAe0K48kCefjI7Q==
    url: mpw:lDBCPwJ6MZPMMPpAP+05ADsYfbcE/JKhyZfVPH3e287XD5+TfOsT9/rkemZOiWLQbAwDVcYyNxIKzG42aO5HacXy2DZlPChia1uyVtdUSW4tNdq0UIOd/dMbUOmXg/pA/Xha5KLd5K65IENymJO2WxopDRm9UNvDSojKr9SnExU=
    # 原始
    #username: root
    #password: 1234
    #url: jdbc:p6spy:mysql://localhost:3306/jdbc?useSSL=false&serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF8
    driver-class-name: com.p6spy.engine.spy.P6SpyDriver

在项目启动类中配置程序实参--mpw.key=秘钥
在这里插入图片描述

测试:

@Mapper
public interface UserMapper extends BaseMapper<User> {

}
public interface UserService extends IService<User> {

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

}
@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping("/list")
    public List<User> list(){
        return userService.list();
    }
}

在这里插入图片描述

十一、代码生成器

​ 通过数据库表自动生成对应的实体类、Mapper层(包括Mapper.xml文件)、Service层以及

Controller层通用代码,快速开发

导入依赖:

<!--代码生成器-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.5.2</version>
</dependency>
<!--freemarker模版引擎-->
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.31</version>
</dependency>
public class CodeGenerator {

    //只需修改数据库名称、用户名和密码即可使用
    private static String dbName = "spring_security";

    private static String username = "root";

    private static String password = "1234";

    /**
     * 数据源配置
     */
    private static final DataSourceConfig.Builder DATA_SOURCE_CONFIG = new DataSourceConfig
            .Builder("jdbc:mysql://localhost:3306/" + dbName + "?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=GMT%2B8", username, password)
            .dbQuery(new MySqlQuery()) //数据库查询
            .schema(dbName) //数据库schema(部分数据库适用)
            .typeConvert(new MySqlTypeConvert()) //数据库类型转换器
            .keyWordsHandler(new MySqlKeyWordsHandler()); //数据库关键字处理器

    public static void main(String[] args) {
        FastAutoGenerator.create(DATA_SOURCE_CONFIG)
                .globalConfig((scanner, builder) -> builder
                        .fileOverride() //覆盖已生成文件,默认值:false
                        .outputDir(System.getProperty("user.dir") + "/src/main/java") //指定输出目录,默认值: windows:D://
                        .author(scanner.apply("请输入开发者名称:"))//作者名,baomidou 默认值:作者
                        .dateType(DateType.TIME_PACK)//时间策略,DateType.ONLY_DATE(数据库中日期类型字段生成对应实体类中Date类型属性) 默认值: DateType.TIME_PACK(数据库中日期类型字段生成对应实体类中LocalDateTime类型属性)
                        .commentDate("yyyy-MM-dd")//注释日期,默认值: yyyy-MM-dd
                        .disableOpenDir()// 禁止打开输出目录,默认值:true
                        //.enableKotlin() //开启 kotlin 模式,默认值:false
                        .enableSwagger() //开启 swagger 模式,默认值:false
                        .build()//加入构建队列
                )
                .packageConfig((scanner, builder) -> builder
                        .parent(scanner.apply("请输入包名:"))//父包名,默认值:com.baomidou
                        //.moduleName("sys")//父包模块名,默认值:无
                        .entity("pojo")//pojo 包名,默认值:entity
                        .service("service")//Service 包名,默认值:service
                        .serviceImpl("service.impl")//Service Impl 包名,默认值:service.impl
                        .mapper("mapper")//Mapper 包名,默认值:mapper
                        .xml("mapper.xml")//Mapper XML 包名,默认值:mapper.xml
                        .controller("controller")//Controller 包名,默认值:controller
                        //.other("other")//自定义文件包名,    输出自定义文件时所用到的包名
                        .pathInfo(Collections.singletonMap(OutputFile.xml, "src/main/resources/mapper")) //路径配置信息,Collections.singletonMap(OutputFile.mapperXml, "D://")
                        .build()//加入构建队列
                )
                .strategyConfig((scanner, builder) -> builder
                        /** 基本参数配置 */
                        .enableCapitalMode()//开启大写命名,默认值:false
                        .enableSkipView()//开启跳过视图,默认值:false
                        .disableSqlFilter()//禁用 sql 过滤,默认值:true,语法不能支持使用 sql 过滤表的话,可以考虑关闭此开关
                        .likeTable(new LikeTable("t_user_login"))//模糊表匹配(sql 过滤)   likeTable 与 notLikeTable 只能配置一项
                        /** 设置需要生成的表名 */
                        .addInclude(scanner.apply("请输入要生成的表名,多个表使用空格分割:").split(" "))// 增加表匹配(内存过滤),include 与 exclude 只能配置一项
                        /** 前缀配置*/
                        //.addTablePrefix("t_")//增加过滤表前缀
                        //.addFieldSuffix("_")//增加过滤表后缀
                        //.addFieldPrefix("ul_")//增加过滤字段前缀  本人不建议使用,去掉后缀,会导致驼峰命名实体类的变量名不带前缀,去掉后,错误:Username,正确:ulUsername
                        //.addFieldSuffix("_")//增加过滤字段后缀

                        /** 实体策略配置 */
                        .entityBuilder()//实体策略配置
                        .disableSerialVersionUID()//禁用生成 serialVersionUID,默认值:true
                        .enableLombok()//开启 lombok 模型,默认值:false
                        .enableChainModel()//开启链式模型,默认值:false
                        .enableRemoveIsPrefix()//开启 Boolean 类型字段移除 is 前缀,默认值:false
                        .enableTableFieldAnnotation()//开启生成实体时生成字段注解,默认值:false
                        .enableActiveRecord()//开启 ActiveRecord 模型,默认值:false
                        .naming(NamingStrategy.underline_to_camel)//数据库表映射到实体的命名策略,默认下划线转驼峰命名:NamingStrategy.underline_to_camel
                        .columnNaming(NamingStrategy.underline_to_camel)//数据库表字段映射到实体属性的命名策略,默认为 null,未指定按照 naming 执行
                        .idType(IdType.AUTO)//全局主键类型
                        //.formatFileName("%sBean")//格式化文件名称,生成实体的后缀,建议这样使用,生成后:UserLoginBean
                        //.superClass(BaseEntity.class)//设置父类
                        //.enableColumnConstant()//开启生成字段常量,默认值:false
                        //.addIgnoreColumns("age")//添加忽略字段
                        //.nameConvert(INameConvert)//名称转换实现
                        .addTableFills(
                            new Column("create_time", FieldFill.INSERT), //创建时间字段添加自动填充属性
                            new Column("update_time", FieldFill.INSERT_UPDATE), //修改时间字段添加自动填充属性
                            new Column("deleted", FieldFill.INSERT) //逻辑删除字段添加自动填充属性
                        )
                        .versionColumnName("version")//乐观锁字段名(数据库)
                        .versionPropertyName("version")//乐观锁属性名(实体)
                        .logicDeleteColumnName("deleted")//逻辑删除字段名(数据库)
                        .logicDeletePropertyName("deleted")//逻辑删除属性名(实体)
                        //.enableSchema()//启用 schema,默认值:false,多 schema 场景的时候打开
                        //.addExclude("t_simple")//增加表排除匹配(内存过滤),include 与 exclude 只能配置一项
                        //.notLikeTable(new LikeTable("USER"))//模糊表排除(sql 过滤)  likeTable 与 notLikeTable 只能配置一项

                        /** controller 策略配置 */
                        .controllerBuilder()//controller 策略配置
                        .enableHyphenStyle()//开启驼峰转连字符,默认值:false
                        .enableRestStyle()//开启生成@RestController 控制器,默认值:false
                        .formatFileName("%sController")//格式化文件名称——controller包下自动生成的类后缀,例如UserLoginController

                        /** Service 策略配置 */
                        .serviceBuilder()//service 策略配置
                        .formatServiceFileName("%sService")//转换 service 接口文件名称,例如:UserLoginService
                        .formatServiceImplFileName("%sServiceImpl")//转换 service 实现类文件名称,例如:UserLoginServiceImpl

                        /** mapper 策略配置 */
                        .mapperBuilder()//mapper 策略配置
                        .superClass(BaseMapper.class)//设置父类,BaseMapper是com.baomidou.mybatisplus.core.mapper中的
                        .enableMapperAnnotation()//开启 @Mapper 注解,默认值:false
                        .enableBaseResultMap()//启用 BaseResultMap 生成,默认值:false
                        .enableBaseColumnList()//启用 BaseColumnList,默认值:false
                        .formatMapperFileName("%sMapper")//转换 mapper 接口文件名称后缀,mapper目录下的,例如:UserLoginMapper(有@Mapper)
                        .formatXmlFileName("%sMapper")//转换 xml 文件名称后缀,例如:UserLoginMapper.xml,Mybatis的xml映射文件
                        .build()//加入构建队列
                )
                /**
                 * 模板引擎
                 */
                //Velocity
                //.templateEngine(new VelocityTemplateEngine())
                //Beetl
                //.templateEngine(new BeetlTemplateEngine())
                //Freemarker
                .templateEngine(new FreemarkerTemplateEngine())
                .execute();

    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值