数据持久层框架:MyBatis-Plus

数据持久层框架:MyBatis-Plus

  • 前言
    • 注解
    • 代码生成器
    • CURD接口
      • Service CRUD 接口
      • Mapper CRUD 接口
    • 条件构造器
      • QueryWrapper和UpdateWrapper
      • allEq
      • eq、ne
      • gt、ge、lt、le
      • between、notBetween
      • like、notLike、likeLeft、likeRight、notLikeLeft、notLikeRight
      • isNull、isNotNull
      • in、notIn、inSql、notInSql
      • groupBy、orderByAsc、orderByDesc、having
      • or、and
      • exists、notExists
      • 组合查询
      • 动态条件查询
    • 主键策略
    • 逻辑删除
    • 自动填充功能
    • 防全表更新与删除插件
    • MybatisX快速开发插件

前言

MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 MapperModelServiceController 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
  • 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 deleteupdate 操作智能分析阻断,也可自定义拦截规则,预防误操作

SpringBoot为例,导入依赖:

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

数据库配置如下

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/spring_data?characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456

示例代码如下:

@TableName("user")
public class User {private Integer id;private String name;private String age;//getter and setter
}
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
@SpringBootApplication
@MapperScan("com.example.mybatisstudy.dao")//扫描mapper
public class MybatisStudyApplication {public static void main(String[] args) {SpringApplication.run(MybatisStudyApplication.class, args);}}
@RunWith(SpringRunner.class)
@SpringBootTest
public class Test {@Autowiredprivate UserMapper userMapper;@org.junit.Testpublic void testSelect() {System.out.println(("----- selectAll method test ------"));List<User> userList = userMapper.selectList(null);userList.forEach(System.out::println);}
}

效果如图
在这里插入图片描述
从以上步骤中,我们可以看到集成MyBatis-Plus非常的简单,只需要引入 starter 工程,并配置 mapper 扫描路径即可。甚至连 XML 文件都不用编写!

注解

  • @TableName:表名注解,标识实体类对应的表
@TableName("user")
public class User {private Integer id;private String name;private String age;//getter and setter
}

注解更多属性如图:
在这里插入图片描述

  • @TableId:主键注解
@TableName("user")
public class User {@TableId(value = "id",type = IdType.AUTO)private Integer id;
}

types属性指定主键类型,默认IdType.NONE
在这里插入图片描述

  • @TableField:字段注解(非主键)
@TableName("user")
public class User {@TableId(value = "id",type = IdType.AUTO)private Integer id;@TableField(value = "name")private String name;
}

注解更多属性如图:
在这里插入图片描述

  • @Version:乐观锁注解、标记在字段上。
@TableName("user")
public class User {@TableId(value = "id",type = IdType.AUTO)@Versionprivate Integer id;
}

然后注册Bean

@Configuration
public class MyConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return mybatisPlusInterceptor;}
}
  • @EnumValue:普通枚举类注解。
@TableName("user")
public class User {@TableId(value = "id",type = IdType.AUTO)@Versionprivate Integer id;@EnumValueprivate String type;
}
  • @TableLogic:表字段逻辑处理注解(逻辑删除)。
@TableName("user")
public class User {@TableId(value = "id",type = IdType.AUTO)private Integer id;@TableField(value = "name")@TableLogic(value = "a",delval = "b")private String name;
}

value属性表示逻辑未删除值,delval属性表示逻辑删除值。

  • @KeySequence:于指定插入操作返回自增主键值的注解。在 MyBatis 中,有些数据库(如 Oracle)并不是像 MySQL 那样具有自增长主键的功能,而是通过序列(sequence)来生成主键值。
@TableName("user")
@KeySequence(value = "id",dbType = DbType.MYSQL)
public class User {
}
  • @InterceptorIgnore:用于指定是否在某个方法上忽略拦截器的注解。
@Intercepts({@Signature(type= Executor.class,method = "update",args = {MappedStatement.class,Object.class})
})
public class ExampleInterceptor implements Interceptor {// 实现拦截器的逻辑// ...
}public interface UserMapper {@InterceptorIgnore@Insert("INSERT INTO users (id, name) VALUES (#{id}, #{name})")int insertUser(User user);}
  • @OrderBy:指定查询操作的结果集的排序规则。
@TableName("user")
public class User {@TableId(value = "id", type = IdType.AUTO)private Integer id;@TableField(value = "name")private String name;@OrderBy(asc = true)private String age;
}

代码生成器

引入依赖

        <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.5.5</version></dependency><dependency><groupId>org.apache.velocity</groupId><artifactId>velocity-engine-core</artifactId><version>2.0</version></dependency>

示例代码如下:

public class Test {public static void main(String[] args) {FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3306/spring_data", "root", "123456")// 全局配置.globalConfig((scanner, builder) -> {builder.author(scanner.apply("请输入作者名称?"));// 获取用户的当前工作目录String userDir = System.getProperty("user.dir");builder.outputDir(userDir+"\\src\\main\\java\\"); // 指定输出目录})// 包配置.packageConfig((scanner, builder) -> builder.parent(scanner.apply("请输入包名?")))// 策略配置.strategyConfig((scanner, builder) -> builder.addInclude(getTables(scanner.apply("请输入表名,多个英文逗号分隔?所有输入 all"))).controllerBuilder().enableRestStyle().enableHyphenStyle().entityBuilder().enableLombok().addTableFills(new Column("create_time", FieldFill.INSERT)).build())/*模板引擎配置,默认 Velocity 可选模板引擎 Beetl 或 Freemarker.templateEngine(new BeetlTemplateEngine()).templateEngine(new FreemarkerTemplateEngine())*/.execute();}// 处理 all 情况protected static List<String> getTables(String tables){return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(","));}}

改进后,会自动生成到当前项目中,如图所示
在这里插入图片描述

CURD接口

Service CRUD 接口

Service CRUD 封装IService (opens new window)接口,进一步封装 CRUD 采用 get 查询单行 remove 删除 list 查询集合 page 分页 前缀命名方式区分 Mapper 层避免混淆,

public interface IUserService extends IService<User> {
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
}
  • Save

数据插入,如果数据已存在则报错

// 插入一条记录(选择字段,策略插入)
boolean save(T entity);
// 插入(批量)
boolean saveBatch(Collection<T> entityList);
// 插入(批量),batchSize:插入批次数量
boolean saveBatch(Collection<T> entityList, int batchSize);

示例代码如下:

@Controller
public class MyController {@Autowiredprivate IUserService iUserService;@GetMapping("/get")public void get(HttpServletResponse response){User user = new User();user.setId(9);user.setName("f");user.setAge("23");boolean b = iUserService.save(user);System.out.println(b);/** Output*  true*/}
}
  • SaveOrUpdate

先查询,数据库存在则更新记录,否插入一条记录

// TableId 注解存在更新记录,否插入一条记录
boolean saveOrUpdate(T entity);
// 根据updateWrapper尝试更新(类似条件)
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);

示例代码如下:

@Controller
public class MyController {@Autowiredprivate IUserService iUserService;@GetMapping("/get")public void get(HttpServletResponse response){User user = new User();user.setId(6);user.setName("f");user.setAge("23");boolean b = iUserService.saveOrUpdate(user);User user2 = new User();user2.setId(8);user2.setName("g");user2.setAge("23");boolean b2 = iUserService.saveOrUpdate(user2);}
}

如图所示:
在这里插入图片描述

  • Remove

数据删除

// 根据 queryWrapper 设置的条件,删除记录
boolean remove(Wrapper<T> queryWrapper);
// 根据 ID 删除
boolean removeById(Serializable id);
// 根据 columnMap 条件,删除记录
boolean removeByMap(Map<String, Object> columnMap);
// 删除(根据ID 批量删除)
boolean removeByIds(Collection<? extends Serializable> idList);

示例代码如下:

@Controller
public class MyController {@Autowiredprivate IUserService iUserService;@GetMapping("/get")public void get(HttpServletResponse response){boolean b = iUserService.removeById(7);boolean b2 = iUserService.removeByIds(Arrays.asList(1,2,3,4));}
}
  • Update

数据更新

// 根据 UpdateWrapper 条件,更新记录 需要设置sqlset
boolean update(Wrapper<T> updateWrapper);
// 根据 whereWrapper 条件,更新记录
boolean update(T updateEntity, Wrapper<T> whereWrapper);
// 根据 ID 选择修改
boolean updateById(T entity);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList, int batchSize);

示例代码如下:

@Controller
public class MyController {@Autowiredprivate IUserService iUserService;@GetMapping("/get")public void get(HttpServletResponse response){User user = new User();user.setId(6);user.setName("f");user.setAge("23");boolean b = iUserService.updateById(user);System.out.println(b);/** Output*  true*/}
}
  • Get

获取单条数据

// 根据 ID 查询
T getById(Serializable id);
// 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")
T getOne(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
T getOne(Wrapper<T> queryWrapper, boolean throwEx);
// 根据 Wrapper,查询一条记录
Map<String, Object> getMap(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
<V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);

示例代码如下:

@Controller
public class MyController {@Autowiredprivate IUserService iUserService;@GetMapping("/get")public void get(HttpServletResponse response){User user = iUserService.getById(1);System.out.println(user.toString());/** Output*  {id:1,name:a,age:12}*/}
}
  • List

获取列表数据

// 查询所有
List<T> list();
// 查询列表
List<T> list(Wrapper<T> queryWrapper);
// 查询(根据ID 批量查询)
Collection<T> listByIds(Collection<? extends Serializable> idList);
// 查询(根据 columnMap 条件)
Collection<T> listByMap(Map<String, Object> columnMap);
// 查询所有列表
List<Map<String, Object>> listMaps();
// 查询列表
List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper);
// 查询全部记录
List<Object> listObjs();
// 查询全部记录
<V> List<V> listObjs(Function<? super Object, V> mapper);
// 根据 Wrapper 条件,查询全部记录
List<Object> listObjs(Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录
<V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);

示例代码如下:

@Controller
public class MyController {@Autowiredprivate IUserService iUserService;@GetMapping("/get")public void get(HttpServletResponse response){List<User> list = iUserService.list();System.out.println(list.toString());System.out.println("===========================");Map<String, Object> map= new HashMap<>();map.put("name","a");List<User> list2 = iUserService.listByMap(map);System.out.println(list2.toString());System.out.println("===========================");List<User> list3 = iUserService.listByIds(Arrays.asList(1,2,3,4));System.out.println(list3.toString());/** Output*  [{id:1,name:a,age:12}, {id:2,name:b,age:13}, {id:3,name:c,age:14}, {id:4,name:bb,age:15}, {id:5,name:ee,age:22}, {id:6,name:null,age:2}, {id:7,name:f,age:2}]*  ===========================*  [{id:1,name:a,age:12}]*  ===========================*  [{id:1,name:a,age:12}, {id:2,name:b,age:13}, {id:3,name:c,age:14}, {id:4,name:bb,age:15}]*/}
}
  • Page

你需要配置分页拦截器:

@Configuration
public class MyConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return mybatisPlusInterceptor;}
}

调用page()方法进行分页

// 无条件分页查询
IPage<T> page(IPage<T> page);
// 条件分页查询
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);
// 无条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page);
// 条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper);

Page对象一共有四个构造方法,可以用来定义分页的页数和条数,你也可以调用对应的set方法进行赋值。

//传入页数、条数
public Page(long current, long size) {}
//传入页数、条数、总数
public Page(long current, long size, long total) {}
//传入页数、条数、是否查询总数:true是、false否
public Page(long current, long size, boolean searchCount) {}
//传入页数、条数、总数、是否查询总数:true是、false否
public Page(long current, long size, long total, boolean searchCount) {}

示例代码如下:

@Controller
public class MyController {@Autowiredprivate IUserService iUserService;@GetMapping("/get")public void get(HttpServletResponse response){Page<User> userPage = new Page<>(1,3,true);Page<User> p = iUserService.page(userPage);List<User> records = p.getRecords();System.out.println(records.toString());/** Output*  [{id:1,name:a,age:12}, {id:2,name:b,age:13}, {id:3,name:c,age:14}]*/}
}

searchCount属性为true的情况,会先去查询总数后分页。

在这里插入图片描述

  • Count

查询总数

// 查询总记录数
int count();
// 根据 Wrapper 条件,查询总记录数
int count(Wrapper<T> queryWrapper);

示例代码如下:

@Controller
public class MyController {@Autowiredprivate IUserService iUserService;@GetMapping("/get")public void get(HttpServletResponse response){long count = iUserService.count();System.out.println(count);/** Output*  8*/}
}

关于Wrapper对象的使用在稍后的章节里详细讲解。

  • Model

实体类只需继承 Model 类即可进行强大的 CRUD 操作

class User extends Model<User>{// fields...public static void main(String[] args) {User user = new User();user.insert();user.selectAll();user.updateById();user.deleteById();// ...}
}

不过在开发过程中,业务逻辑通过自动注入进行操作,实体类只用于数据传输操作。

Mapper CRUD 接口

通过封装BaseMapper (opens new window)接口实现CRUD操作。

@Mapper
public interface UserMapper extends BaseMapper<User> {
}
  • Insert

新增数据

int insert(T entity);

示例代码如下:

@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){User user = new User();user.setId(10);user.setName("h");user.setAge("23");long insert = userMapper.insert(user);System.out.println(insert);/** Output*  1*/}
}
  • Delete

删除数据

// 根据 entity 条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
// 删除(根据ID 批量删除)
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 ID 删除
int deleteById(Serializable id);
// 根据 columnMap 条件,删除记录
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

示例代码如下:

@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){//根据ID删除int deleteById = userMapper.deleteById(1);//根据ID批量删除int deleteById2 = userMapper.deleteBatchIds(Arrays.asList(1, 2, 3, 4));//根据key=value当做条件删除Map<String,Object> map = new HashMap<>();map.put("name","g");int deleteById3 = userMapper.deleteByMap(map);}
}
  • Update

修改数据

// 根据 whereWrapper 条件,更新记录
int update(@Param(Constants.ENTITY) T updateEntity, @Param(Constants.WRAPPER) Wrapper<T> whereWrapper);
// 根据 ID 修改
int updateById(@Param(Constants.ENTITY) T entity);

示例代码如下:

@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){User user = new User();user.setId(10);user.setName("h");user.setAge("23");long insert = userMapper.updateById(user);}
}
  • Select

查询数据

// 根据 ID 查询
T selectById(Serializable id);
// 根据 entity 条件,查询一条记录
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);// 查询(根据ID 批量查询)
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 entity 条件,查询全部记录
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 查询(根据 columnMap 条件)
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
// 根据 Wrapper 条件,查询全部记录
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);// 根据 entity 条件,查询全部记录(并翻页)
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录(并翻页)
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询总记录数
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

示例代码如下:

@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){//传null查询全部List<User> users = userMapper.selectList(null);//通过id查询User user = userMapper.selectById(1);//批量id查询List<User> users2 = userMapper.selectBatchIds(Arrays.asList(1,2,3,4));//根据key=value当做条件查询Map<String,Object> map = new HashMap<>();map.put("name","g");map.put("age","23");List<User> users3 = userMapper.selectByMap(map);}
}

条件构造器

CRUD的方法中,看到很多的Wrapper参数,下面就来学习如何使用它当中参数。

QueryWrapper和UpdateWrapper

QueryWrapper(LambdaQueryWrapper)UpdateWrapper(LambdaUpdateWrapper) 的父类,用于生成 sqlwhere 条件, entity 属性也用于生成 sqlwhere 条件。

  • QueryWrapper

QueryWrapperMyBatis-Plus 中的一个查询条件构造器,用于构建查询条件。使用 QueryWrapper 可以实现复杂的查询条件组合,例如等值条件、范围条件、模糊查询、排序等。QueryWrapper 还支持 Lambda 表达式,可以通过 Lambda 来指定字段名,减少因为字段改名而引起的错误。

使用select方法,指定查询返回字段。

@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.select("id","name");List<User> users = userMapper.selectList(wrapper);}
}

如图所示
在这里插入图片描述

  • UpdateWrapper

UpdateWrapperMyBatis-Plus 中用于构建更新操作条件的类,使用set()方法设置要更新的字段及对应的数值。

@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){UpdateWrapper<User> wrapper = new UpdateWrapper<>();wrapper.eq("id","7");wrapper.set("name","g");wrapper.set("age","20");int users = userMapper.update(wrapper);}
}

如图所示
在这里插入图片描述

allEq

传入Map参数,key为数据库字段名,value为字段值。

allEq(Map<R, V> params)
//null2IsNull:忽略空值
allEq(Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, Map<R, V> params, boolean null2IsNull)

示例代码如下:

@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){Map<String,Object> map = new HashMap<>();map.put("name","a");map.put("age",null);QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.allEq(map);List<User> users = userMapper.selectList(wrapper);System.out.println(users.toString());wrapper = new QueryWrapper<>();wrapper.allEq(map,false);List<User> users2 = userMapper.selectList(wrapper);System.out.println(users2.toString());/** Output*  []*  [{id:1,name:a,age:12}]*/}
}

执行结果如图

在这里插入图片描述

eq、ne

  • eq:等于 =
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.eq("name","a");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图所示
在这里插入图片描述

  • ne:不等于 <>
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.ne("name","a");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图所示

在这里插入图片描述

gt、ge、lt、le

  • gt:大于 >
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.gt("age",21);List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • ge:大于等于 >=
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.ge("age",21);List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • lt:小于 <
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.lt("age",21);List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • le:小于等于 <=
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.le("age",21);List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

between、notBetween

  • between:区间BETWEEN 值1 AND 值2
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.between("age",21,25);List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • notBetween:非区间NOT BETWEEN 值1 AND 值2
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.notBetween("age",21,25);List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图

在这里插入图片描述

like、notLike、likeLeft、likeRight、notLikeLeft、notLikeRight

  • like:全模糊匹配LIKE '%值%'
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.like("name","b");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • notLike:全模糊不匹配NOT LIKE '%值%'
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.notLike("name","b");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • likeLeft:左模糊匹配LIKE '%值'
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.likeLeft("name","b");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • likeRight:右模糊匹配LIKE '值%'
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.likeRight("name","b");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • notLikeLeft:左模糊不匹配NOT LIKE '%值'
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.notLikeLeft("name","b");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • notLikeRight:右模糊不匹配NOT LIKE '值%'
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.notLikeRight("name","b");List<User> users14 = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

isNull、isNotNull

  • isNull:是null
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.isNull("name");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图

在这里插入图片描述

  • isNotNull:不是null
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.isNotNull("name");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图

在这里插入图片描述

in、notIn、inSql、notInSql

  • in字段 IN (value.get(0), value.get(1), ...)
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.in("id",1,2,3,4,5);List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • notIn字段 NOT IN (value.get(0), value.get(1), ...)
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.notIn("id",1,2,3,4,5);List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • inSql字段 IN ( sql语句 )
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.inSql("id","select id from user where age <23");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • notInSql字段 NOT IN ( sql语句 )
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.notInSql("id","select id from user where age <23");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

groupBy、orderByAsc、orderByDesc、having

  • groupBy:分组 GROUP BY 字段, ...
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.groupBy("class_id");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图

在这里插入图片描述

  • orderByAsc:排序 ORDER BY 字段, ... ASC
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.orderByAsc("id");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图

在这里插入图片描述

  • orderByDesc:排序 ORDER BY 字段, ... DESC
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.orderByDesc("id");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图

在这里插入图片描述

  • havingHAVING ( sql语句 )
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.groupBy("class_id");wrapper.having("age >20");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

or、and

使用 QueryWrapperand()or() 方法可以实现多个查询条件的组合

@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.isNotNull("name").and(w1 -> w1.like("name", "a").eq("age", "12")).or(w2 -> w2.eq("name", "b").ge("age", "20"));List<User> users = userMapper.selectList(wrapper);}
}

如图所示

在这里插入图片描述

exists、notExists

  • exists:拼接 EXISTS ( sql语句 )
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.exists("select * from user where id = 1");List<User> users = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

  • notExists:拼接 NOT EXISTS ( sql语句 )
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.notExists("select * from user where id = 1");List<User> users2 = userMapper.selectList(wrapper);}
}

执行结果如图
在这里插入图片描述

组合查询

我们可以使用多个条件来过滤数据,从而得到符合多个条件的结果。

@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.eq("id",1);wrapper.eq("name","a");wrapper.eq("age","12");List<User> users = userMapper.selectList(wrapper);}
}

如图所示

在这里插入图片描述

动态条件查询

在实际的应用中,经常会遇到根据不同条件动态构建查询条件的情况。

@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){String name = null;String age = "12";QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.eq("id",1);if(name != null) {wrapper.eq("name", name);}if(age != null) {wrapper.eq("age", age);}List<User> users = userMapper.selectList(wrapper);}
}

如图所示
在这里插入图片描述
如果你要使用XML,需要加上配置文件进行扫描

主键策略

MyBatis-Plus 中,主键策略可以通过 @TableId 注解来指定。主键生成策略有多种选择,常用的有如下几种:

  • 数据库自增主键(默认):使用数据库自增主键的方式生成主键值,对应 MySQL 的 AUTO_INCREMENT 策略或者其他数据库的类似机制。
@TableName("user")
public class User {@TableId(value = "id", type = IdType.AUTO)private Integer id;private String name;private String age;
}
  • 雪花算法生成主键:使用雪花算法生成全局唯一的主键,一般用于分布式系统中。
@TableName("user")
public class User {@TableId(value = "id", type = IdType.ASSIGN_ID)private Integer id;private String name;private String age;
}
  • UUID 生成主键:使用 UUID 来生成主键值。
@TableName("user")
public class User {@TableId(value = "id", type = IdType.ASSIGN_UUID)private Integer id;private String name;private String age;
}
  • 自定义生成策略:可以实现 IdentifierGenerator 接口自定义主键生成策略。
@TableName("user")
public class User {@TableId(value = "id", type = IdType.INPUT)private Integer id;private String name;private String age;
}

自定义生成类

@Component
public class CustomIdGenerator implements IdentifierGenerator {@Overridepublic Long nextId(Object entity) {//可以将当前传入的class全类名来作为bizKey,或者提取参数来生成bizKey进行分布式Id调用生成.String bizKey = entity.getClass().getName();//根据bizKey调用分布式ID生成long id = ....;//返回生成的id值即可.return id;}
}

注入bean,两种方法

@Bean
public IdentifierGenerator idGenerator() {return new CustomIdGenerator();
}

或者通过 MybatisPlusPropertiesCustomizer 自定义

@Bean
public MybatisPlusPropertiesCustomizer plusPropertiesCustomizer() {return plusProperties -> plusProperties.getGlobalConfig().setIdentifierGenerator(new CustomIdGenerator());
}

内置支持:DB2KeyGenerator、H2KeyGenerator、KingbaseKeyGenerator、OracleKeyGenerator、PostgreKeyGenerator

@Bean
public IKeyGenerator keyGenerator() {return new H2KeyGenerator();
}

逻辑删除

逻辑删除是指在数据库中并不真正删除数据记录,而是通过标记一个字段来表示数据记录的删除状态,通常是将该字段的值设置为已删除的标识。

有两种方法可以使用逻辑删除:全局配置和指定注解

  • 全局配置

在配置文件中添加全局配置

# 逻辑已删除值(默认为 1)
mybatis-plus.global-config.db-config.logic-delete-value=1
# 逻辑未删除值(默认为 0)
mybatis-plus.global-config.db-config.logic-not-delete-value=0

找到实体类字段,加上注解@TableLogic

public class User implements Serializable {private static final long serialVersionUID = 1L;private Integer id;private String name;private String age;private Integer classId;@TableLogicprivate Integer isDel;@Overridepublic String toString() {return "{id:"+id+",name:"+name+",age:"+age+"}";}
}
  • 指定注解

你可以直接使用注解进行设置

public class User implements Serializable {private static final long serialVersionUID = 1L;private Integer id;private String name;private String age;private Integer classId;@TableLogic(value = "0",delval = "1")private Integer isDel;@Overridepublic String toString() {return "{id:"+id+",name:"+name+",age:"+age+"}";}
}

如果没有配置属性值,默认情况下value = "0",delval = "1"

加上注解后对应的CRUD操作会有一些变化:

  • 插入: 不作限制
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){User user = new User();user.setId(8);user.setName("g");user.setAge("15");userMapper.insert(user);}
}

如图所示
在这里插入图片描述

  • 查找: 追加 where 条件过滤掉已删除数据。
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){User user = userMapper.selectById(1);}
}

如图所示
在这里插入图片描述

  • 更新: 追加 where 条件防止更新到已删除数据。
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){User user = new User();user.setId(8);user.setName("g");user.setAge("15");userMapper.updateById(user);}
}

如图所示
在这里插入图片描述

  • 删除: 转变为 更新
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){userMapper.deleteById(8);}
}

如图所示
在这里插入图片描述

自动填充功能

自动填充功能可以用于在插入和更新操作时自动填充一些字段的值,比如创建时间、更新时间、操作人等。可以通过实现 MetaObjectHandler 接口来实现

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {LocalDateTime currentTime = LocalDateTime.now();this.strictInsertFill(metaObject, "ctime", LocalDateTime.class, currentTime);this.strictInsertFill(metaObject, "utime", LocalDateTime.class, currentTime);}@Overridepublic void updateFill(MetaObject metaObject) {LocalDateTime currentTime = LocalDateTime.now();this.strictUpdateFill(metaObject, "utime", LocalDateTime.class, currentTime);}
}

实体类加上注解@TableField(fill = FieldFill.*)

public class User implements Serializable {private static final long serialVersionUID = 1L;private Integer id;private String name;private String age;private Integer classId;private Integer isDel;@TableField(fill = FieldFill.INSERT)private LocalDateTime ctime;@TableField(fill = FieldFill.INSERT_UPDATE)private LocalDateTime utime;@Overridepublic String toString() {return "{id:"+id+",name:"+name+",age:"+age+"}";}
}

我们分别执行新增和修改操作

@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){User user = new User();user.setId(8);user.setName("g");user.setAge("15");userMapper.insert(user);}
}

如图所示

在这里插入图片描述

@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){User user = new User();user.setId(8);user.setName("g");user.setAge("15");userMapper.updateById(user);}
}

如图所示
在这里插入图片描述
可以看到执行新增和修改操作时都自动填充了相应的值。

FieldFill是一个枚举,有以下几种值:

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

防全表更新与删除插件

注入MybatisPlusInterceptor类,并配置BlockAttackInnerInterceptor拦截器

@Configuration
public class MyConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());return interceptor;}
}
@Controller
public class MyController {@Autowiredprivate UserMapper userMapper;@GetMapping("/get")public void get(HttpServletResponse response){User user = new User();user.setId(8);user.setName("g");user.setAge("15");userMapper.update(user,null);}
}

执行结果如图所示

在这里插入图片描述

MybatisX快速开发插件

MybatisX 是一款基于 IDEA 的快速开发插件,为效率而生。

安装方法:打开 IDEA,进入 File -> Settings -> Plugins -> Browse Repositories,输入 mybatisx 搜索并安装。

在这里插入图片描述
找到Idea最右侧,数据库连接,点击新建,输入用户名密码等信息,创建Mysql连接。

在这里插入图片描述

填写完毕后,点击Apply按钮。

按下列图顺序,选择显示的数据库
在这里插入图片描述
找到对应的表
在这里插入图片描述
点击MybatisX-Generator,填写路径和包名,点击下一步
在这里插入图片描述
然后选择Myabtis-Plus 3的相关操作,按图片勾选,点击Finish

在这里插入图片描述
生成效果如下

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/513685.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Cookie 探秘:了解 Web 浏览器中的小甜饼

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

list链表的创建,排序,插入, test ok

1. 链表的建立&#xff0c;打印 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <stack> #include <iostream> #include <string.h> #include <string>using namespace std;struct node {int data;s…

存内计算生态环境搭建以及软件开发

在当今数据驱动的商业世界中&#xff0c;能够快速处理和分析大量数据的能力变得越来越重要。而存内计算开发环境在此领域发挥其关键作用。存内计算环境利用内存&#xff08;RAM&#xff09;而非传统的磁盘存储来加速数据处理&#xff0c;提供了一个高效和灵活的平台。这种环境的…

SpringCloud--Sentinel使用

一、快速开始 Sentinel 的使用可以分为两个部分&#xff1a; 核心库&#xff08;Java 客户端&#xff09;&#xff1a;不依赖任何框架/库&#xff0c;能够运行于 Java 8 及以上的版本的运行时环境&#xff0c;同时对 Dubbo / Spring Cloud 等框架也有较好的支持。控制台&…

重构、重构、不小心把截图弄掉了,又要重新⏲

这里卡了一天的命令行了&#xff0c;都是vue,react的&#xff0c;也是服了。 参考文章&#xff0c;vue的响应式&#xff0c;以下是链接 https://blog.csdn.net/jieyucx/article/details/134534625 #mermaid-svg-H5Ltjf334Cx7lPuR {font-family:"trebuchet ms",verda…

HarmonyOS通过 axios发送HTTP请求

我之前的文章 HarmonyOS 发送http网络请求 那么今天 我们就来说说axios 这个第三方工具 想必所有的前端开发者都不会陌生 axios 本身也属于 HTTP请求 所以鸿蒙开发中也支持它 但首先 想在HarmonyOS中 使用第三方工具库 就要先下载安装 ohpm 具体可以参考我的文章 HarmonyOS 下…

IntelliJ IDEA 2020.2.4试用方法

打开idea&#xff0c;准备好ide-eval-resetter压缩包。 将准备好的压缩包拖入idea中 选中弹窗中的自动重置选项&#xff0c;并点击重置 查看免费试用时长

rabbitmq基础(1)

1、背景 能实现消息队列的框架软件有很多&#xff0c;kafka、rabbitmq、RocketMq、activeMq、Redis&#xff08;非专业&#xff09;&#xff0c;各有各的特点和优缺点。但是之前的公司数据需求规模并非很大&#xff0c;所以采用rabbitmq作为消息队列。 2、rabbitMq的基础架构…

结构体嵌套

在C或C编程中&#xff0c;结构体嵌套是指一个结构体内部包含了另一个结构体的实例作为其成员。 // 结构体嵌套.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 #define _CRT_SECURE_NO_WARNINGS#include <iostream>// 定义一个地址结构体 type…

矩阵爆破逆向-条件断点的妙用

不知道你是否使用过IDA的条件断点呢&#xff1f;在IDA进阶使用中&#xff0c;它的很多功能都有大作用&#xff0c;比如&#xff1a;ida-trace来跟踪调用流程。同时IDA的断点功能也十分强大&#xff0c;配合IDA-python的输出语句能够大杀特杀&#xff01; 那么本文就介绍一下这…

SpringBoot集成flink

Flink是一个批处理和流处理结合的统一计算框架&#xff0c;其核心是一个提供了数据分发以及并行化计算的流数据处理引擎。 最大亮点是流处理&#xff0c;最适合的应用场景是低时延的数据处理。 场景&#xff1a;高并发pipeline处理数据&#xff0c;时延毫秒级&#xff0c;且兼具…

【Python】新手入门(2):避免将关键字作为标识符

Python新手入门&#xff08;2&#xff09;&#xff1a;避免将关键字作为标识符 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1…