十、MybatisPlus

十、MybatisPlus

总结:
mapper接口:mapper接口中无需写增删改查方法。只需要继承BaseMapper接口;(里面自动帮忙写好了基本的增删改查方法,需要时可以直接调用 “xxxMapper.方法名” 直接调用即可)
mapper.xml配置文件:mapper.xml配置文件无需创建。使用条件构造器Wrapper帮忙拼接复杂的sql语句,无需创建mapper接口对应的mapper.xml配置文件编写sql语句了;
实体类上添加注解与数据库红表和字段绑定:表名:@TableName(“ACC_POS”)、主键:@TableId(“ID”)、字段@TableField(“CRT_DT”)


MyBatis-Plus(简称 MP)是一个MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,为简化开发 提高效率而生.
一、配置:application.properties配置文件中配置mysql的连接、添加日志的配置;
二、创建实体类:
@TableId(type = IdType.AUTO)//id自增
//@TableId(type = IdType.INPUT)//一旦手动输入id之后,就需要自己设置id了(即测试类MybatisPlusApplicationTests中testInsert()方法new User时需要setId)
private Long id;

@Version//MP的乐观锁的version注解
private Integer version;

@TableLogic//逻辑删除注解
private Integer deleted;

//字段添加填充内容
@TableField(fill = FieldFill.INSERT)//在插入时填充
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)//在插入和更新时填充
private Date updateTime;
三、新建mapper接口:继承BaseMapper基类、添加@Repository注解;(无需创建UserMapper接口对应的UserMapper.xml文件);
四、启动类上加注解:MybatisPlusApplication启动类上添加@MapperScan(“com.asd.mapper”)注解扫描mapper包;
五、测试类进行测试:注入userMapper,调用其extends的BaseMapper中已有的一些CRUD方法。
wrapper.isNotNull("name"):name不为null的
wrapper.eq("name", "Jack"):name为Jack的
wrapper.ge("age", 12):age大于等于12的
wrapper.in("age", 20,30,40):age在"20,30,40"几个数字当中的
wrapper.between("age", 20, 30):age在20-30岁之间的
wrapper.like("name", "p"):name中包含p的
wrapper.notLike("name", "e"):name中不包含e的
wrapper.orderByDesc("id"):orderByDesc降序,根据id进行降序
wrapper.likeRight("email", "t"):(%在右边)表示 t%,表示以t开头
wrapper.inSql("id", "select id from user where id<3"):inSql表示id是在子查询中查询出来的 where-in查询
wrapper.orderByAsc("code"):升序
wrapper.orderByDesc("code"):降序
           

User user = userMapper.selectOne(wrapper);
Integer count = userMapper.selectCount(wrapper);
userMapper.selectList(wrapper).forEach(System.out::println);
userMapper.selectMaps(wrapper).forEach(System.out::println);
userMapper.selectObjs(wrapper).forEach(System.out::println);

List<User> users=userMapper.selectList(wrapper);
    users.forEach(System.out::println);
List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
    maps.forEach(System.out::println);//对其进行foreach
List<Object> objects = userMapper.selectObjs(wrapper);//selectObjs查询的是一些对象
    objects.forEach(System.out::println);
详细参考如下:
一、配置

①application.properties配置文件中配置mysql的连接、添加日志的配置;(②idea中连接数据库:右方Database——+Data Source—MySql——输入User、Password(Database不用输)——Test Connection;)

# 端口号
server.port=9000
# 环境设置
spring.profiles.active=dev
# 数据库连接配置
#mysql 5 驱动不同:com.mysql.jdbc.Driver
#mysql 8 驱动不同:com.mysql.cj.jdbc.Driver、需要增加时区的设置
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 配置日志(此处添加默认日志;若其他日志如log4j则需要添加相应的依赖)
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
二、创建实体类

1、有关主键生成策略:
分布式系统唯一id生成方案:uuid、自增id、雪花算法、redis生成、Zookeeper生成;
【1】雪花算法:此处(即MybatisPlusApplicationTests类中testInsert()方法没有setId,实体类User的id上未添加@TableId(type= IdType.AUTO))会自动生成id使用雪花算法:雪花算法snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。可以保证几乎全球唯一。
【2】主键自增:
第一步:实体类User的id字段上添加@TableId(type=IdType.AUTO)注解(其type可设不同值,当值为IdType.AUTO表示主键自增);
第二步:数据库需要自增的字段上勾选自增;(实体类上加上面注解,数据库中字段不勾选自增会报错);
IdType的值:

public enum IdType {
    AUTO(0),    //数据库id自增
    NONE(1),    //未设置主键
    INPUT(2),   //手动输入
    ID_WORKER(3),//默认的全局id(数字)
    UUID(4),    // 全局唯一id
    ID_WORKER_STR(5);//截取字符串 ID_WORKER的字符串表示(字符串)
}

【3】手动输入:
第一步:将实体类User的id字段上注解@TableId(type=IdType.INPUT)中改为INPUT;
第二步:测试类MybatisPlusApplicationTests中testInsert()方法new User时需要setId值(user.setId(6L)😉(一旦手动输入id之后,就需要自己设置id了,
测试类MybatisPlusApplicationTests中testInsert()方法若没有setId,User(id=null, name=lala, age=3, email=123456@qq.com))

2、(时间日期等字段的)自动填充:
创建时间、修改时间,gmt_create、gmt_modified几乎所有的表都要配置上,而且需要自动化,不希望手动更新;
【方式一】:数据库级别(因为修改数据库了,工作中不建议使用)
1.在表中新增字段create_time,update_time,类型为datetime;勾选下方 根据当前时间戳更新,输入设置的默认值为 CURRENT_TIMESTAMP;
2.实体类直接同步,添加字段,类型为Date;
3.测试查看更新结果;
【方式二】:代码级别
1.删除数据库的默认值、更新操作((根据当前时间戳更新)自动更新取消勾选,设置的默认值删除);
2.实体类的字段createTime、updateTime上添加 @TableField(fill= FieldFill.INSERT)注解:(fill= FieldFill.INSERT)在插入时填充,(fill = FieldFill.INSERT_UPDATE)在插入和更新时填充

public enum FieldFill {
    DEFAULT,    //默认不填充
    INSERT,     //在插入时填充
    UPDATE,     //在更新时填充
    INSERT_UPDATE;//在插入和更新时填充
}

3.编写处理器来处理注解
新建handler包,编写MyMetaObjectHandler处理器类;
①此处理器要加入到IOC容器中被识别,需要在类上加@Component注解; 用到日志需要在类上加@Slf4j注解;
②此类implements MetaObjectHandler 实现MetaObjectHandler,实现里面的insertFill、updateFill方法;
方法中调用this.setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject) 参数:(想修改的字段名、想插入的字段值、想给哪个参数处理)
4.实体类User的id字段上改为@TableId(type= IdType.AUTO)自增再在test类中进行插入、更新测试,观察时间的填充和变化;

3、乐观锁:
乐观锁:十分乐观,总是认为不会出现问题,无论干什么都不去上锁,如果出现问题,在此更新测试;
悲观锁:十分悲观,认为总是出现问题,无论干什么都会上锁,在去操作;
乐观锁的实现方式:
1.取出记录时,获取当前版本;
2.更新时,带上这个version;
3.执行更新时,set version=newVersion where version=oldversion
4.如果version不对,就更新失败;
eg:
(1.先查询获取版本号为version=1;2.更新时,id条件后带上这个version;3.执行更新时把version由原来的版本改为最新的版本,一般会自动+1;4.如果version不对,就更新失败)

-----A(线程)
update user set name='lala',version=version+1
where id=2 and version=1
-----B(线程)抢先于A线程完成,此时version=2了,会导致A线程修改失败!
update user set name='lala',version=version+1
where id=2 and version=1

测试MP(mybatis plus)的乐观锁插件
1.表中新增version字段,并设置默认值都为1;
2.实体类加对应的字段version,并在字段上添加@version注解(mybatis plus的乐观锁的version注解);
3.注册组件:新建config包,创建MyBatisPlusConfig配置类:
①在类上加@Confguration注解表示这是一个配置类;(有事务的控制还可以加上一个@EnableTransactionManagement注解自动管理事务);
若在此配置类上管理mybatis plus,则可以将启动类上的包扫描(是交给mybatis做的),不放在启动类上了,放在此配置类上;
②类中注册乐观锁插件;
此时乐观锁插件配置完毕;
4.测试类中进行测试;

4、删除操作:
Test测试类中删除测试:deleteById(id)根据id删除、deleteBatchIds(idLists)根据批量id删除、deleteByMap(map)根据map封装和删除条件删除;
【逻辑删除】:(本质是更新操作,不是删除!)
物理删除:从数据库中直接移除;
逻辑删除:在数据库中没有被移除,而是通过一个变量让他失效;(如:isDel=0 =>isDel=1,运用例子:管理员可以查看被删除的记录)防止数据的丢失
1.在数据表中添加一个deleted字段,设置一个默认值 为0;
2.实体类中增加deleted字段并添加注解@TableLogic(逻辑删除注解);
3.配置:MyBatisPlusConfig配置类中添加@Bean逻辑删除组件、application.properties属性文件中添加逻辑删除配置;
4.测试删除(deleteById(id)此时记录仍在,只是deleted字段值由0变为1,即由未删除状态变为已删除状态);
(逻辑删除之后,再进行selectById(id)查询操作,会查询不到此数据,因为加上上方一系列逻辑删除操作之后,查询时会自动拼接 AND deleted=0查询条件
SELECT id,name,age,email,version,deleted,create_time,update_time FROM user WHERE id=? AND deleted=0;
查询时会自动过滤掉被逻辑删除的字段)

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

    //id对应数据库中的主键(uuid、自增id、雪花算法、redis生成、Zookpeer生成)
    @TableId(type = IdType.AUTO)//id自增
    //@TableId(type = IdType.INPUT)//一旦手动输入id之后,就需要自己设置id了(即测试类MybatisPlusApplicationTests中testInsert()方法new User时需要setId)
    private Long id;

    private String name;
    private Integer age;
    private String email;

    @Version//MP的乐观锁的version注解
    private Integer version;

    @TableLogic//逻辑删除注解
    private Integer deleted;

    //字段添加填充内容
    @TableField(fill = FieldFill.INSERT)//在插入时填充
    private Date createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)//在插入和更新时填充
    private Date updateTime;
}
三、新建mapper接口
//①在对应的Mapper上继承基本的接口BaseMapper (无须再写对应的UserMapper.xml配置文件了)——②后面再在测试类上加@MapperScan注解扫描mapper文件夹
@Repository
public interface UserMapper extends BaseMapper<User> {
    //所有的CRUD都编写完成了(BaseMapper已经帮忙写好了)
}
四、启动类上加注解:MybatisPlusApplication启动类上添加@MapperScan(“com.asd.mapper”)注解扫描mapper包;
//加此注解扫描mapper文件夹
/*@MapperScan("com.asd.mapper")*/
@SpringBootApplication
public class MybatisPlusApplication {
    public static void main(String[] args) {
        SpringApplication.run(MybatisPlusApplication.class, args);
    }
}
五、测试类进行测试:注入userMapper,调用其extends的BaseMapper中已有的一些CRUD方法。
@SpringBootTest
public class WapperTest {

    @Autowired
    private UserMapper userMapper;

    //查询name不为null的用户,并且邮箱不为空的用户,年龄大于等于12岁的
    @Test
    void contextLoads() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper
                .isNotNull("name")
                .isNotNull("email")
                .ge("age", 12);//g大于 e等于
        userMapper.selectList(wrapper).forEach(System.out::println);
        //List<User> users=userMapper.selectList(wrapper);//和map对比
        //users.forEach(System.out::println);
        /*和map对比:
        map直接put条件值;
        wrapper是一个对象,对象不能直接put,他有自己的很多的方法,可以直接使用其方法赋条件。*/
    }

    //查询年龄在"20,30,40"几个数字当中的,名字为Jack的
    @Test
    public void test2() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.in("age", 20,30,40);
        wrapper.eq("name", "Jack");
        User user = userMapper.selectOne(wrapper);//selectOne查询一个数据,出现多个结果使用list或者map
        System.out.println(user);
    }

    //查询年龄在20-30岁之间的用户
    @Test
    public void test3() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.between("age", 20, 30);
        Integer count = userMapper.selectCount(wrapper);//selectCount查询结果数,返回一个Integer类型 数量
        System.out.println(count);
    }

    //模糊查询:查询name中不包含e,并且email以t开头的
    @Test
    public void test4() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        //likeLeft、likeRight, 左和右如何区分,代表%在左边还是右边 %e或者e%,若两边都要匹配%e%
        wrapper
                .notLike("name", "e")//notLike表示name中不包含e
                .like("name","p")//名字中包含p的
                .likeRight("email", "t");//表示 t%,表示以t开头
        wrapper.between("age", 20, 30);
        List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
        maps.forEach(System.out::println);//对其进行foreach
    }

    //sql中嵌套sql
    @Test
    public void test5() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        //inSql表示id是在子查询中查询出来的 where-in查询
        wrapper.inSql("id", "select id from user where id<3");
        List<Object> objects = userMapper.selectObjs(wrapper);//selectObjs查询的是一些对象
        objects.forEach(System.out::println);
    }

    //排序
    @Test
    public void test6() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        //根据id进行排序
        wrapper.orderByDesc("id");//orderByDesc降序
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }
}

六、分页查询:

(参考:https://blog.csdn.net/womenyiqilalala/article/details/95073892
MybatisPlus其实也内置了分页插件;如何使用?:
1.配置文件中配置 PaginationInterceptor拦截器组件;
2.再直接使用Page(或IPage)对象即可;
1.MyBatisPlusConfig 配置文件中:

@MapperScan("com.asd.mapper")//mapper文件夹扫描
@EnableTransactionManagement//自动管理事务的注解 默认开启
@Configuration//配置类
public class MyBatisPlusConfig {
  //分页插件(配置拦截器)
  @Bean
  public PaginationInterceptor paginationInterceptor() {
      return new PaginationInterceptor();
  }
}

2.使用:

@Resource
private UserMapper userMapper;

//测试分页查询1
@Test
public void testPage() {
   //参数一:当前页码、参数二:页面大小(显示的条数)
   Page<User> page = new Page<>(2, 5);//查询第1页,每页5个 /查询第2页,每页5个
   IPage<User> userIPage = userMapper.selectPage(page, null);
   
   System.out.println("总页数: "+userIPage.getPages());
   System.out.println("总记录数: "+userIPage.getTotal());
   userIPage.getRecords().forEach(System.out::println);
   List<User> list=userIPage.getRecords();
   for(User user : list){
	      System.out.println(user);//输出对象
	}
}

//测试分页查询2
@Test
public void testPage2(){
  //方法参数一:page
  Page<User> page = new Page<>(1 , 2);
  //方法参数二:wrapper
  QueryWrapper<User> wrapper =new QueryWrapper<>();
  wrapper.like("age", 9);
  //调用
  IPage<User> userIPage = userMapper.selectPage(page , wrapper);
  System.out.println("总页数: "+userIPage.getPages());
  System.out.println("总记录数: "+userIPage.getTotal());
  userIPage.getRecords().forEach(System.out::println);
}
七、其他:
6.2 条件构造器Wrapper

写一些复杂的sql就可以使用条件构造器来替代;
和map对比(都是new出来作为查询条件传入):
map直接put条件值;
wrapper是一个对象,对象不能直接put,他有自己的很多的方法,可以直接使用其方法赋条件。

6.3 代码自动生成器

AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、
Service、Controller 等各个模块的代码,极大的提升了开发效率。
dao、pojo、service、controller都自己生成。
1.pom.xml中引入mybatis-plus的依赖;
2.application.properties进行配置:服务端口、开发环境、连接数据库的配置等;
3.编写一个类让其帮忙自动生成pojo…等其他类;
test包下创建一个GenerateCode.java类(即代码自动生成器)
注:自动生成代码时报错:引入 “模板引擎” 依赖!
测试自动生成代码在项目:“E:\IdeaWorkSpace\springboot_mp_jdbc\easyexcel_work_test”————
"MybatisPlusGenerator.java"中!

6.4 性能分析插件

在平时开发中会遇到一些慢sql(慢查询),可通过测试、压测、druid…等工具进行操作;
MP也提供了一款性能分析插件,如果超过这个时间就停止运行;
作用:分析每条sql执行的时间. 性能分析拦截器,用于输出每条sql语句及其执行时间;
1.导入插件;
即配置:MyBatisPlusConfig配置类中添加@Bean性能分析插件(即sql执行效率插件)、application.properties属性文件中设置开发环境;
(配置完后此插件即可生效,但直接return new PerformanceInterceptor();是无法看到功能的;
可以在new出一个对象之后setMaxTime(1)设置sql执行的最大时间为1ms(默认单位ms),如果超过了不执行、以及开启sql格式化的格式化支持)
2.测试使用;
Test中测试查询全部的用户contextLoads;
(结果:运行报错
Cause: com.asd.mybatis_plus.core.exceptions.MybatisPlusException:The SQL execution time is too large, please optimize !
因为sql执行时间设置为1ms太短,sql实际的执行时间超过规定的时间所以抛异常,需要将时间设置变长.)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值