mybatis map里面传对象_mybatis-plus入门到精通

a15e45c086de47309c097746b3655b6a.png

基于springbooot的mybatisplus

官网:https://mp.baomidou.com/

相关依赖

    <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.1.tmp</version>
        </dependency>

相关数据库配置

spring.datasource.username= root
spring.datasource.password= 123456
spring.datasource.url= jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
spring.datasource.hikari.driver-class-name=com.mysql.cj.jdbc.Driver
#mybatis日志输出到控制台
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

相关Mapper接口

@Repository
public interface PeopleMapper extends BaseMapper<People> {
//该接口直接集成BaseMapper接口,里面有大量写好的操作数据库的方法,我们将实体类作为泛型传入,可直接操作
//注意:该接口需要注明是一个Mapper,在启动类上加@MapperScan("com.baidu.mapper"),
//或在本类上加@Mapper注解均可
​
//接口中的方法
    /**
     * 插入一条记录
     * @param entity
     * 实体对象
     * @return int
     */
    Integer insert(T entity);
    /**
     * 根据 ID 删除
     * @param id
     * 主键ID
     * @return int
     */
    Integer deleteById(Serializable id);
​
     /**
     * 根据 columnMap 条件,删除记录
     * @param columnMap
     * 表字段 map 对象
     * @return int
     */
    Integer deleteByMap(@Param("cm") Map<String, Object> columnMap);
​
    /**
     * 根据 entity 条件,删除记录
     * @param wrapper
     * 实体对象封装操作类(可以为 null)
     * @return int
     */
    Integer delete(@Param("ew") Wrapper<T> wrapper);
​
​
     /**
     * 删除(根据ID 批量删除)
     * @param idList
     * 主键ID列表
     * @return int
     */
    Integer deleteBatchIds(List<? extends Serializable> idList);
​
    /**
     * 根据 ID 修改
     * @param entity
     * 实体对象
     * @return int
     */
    Integer updateById(T entity);
​
    /**
     * 根据 whereEntity 条件,更新记录
     * @param entity
     * 实体对象
     * @param wrapper
     * 实体对象封装操作类(可以为 null)
     * @return
     */
    Integer update(@Param("et") T entity, @Param("ew") Wrapper<T> wrapper);
​
    /**
     * 根据 ID 查询
     * @param id
     * 主键ID
     * @return T
     */
    T selectById(Serializable id);
​
​
     /**
     * 查询(根据ID 批量查询)
     * @param idList  (里面传一个list集合,例如:Arrays.asList(id1,id2,id3L))
        可以使用ArrayList.asList(),也可以new List传入
    * 主键ID列表
     * @return List<T>
     */
    List<T> selectBatchIds(List<? extends Serializable> idList);
​
​
    /**
     * 查询(根据 columnMap 条件)(一般不用)
     * @param columnMap
     里面传入一个map集合,根据传入的条件查询
     map.put("name",22)
     map.put("age",18)
     where name = 22,age = 18
     * 表字段 map 对象
     * @return List<T>
     */
    List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);
 
    /**
     * 根据 entity 条件,查询一条记录
     * @param entity
     * 实体对象
     * @return T
     */
    T selectOne(@Param("ew") T entity);
 
    /**
     * 根据 Wrapper 条件,查询总记录数
     * @param wrapper
     * 实体对象
     * @return int
     */
    Integer selectCount(@Param("ew") Wrapper<T> wrapper);
 
    /**
     * 根据 entity 条件,查询全部记录
     * @param wrapper
     * 实体对象封装操作类(可以为 null)
     * @return List<T>
     */
    List<T> selectList(@Param("ew") Wrapper<T> wrapper);
 
    /**
     * 根据 Wrapper 条件,查询全部记录
     * @param wrapper
     * 实体对象封装操作类(可以为 null)
     * @return List<T>
     */
    List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> wrapper);
 
    /**
     * 根据 Wrapper 条件,查询全部记录
     * @param wrapper
     * 实体对象封装操作类(可以为 null)
     * @return List<Object>
     */
    List<Object> selectObjs(@Param("ew") Wrapper<T> wrapper);
 
    /** 
     * 用法:(new RowBounds(offset, limit), ew);
     * 根据 entity 条件,查询全部记录(并翻页)
     * @param rowBounds
     * 分页查询条件(可以为 RowBounds.DEFAULT)
     * @param wrapper
     * 实体对象封装操作类(可以为 null)
     * @return List<T>
     */
    List<T> selectPage(RowBounds rowBounds, @Param("ew") Wrapper<T> wrapper);
 
    /** -- 不常用,
     * 根据 Wrapper 条件,查询全部记录(并翻页)
     * @param rowBounds
     * 分页查询条件(可以为 RowBounds.DEFAULT)
     * @param wrapper
     * 实体对象封装操作类
     * @return List<Map<String, Object>>
     */
    List<Map<String, Object>> selectMapsPage(RowBounds rowBounds, @Param("ew") Wrapper<T> wrapper);
    
}

相关实体类

@Data
public class People {
    /*设置主键生成策略
    AUTO  自动增长
    INPUT 自行输入
    NONE 无状态,自行输入
    UUID 32为uuid字符串
    ID_WORKER 分布式全局唯一ID 长整型(LONG)
    ID_WORKER_STR 分布式全局唯一ID 字符串型(STRING)
    */
    @TableId(type = IdType.AUTO) 
    private  int id;
    private String uname;
    private String pwd;
    /*自动填充
    INSERT 插入时填充
    UPDATE 更新时填充
    INSERT_UPDATE 插入或更新时填充
    DEFAULT 
    */
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    private Date updateTime;
​
}
​

mybatis-puls的自动填充

1.在实体类上添加注解 @TableField(fill = FieldFill.INSERT)

2.创建类,实现接口 MetaObjectHandler

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
           //  通过名字修改属性值           属性名    属性值        元数据(参数)
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updateTimme",new Date(),metaObject);
    }
​
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTimme",new Date(),metaObject);
    }
}
/**
小提示:  在mysql中字段为create_time,实体类中字段名为createTime(可以自动映射)
​
​
*/

mybatis-plus实现乐观锁

在不考虑事务隔离性的情况下

产生的读的问题:

脏读:事务1第二次读取时,读到了事务2未提交的数据。若事务2回滚,则事务1第二次读取时,读到了脏数 据。

不可重复读:与脏读逻辑类似。主要在于事务2在事务1第二次读取时,提交了数据。导致事务1前后两次读 取的数据不一致。

幻读:事务1第二次查询时,读到了事务2提交的数据。

写的问题:

丢失更新问题:事务1和事务2同时操作一份数据,事务1提交后,事务2提交会覆盖事务1的数据

解决:

悲观锁(串行操作):一份数据同一时间只能由一人操作(锁表/锁记录),操作完后才能由其他人操作

乐观锁:取出记录时,获取当前的version(版本号)

更新时,带上这个version

执行更新时,set version = new Version where version = oldversion

如果version不对,就更新失效

实现乐观锁:

1.在数据库中加一个字段version(自己定义名字)

2.在实体类中加一个对应版本号字段,并添加@Version注解,可以用之前的@TableField(file=FieldFill.INSERT)设 置一个初始值(可以不加,不加第一次为空)

 @Version
 @TableField(fill=FieldFill.INSERT)
 private int version;

3.创建springboot配置类

@Configuration
@EnableTransactionManagement  //开启事务管理支持,在Mapper中添加@Transactional 即可实现事务
@MapperScan("com.baidu.mapper")
public class MpConfig {
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
}

3.测试乐观锁

 @Test
    void testOptimisticLockerInterceptor() {
        People people = peopleMapper.selectById("1");
        people.setId(1);
        people.setPwd("456");
        peopleMapper.updateById(people);
        /*
        注意:需要先查询再更新,如果直接更新
        相关SQL:UPDATE people SET uname=?, pwd=?, create_time=?, update_time=?, version=? WHERE id=? AND version=? 
        相关实体类没有version的话,则更新失败
        可以手动设置version的值(不推荐)
        更新之后version会+1
        */
    }

mybatis-plus实现分页(类似pagehelper)

1.在配置类中配置分页插件

    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
        // paginationInterceptor.setOverflow(false);
        // 设置最大单页限制数量,默认 500 条,-1 不受限制
        // paginationInterceptor.setLimit(500);
        // 开启 count 的 join 优化,只针对部分 left join
        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
        return paginationInterceptor;
        //可以直接return new PaginationInterceptor();
    }

2.实现分页

    @Test
    void testPage() {
        //第一个参数为当前页数,第二个参数为显示条数
        Page<People> page = new Page<>(1,3);
        //第一个参数为上面的page对象,第二个为条件
        peopleMapper.selectPage(page, null);
        long current = page.getCurrent();//获取当前页
        List<People> records = page.getRecords();//每页数据的集合
        page.getSize();//每页显示条数
        page.getTotal();//总记录数
        page.getPages();//总页数
        page.hasNext();//是否有下一页
        page.hasPrevious();//是否有上一页
    }

mybatis-plus逻辑删除

物理删除:直接从表中删除数据

逻辑删除:在表中设置标记位,删除时只是将标记位的值改变

逻辑删除实现:

1.在表中加入标记位int deleted(名字自行定义)

2.实体类中添加对应字段 deleted

 	@TableLogic
    @TableField(fill = FieldFill.INSERT)//增加时自动设置值,也可以在建表时设置default默认值
    private int deleted;

3.效果: 使用mp自带方法删除和查找都会附带逻辑删除功能 (自己写的xml不会)

example
删除 update user set deleted=1 where id =1 and deleted=0
查找 select * from user where deleted=0

配置类中配置逻辑删除插件(MybatisPlus 3.1.1以下版本需要,以上不需要)

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

备注:application.properties 加入配置(如果你的默认值和mp默认的一样,该配置可无):

mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
# 该配置可以不写,默认没删除是0,删除了是1
# 在application.propertis中可以自行配置

mybatis-plus 性能分析插件

性能分析拦截器,用于输出每条 SQL 语句及其执行时间

该插件 3.2.0 以上版本移除推荐使用第三方扩展 执行SQL分析打印 功能

 	/**
     * SQL执行效率插件
     */
    @Bean
    @Profile({"dev","test"})// 设置 dev test 环境开启
    public PerformanceInterceptor performanceInterceptor() {
        return new PerformanceInterceptor();
    }

设置springboot环境

# dev 开发环境 test 测试环境 prod 生产环境
spring.profiles.active=dev
注意!参数说明:
参数:maxTime SQL 执行最大时长,超过自动停止运行,有助于发现问题。
参数:format SQL SQL是否格式化,默认false。
该插件只用于开发环境,不建议生产环境使用。

执行 SQL 分析打印

(官方文档:https://mp.baomidou.com/guide/p6spy.html)

p6spy 依赖引入Maven:

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

spy.properties 配置:

#3.2.1以上使用
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
#3.2.1以下使用或者不配置
#modulelist=com.p6spy.engine.logging.P6LogFactory,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
# 实际驱动可多个
#driverlist=org.h2.Driver
# 是否开启慢SQL记录
outagedetection=true
# 慢SQL记录标准 2 秒
outagedetectioninterval=2
注意!
driver-class-name 为 p6spy 提供的驱动类
url 前缀为 jdbc:p6spy 跟着冒号为对应数据库连接地址
打印出sql为null,在excludecategories增加commit
批量操作不打印sql,去除excludecategories中的batch
批量操作打印重复的问题请使用MybatisPlusLogFactory (3.2.1新增)
该插件有性能损耗,不建议生产环境使用。

mp实现复杂条件查询(条件构造器)

e4ca13973b8e6b9e6324de03c1ee4ec9.png
  1. 上图绿色框为抽象类abstract
  2. 蓝色框为正常class类,可new对象
  3. 黄色箭头指向为父子类关系,箭头指向为父类

wapper介绍 :

Wrapper : 条件构造抽象类,最顶端父类,抽象类中提供4个方法西面贴源码展示 AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件 AbstractLambdaWrapper : Lambda 语法使用 Wrapper统一处理解析 lambda 获取 column。 LambdaQueryWrapper :看名称也能明白就是用于Lambda语法使用的查询Wrapper LambdaUpdateWrapper : Lambda 更新封装Wrapper QueryWrapper : Entity 对象封装操作类,不是用lambda语法 UpdateWrapper : Update 条件封装,用于Entity对象更新操作

  /*
  查询年龄大于20的people
  */
  @Test
    void testSelectQuery() {
        QueryWrapper<People> wrapper = new QueryWrapper<>();
        wrapper.ge("age",20);  //ge表示大于等于 >=,传入字段和值,age>20 
         List<People> people = peopleMapper.selectList(wrapper);
    }
eq   等于 =	 例: eq("name", "老王")--->name = '老王'
ne	 不等于 <> 例: ne("name", "老王")--->name <> '老王'
ge 	 大于等于 >= 例: ge("age", 18)--->age >= 18
lt  小于 < 例: lt("age", 18)--->age < 18
le	 小于等于 <= 例: le("age", 18)--->age <= 18
between ETWEEN 值1 AND 值2 例: between("age", 18, 30)--->age between 18 and 30
notBetween NOT BETWEEN 值1 AND 值2 例: notBetween("age", 18, 30)--->age not between 18 and 30
like LIKE '%值%' 例: like("name", "王")--->name like '%王%'

更多查阅官方文档:https://mp.baomidou.com/guide/wrapper.html#abstractwrapper

更多知识欢迎关注微信公众号"JAVA不归路",使用微信扫一扫关注

http://weixin.qq.com/r/ID-y6urEprfZra6J92oy (二维码自动识别)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值