Mybatis-Plus 学习总结笔记

简介

目前在实习的这家公司开发技术栈用到了 Mybatis-Plus,之前我用的都是Mybatis,于是花了些时间补学了下。学习的时候笔记是记在有道云笔记上,假期无事,于是自己回顾一遍,整理一下放到csdn上。

一、常用注解

  • 1.排除某些和数据库字段没有对应的实体属性:
@TableField(exit=false)
private String name;
  • 2.实体类和数据库表对应(加在实体类上)
@TableName("数据库表名")
  • 主键对应
@TableId
private Long id;
  • 4.字段对应
@TableField("字段名")
private String userName;
  • 5.这样设置可以让字段由默认的等值查询改为模糊查询
@TableField(condition=SqlCondition.LIKE)
private String name;
  • 6.也可以让字段由默认的等值查询改为自定义查询方式(这里是小于)
@TableField(condition="%s<#{%s}")
private Integer age;

二、普通查询

  • 1.根据一个id查一条数据
User user = userMapper.selectById(1);
  • 2.根据多个id查多条数据
List<Integer> list = Arrays.asList(1, 2, 3);
List<User> list1 = userMapper.selectBatchIds(list);
  • 3.根据多个条件查数据
Map<String,Object> map = new HashMap<String,Object>();
params.put("name","王天风");
params.put("age",null);
List<User> list = userMapper.selectByMap(map);

三、查询条件构造器:

  • 1.两种方式得到QueryWrapper实例:
QueryWraper<User> queryWraper = new QueryWraper<>();
QueryWrapper<User> queryWraper = Wrappers.query();
  • 2.名字中包含雨并且年龄小于40 ( name like ‘%雨%’ and age<40)
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("name", "雨").lt("age", 40);
List<User> userList = userMapper.selectList(queryWrapper);
  • 3.名字中包含雨年并且龄大于等于20且小于等于40并且email不为空(name like ‘%雨%’ and age between 20 and 40 and email is not null)
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("name", "雨").between("age" ,20 ,40)
            .isNotNull("email");
List<User> userList = userMapper.selectList(queryWrapper);
  • 4.名字为王姓或者年龄大于等于25,按照年龄降序排列,年龄相同按照id升序 排列( name like ‘王%’ or age>=25 order by age desc,id asc)
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.likeRight("name", "王").or().gt("age", 25)
            .orderByDesc("age").orderByAsc("id");
List<User> userList = userMapper.selectList(queryWrapper);
  • 5.创建日期为2019年2月14日并且直属上级为名字为王姓
    date_format(create_time,’%Y-%m-%d’)=‘2019-02-14’ and manager_id in (select id from user where name like ‘王%’)
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.apply("date_format(create_time, '%Y-%m-%d')={0}","2019-02-12")
            .inSql("id", "select id from user where name like '王%");
List<User> userMappers = userMapper.selectList(queryWrapper);

apply():数据库函数 动态入参,insql:子查询

  • 6.名字为王姓并且(年龄小于40或邮箱不为空)
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.likeRight("name", "王").and(wq -> wq.lt("age", 40)
            .or().isNotNull("email"));
List<User> userMappers = userMapper.selectList(queryWrapper);

构造器配合lambda表达式

  • 7.(年龄小于40或者邮箱不为空)并且名字为王姓
    (age< 40 email is not null )and name like ‘王%’
queryWrapper.nested(wq->wq.lt("age",40).or()
            .isNotNull("email")).likeRight("name","王");

ps:
1.sql中or的优先级小于and
2.queryWrapper.nested(函数式接口) 括号在最前面的情况下用

  • 8.范围查询:年龄为30,31,32,33,34,35
List<Integer> list = Arrays.asList(30, 31, 34, 35);
queryWrapper.in("age",list);
  • 9…范围查询,但只返回其中的一条记录
queryWrapper.in("age",list).last("limit 1");

ps:多次使用last()会有sql注入的风险

  • 10.查询部分字段
queryWrapper.select("name", "age").eq("id", 1);
  • 11.查询部分字段的另一种用法(排除某些字段)
queryWrapper.select(User.class, info -> info.getColumn().equals("age"))
            .lt("age", 40);    //排除age字段
queryWrapper.select(User.class, info -> !info.getColumn().equals("age"))
            .lt("age", 40);     //排除非age字段 
  • 12.condition:condition是个布尔值,为真就把后面的字段加入最后的sql
//用法:
//queryWrapper.like(布尔值, 字段名, 字段值);
queryWrapper.like(!StringUtils.isEmpty("字符串"), "name", "小米");

ps:不只是like()方法可以这样使用,ge(),lt(),eq()等都可以这样用

  • 13.使用实体入参创建构造器,就是会把实体的属性值作为查询的条件
User user = new User(1,"小米", 18);
QueryWrapper<User> queryWrapper = new QueryWrapper<>(user);

ps:后续对queryWrapper做限制和这里入参的条件不冲突,条件会叠加

  • 14.AllEq用法 map多条件入参
// 默认如果某个条件为null,则最后的sql会将这个条件转换为isNull,如这里
// 就会转换成where name="王天风" and age IS NULL 
Map<String,Object> map= new HashMap<String,Object>();
params.put("name","王天风");
params.put("age",null);
queryWrapper.allEq(map);

//如果相应在某个字段为空就不加入sql条件的话,可以这样:
queryWrapper.allEq(map, false);

//allEq()方法可以直接排除某些字段不加入sql,这里就将name字段过滤掉
//这里是根据键过滤,也可以根据值过滤
//用法:allEq(BiPredicate<String, V) filter, Map<String, V> map)
queryWrapper.allEq((k, v) -> k.equals("name")), map);

四、其他查询条件构造器:

  • 1.selectMaps(),查询的记录为一个map
//当只需要查某些字段时,如果用selectList(),其他的字段会为null,用
//selectMaps()就只会查询出相应的字段
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.select("id", "name").gt("age", 18);
Map<User> map = userMapper.selectMaps(queryWrapper);

//当查询的字段需要改名,或者是查询用到了函数,也可以用selectMaps()
queryWrapper.select("AVG(age) as user_age ", "name").gt("age", 18);
  • 2.selectObjs(),只返回多列中的第一列
//这里我查询id和name列,但是那寻出来的name值会被舍弃,只会将id封装进list里
queryWrapper.select("id", "name").gt("age", 18);
List<Object> list = userMapper.selectObjs(queryWrapper);
  • 3.selectCount(),返回满足条件的总记录数
queryWrapper.select().gt("age", 18);
Integer count = userMapper.selectCount(queryWrapper);

ps:此处select()方法里不能有参数

  • 4.selectOne(),返回一条记录,为实体类型
queryWrapper.select().gt("age", 18);
User user = userMapper.selecOne(queryWrapper);

ps:只能返回0条或一条记录,大于1条会报错

五、其他查询条件构造器:

  • 1.构造lumbda查询条件构造器的三种方式:
LambdaQueryWrapper<User> lambdaquery1 = new QueryWrapper<User>().lambda();
LambdaQueryWrapper<User> lambdaquery2 = new LambdaQueryWrapper<>();
LambdaQueryWrapper<User> lambdaquery3 = Wrappers.<User>lambdaQuery();
  • 2.使用方法引用的方式入参查询条件(防误写)
lambdaqueryWrapper2.like(User :: getName, "王");
  • 3.一种特殊的lumbda条件构造器(链式)
List<User> list = new LambdaQueryChainWrapper<User>(userMapper).like(User::getName, "王").list();

六、自定义sql

//1.先在mapper类定义一个接口
List<User> selectAll(@Param(Constants.WRAPPER) Wrapper<User> wrapper);
//2.在properties文件中配置xml文件的路径
mybaties-plus:
    mapper-locations:
        -xml文件路径
//3.编写xml文件(sql里不用加where关键字,会智能加上)
<select id="selectAll" resultType=com.entity>
    select * from user ${ew.customSqlSegment}  
</select>  
//调用。。。 

七、分页查询

  • 1.单表分页查询,用mybaties-plus提供的方法就可以
//1.定义一个配置类
@Configuration
public class MybatiesConfig {
    @Bean
    public PaginationInterceptor paginationInterceptor(){
        return new PaginationInterceptor();
    }
}

//2.编写方法
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.ge("age", 18);
Page<User> userPage = new Page<>(pageNo, pageSize);
Ipage<User> ipage = userMapper.selectPage(userPage, queryWrapper);
long pages = userPage1.getPages();  //总页数
long total = userPage1.getTotal();  //总记录数
List<OrderItem> orders = userPage1.getOrders();  //对象集合

//3.也可以用selectMapsPage()方法,返回的是map集合,这个方法和之前一样,
//  当只要查询部分字段的时候,其他的字段会被过滤掉,不会显示为null
Ipage<Map<String, Object> ipage = userMapper.selectPage(userPage, queryWrapper);

//4.当不需要总记录数时,可以在构造Page时多入参一个false参数
Page<User> userPage = new Page<>(pageNo, pageSize, false);
  • 2.多表分页查询,需自定义sql
//1.在mapper包中定义接口
Ipage<User> selectUserPage(Page<User> page, 
            @Param(Constants.WRAPPER) Wrapper<User> wrapper);
//2.编写xml文件
<select id="selectUserPage" resultType=com.entity.user>
    select * from user ${ew.customSqlSegment}  
</select> 
//调用。。。

八、更新

  • 1.根据主键更新
User user = new User(1,"小米", 18);
int i = userMapper.updateById(user);
  • 2.更新条件构造器
UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
userUpdateWrapper.eq("id", "1");
User user = new User(1,"小米", 18);
int update = userMapper.update(user, userUpdateWrapper);

//在构造UpdateWrapper时,也可以用实体入参,实体的属性会作为sql的where条件
UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>(user);

//只更新个别字段的情况
UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
userUpdateWrapper.eq("name", "小米").set("age", 19);
int update = userMapper.update(null, userUpdateWrapper);
  • 2.lumbda更新条件构造器
LambdaUpdateWrapper<User> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
lambdaUpdateWrapper.eq(User::getName, "小米").set(User::getAge, "20");
int update1 = userMapper.update(null, userLambdaUpdateWrapper);
  • 3.特殊的umbda更新条件构造器(链式)
boolean bool = new LambdaUpdateChainWrapper<>(userMapper).eq(User::getId, 1)
                    .set(User::getName, "大米").update();

九、删除

  • 1.根据主键删除
int i = userMapper.deleteById(1);
  • 2.多条件删除
Map<String,Object> map = new HashMap<String,Object>();
params.put("name","王天风");
params.put("age",null);
int row = userMapper.selectByMap(map);
  • 3.同时删除多个
List<Integer> list = Arrays.asList(1, 2, 3);
int i = userMapper.deleteBatchIds(list);
  • 4.删除条件构造器
QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
userQueryWrapper.eq("id", 2);
int delete = userMapper.delete(userQueryWrapper);

十、AR模式

//1.让实体类继承Model
public class User extends Model<User> {}
//2.定义一个mapper继承baseMapper
public interface UserMapper extends BaseMapper<User> {)}
//3.这样就可以直接操作实体,返回成功与非
User user = new User(1,"小米", 18);
boolean bool = user.insert();
//4.也可以查询
User user = new User(1,"小米", 18);
User user = user.selectById());
//5.也可以更新
User user = new User(1,"小米", 18);
boolean bool = user.updateById();
//6.也可以删除
User user = new User(1,"小米", 18);
boolean bool = user.deleteById();
//特例
boolean bool = user.insertOrUpdate();

十一、主键策略

  • 1.局部主键策略
//通过在实体属性上加注解(如设置为主键自增)
@TableId(type = IdType.AUTO)
private Integer id;
//IdType.ID_WORKER(全局唯一id)
//IdType.ID_WORKER_STR(字符串类型全局唯一id)
//IdType.UUID
  • 2.全局的需要在配置文件中配置
mybaties-plus:
    global-config:
        db-config:
            id-type: uuid/id-worker/id-worker-str/auto

十二、通用service

  • 1.定义接口继承IService
public interface UserService extends IService<Usr>{}
  • 2.定义接口的实现类
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService{}

十三、逻辑删除

  • 1.在配置文件里配置
mybaties-plus:
    global-config:
        db-config:
            logic-not-delete-value: 0  #用0标识未删除
            logic-delete-value: 1  #用1标识已经删除
  • 2.在实体类属性上加上逻辑删除注解
@TableLogic
private Integer deleted;
  • 3.在查询的时候排除deleted字段
@TableField(select = false)
private Integer deleted;

ps:自定义sql的话,已经逻辑删除的记录还是会被查出来,需要自己加限制条件排除已经逻辑删除了的记录

十四、自动填充

//1.在实体类需要字段填充的属性上加上注解
@TableField(fill = FieldFill.INSERT)  //新增时填充
private LocalDateTime createTime;
@TableField(fill = FieldFill.UPDATE)  //更新时填充
private LocalDateTime updateTime;

//2.编写配置类
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        setFieldValByName("createTime", LocalDateTime.now(), metaObject);
    }
    @Override
    public void updateFill(MetaObject metaObject) {
        setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
    }
}

//3.另外,配置类里的这两个方法是默认每次新增或更新都会执行的,比如有的表
//  没有createTime或者updateTime字段,就不用执行,可以这样:
@Override
public void insertFill(MetaObject metaObject) {
    if (metaObject.hasSetter("createTime")){
        MetaObjectHandler createTime = setFieldValByName("createTime", LocalDateTime.now(), metaObject);
    }
} 

//4.想要当自己手动添加了更新时间,不想要自动填充时,可以这样
@Override
public void updateFill(MetaObject metaObject) {
    Object updateTime = getFieldValByName("updateTime", metaObject);
    if (updateTime == null){
        setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
    }
}

十五、乐观锁插件

//1、在实体类添加version属性,并添加注解,同意数据库表添加相应字段
@Version
private Integer version;

//2.编写配置类
@Configuration
public class MybatiesPlusConfig {
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor(){
        return new OptimisticLockerInterceptor();
    }
}

十六、多租户

//1.在实体类定义租户id属性,同时数据库建立对应字段
private String manageId;
//2.多租户依赖分页插件,所以先配置分页插件
@Bean
public PaginationInterceptor paginationInterceptor(){
    PaginationInterceptor paginationInterceptor = new PaginationInterceptor();  //分页插件
    //创建sql解析器接口
    ArrayList<ISqlParser> spList = new ArrayList<>();  
    //创建多租户sql解析器
    TenantSqlParser tenantSqlParser = new TenantSqlParser(); 
    //设置TenantHandler   
    tenantSqlParser.setTenantHandler(new TenantHandler() {      
        @Override  //设置多租户字段
        public Expression getTenantId(boolean where) {      
            return "表中的多租户字段";
        }

        @Override  //租户信息(一般从session或配置文件中取出)
        public String getTenantIdColumn() {    
            return "租户id";
        }

        @Override  //过滤不加租户信息的表
        public boolean doTableFilter(String tableName) {    
            if ("表名".equals(tableName)){ //这里设置的表就不会增加租户信息
                return true;
            }
            return false;
        }
    });
    spList.add(tenantSqlParser);

    return paginationInterceptor;
}

//3.方法级过滤(某些方法不增加租户信息),在mapper包方法上加注解
@SqlParser(filter = true)
List<User> selectUserPage();
发布了35 篇原创文章 · 获赞 52 · 访问量 1305

猜你喜欢

转载自blog.csdn.net/weixin_40242806/article/details/104076862