# mybatis-plugs **Repository Path**: bitcarton/mybatis-plugs ## Basic Information - **Project Name**: mybatis-plugs - **Description**: 一个简单的,高性能的,易学的mybatis增强框架 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: springboot3 - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 30 - **Forks**: 9 - **Created**: 2019-06-13 - **Last Updated**: 2025-09-01 ## Categories & Tags **Categories**: database-dev **Tags**: MyBatis, mybatis-plugs, mybatis增强工具, 简化mybatis增删改查, 数据库持久化框架 ## README

Mybatis-plugs

🍑 A mybatis tool that simplifys code

👉 https://gitee.com/wdyun/mybatis-plugs 👈

👉 mybatis-plugs 👈

Maven Central


[**🌎English Documentation**](README.en.md) ### 📚简介 mybatis-plugs是基于mybatis开发的一款增强的持久层框架。 只需在springboot项目中引入依赖mybatis-plugs-spring-boot-starter 即可实现mybatis的CRUD简化操作,不用在书写基本的增删改查sql ## 🍺目的 mybatis-plugs为简化代码,提高效率而生! ## 🐮特性 - 不对mybatis做任何修改 只做mybatis的扩展增强。 - 代码自动生成,根据表名可快速生成xxxMapper.java、xxxService.java、xxxServiceImpl.java、xxxController.java、xxxMapper.xml。 - 依赖少,仅仅依赖 mybatis-plugs-spring-boot-starter - 自动填充创建时间,更新时间,创建人等信息。 - 内置基于Mybatis物理分页的分页插件。 - 自动记录sql执行的时间,方便定位慢查询。 - 代码简洁,方便理解。 - 内置接口拦截器,通过注解确定是否拦截请求。 - 支持通过注解实现逻辑删除。 ## 📦快速开始 我们将通过一个简单的 Demo 来阐述 MyBatis-Plugs 的强大功能,在此之前,我们假设您已经: a.拥有 Java 开发环境、相应 IDE以及mysql数据库 b.熟悉 Spring Boot c.熟悉 Maven 如果从零开始用 MyBatis-Plugs来实现该表的增删改查我们需要做什么呢? 👉 1.创建表 现有一张 sys_user 表,其对应的数据库 Sql 脚本如下: ``` CREATE TABLE sys_user ( id bigint NOT NULL COMMENT '主键ID', name varchar(30) COMMENT '姓名', age int COMMENT '年龄', phone varchar(11) COMMENT '电话', PRIMARY KEY (id) ) ``` 👉 2.创建springboot项目 使用 idea 创建SpringBoot项目 第一步: ![Image text](p1.png) 第二步: ![Image text](p2.png) 第三步:选择LomBok插件 ![Image text](p3.png) 项目基本结构 ![Image text](p4.png) 👉 3.配置Maven 在项目的pom.xml文件中加入mybatis-plugs的Maven依赖:mybatis-plugs-spring-boot-starter 最新版本:Maven Central ```xml com.enbatis mybatis-plugs-spring-boot-starter 最新版本 ``` 👉4.配置yml 修改 application.properties为application.yml 新增 开发环境: application-dev.yml 新增 测试环境: application-test.yml 新增 生产环境: application-pro.yml 小说明 1.开发环境为我们进行开发所使用的配置 2.测试环境为测试人员进行软件测试所使用的配置 3.生产环境为上线部署所使用的配置 application.yml中配置为: ``` spring: profiles: active: dev server: port: 8080 ``` tips: ``` spring: profiles: active: dev ``` 指定所使用的环境 ``` server: port: 8080 ``` 指定项目所启动的端口为8080端口 application-dev.yml内容如下: ``` mybatis: mapper-locations: classpath:/mapping/*.xml type-aliases-package: com.panpan.housesale.entity configuration: map-underscore-to-camel-case: true spring: datasource: type: com.alibaba.druid.pool.DruidDataSource url: jdbc:mysql://127.0.0.1:3306/test_db?useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai username: root password: 111111 driver-class-name: com.mysql.cj.jdbc.Driver filters: stat,wall initialSize: 5 minIdle: 5 maxActive: 20 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: SELECT 1 FROM DUAL testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入 #如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority #则导入 log4j 依赖即可,Maven 地址: https://mvnrepository.com/artifact/log4j/log4j maxPoolPreparedStatementPerConnectionSize: 20 useGlobalDataSourceStat: true connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500 ``` 👉5.修改启动类 在启动类上加上Mapper扫描的注解 ``` @MapperScan("com.xxxxx.xxxxx.mapper") ``` ## 🍊代码生成器 我们通过数据库表可以快速生成entity,controller,mapper,service,serviceImpl,mapping.xml 生成代码需要连接数据库,所以我们需要进行数据库的连接,只需要通过配置数据库基本信息,利用mybatis-plugs的代码生成类 CodeBuilder 即可 👉1.配置代码生成器 在启动类的同级目录下,建立生成器类 CodeGenerate ``` import com.bitcarton.mybatisplugs.core.generate.CodeBuilder; import com.bitcarton.mybatisplugs.core.generate.template.GeneratorTemplate; public static void main(String[] args) { String url="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai"; String user="root"; String psd="123456"; String driver="com.mysql.cj.jdbc.Driver"; String filePath="D://generate_code//"; String basePackName="org.example"; GeneratorTemplate build = new CodeBuilder(url,driver). setBasePackName(basePackName). setUser(user). setPassword(psd). setFilePath(filePath) .build(); build.generate(CodeTest.class); } ``` 注释: url: 数据库连接url root: 数据库用户名 psd: 数据库密码 filePath: java代码生成位置(防止代码覆盖所以我们不会自动生成到对应的代码位置) CodeGenerator2: mybatis-plugs代码核心生成器 👉2.使用方法 1.执行main方法 2.在控制台输入作者以及要生成代码的表 ![Image text](pp1.png) 3.输入完成之后点击回车 4.当输出以下信息表示代码生成成功 ![Image text](pp2.png) 5.去代码生成的位置查看生成的代码 ![Image text](pp3.png) 👉3.建立代码包 建立代码包:entity、controller、mapper、service、impl以及xml的文件夹 ![Image text](pp4.png) 👉4.复制代码 将生成的代码复制到对应的文件夹 ![Image text](pp5.png) 👉5.启动项目 启动项目 访问 http://localhost:8080/v1/sys_user/list 查询所有用户列表 ## 🐮CRUD 接口 说明:通过封装mybatis的 BaseService接口即可快速实现数据库的CRUD操作 泛型 T 为任意实体对象;参数 Serializable 为任意类型主键 Mybatis-Plugs 不推荐使用复合主键约定每一张表都有自己的唯一 id 主键;对象 Wrapper 为 条件构造器。 1.插入接口 1.1单条插入 ``` /** * 插入一条记录 * @param entity 传入的插入对象 * @return T */ T insert(T entity); ``` 使用方法:在serviceImpl层写代码示例如下 ``` SysUser user = new SysUser(); user.setName("张三"); user.setAge(32); user.setPhone("13615425135"); super.insert(user); ``` 1.2批量插入 ``` /** * 批量插入 * @param entityList * @return */ int saveBatch(List entityList); ``` 使用方法:在serviceImpl层写代码示例如下 ``` List sysUserList = new ArrayList<>(); for (int i = 0; i <10 ; i++) { SysUser sysUser = new SysUser(); sysUser.setName("张三"+i); sysUser.setAge(30+i); sysUser.setPhone("1361542513"+i); sysUserList.add(sysUser); } super.saveBatch(sysUserList); ``` 2.删除接口 2.1单个删除 ``` /** * 根据id删除一条数据 * @param id 传入的查询ID * @return 删除条数 */ int deleteById(Serializable id); ``` 使用方式:在serviceImpl层写代码示例如下 ``` super.deleteById(12000012); ``` 2.2批量删除 ``` /** * 批量删除 * @param queryWrapper * @return */ int delete(Wrapper queryWrapper); ``` 使用方式:在serviceImpl层写代码示例如下 ``` Wrapper queryWrapper = new Wrapper(); queryWrapper.eq("age",30); queryWrapper.like("name","张三"); super.delete(queryWrapper); ``` 说明:关于条件构造器会专门讲解。 3 修改接口 3.1单个修改 ``` /** * 根据id更新一条数据 * @param bean 传入的更新对象 * @return 返回更新条数 */ int updateById(T bean); ``` 使用方式:在serviceImpl层写代码示例如下 ``` SysUser sysUser = new SysUser(); sysUser.setId(1234561114L); sysUser.setPhone("13615425135"); sysUser.setAge(36); super.updateById(sysUser); ``` 3.2批量修改 ``` /** * 批量修改 * @param entityList * @return */ int updateBatchById(List entityList); ``` 使用方式:在serviceImpl层写代码示例如下 ``` List sysUserList = new ArrayList<>(); SysUser sysUser = new SysUser(); sysUser.setId(111100001101L); sysUser.setAge(35); sysUserList.add(sysUser); SysUser sysUser2 = new SysUser(); sysUser2.setId(111100001102L); sysUser2.setAge(32); sysUserList.add(sysUser); super.updateBatchById(sysUserList); ``` 4.列表查询接口 ``` /** * 查询列表数据 * @param queryWrapper 查询条件 * @return 集合 */ List list(Wrapper queryWrapper); ``` 使用方式:在serviceImpl层写代码示例如下 ``` Wrapper queryWrapper = new Wrapper(); queryWrapper.like("name","张三"); List list = super.list(queryWrapper); ``` 5.分页查询 ``` /** * 分页查询 * @param page * @param queryWrapper * @return */ Page page(Page page, Wrapper queryWrapper); ``` 使用方式:在controller层写代码示例如下 ``` @PostMapping("/page") public ResultReturn> getPage(@RequestBody SysUser user){ return success(sysUserService.page( getPage(),new Wrapper(user))); } ``` 说明:controller需要继承BaseController 6查询单条 ``` /** * 根据id获取 * @param id 对象ID * @return 对象 */ T getById(Serializable id); ``` 使用方式:在controller层写代码示例如下 ``` @GetMapping("/{id}") public ResultReturn get(@PathVariable("id") Long id) { return success(sysUserService.getById(id)); } ``` 7.查询数量 ``` /** * 查询count * @param queryWrapper 查询条件 * @return 数量 */ int selectCount(Wrapper queryWrapper); ``` 使用方式:在serviceImpl层写代码示例如下 ``` Wrapper queryWrapper = new Wrapper(); queryWrapper.like("name","张三"); int count = super.selectCount(queryWrapper); ``` ## 🐮 条件构造器Wrapper 1 eq构造 如果我们想快速查询数据库表sys_user 的姓名为 “Tom” 如何进行操作呢? 回答:只需service调用list 传入 条件构造器Wrapper Wrapper调用 eq 方法,下面的方法即为 查询姓名是Tom的SysUser列表 ``` sysUserService.list(new Wrapper<>(sysUser).eq("name","Tom")); ``` 2 ne构造 如果我们想快速查询数据库表sys_user 的姓名不是 “Tom” 如何进行操作呢? 回答:只需service调用list 传入 条件构造器Wrapper Wrapper调用 ne 方法,下面的方法即为 查询姓名不是Tom的SysUser列表 ``` sysUserService.list(new Wrapper<>(sysUser).ne("name","Tom")); ``` 3 like构造 如果我们想根据姓名模糊查询,怎么操作呢? 回答:只需service调用list 传入 条件构造器Wrapper Wrapper调用 like 方法,下面的方法即为 根据姓名“Tom”模糊查询 ``` sysUserService.list(new Wrapper<>(sysUser).like("name","Tom")); ``` 4 in构造 如果我们想查询姓名是“Tom”,“Jack”,“June”怎么操作呢? 回答:只需service调用list 传入 条件构造器Wrapper Wrapper调用 in 方法,传入ArrayList即可 ``` List arrayList=new ArrayList<>();  arrayList.add("Tom");  arrayList.add("Jack");  arrayList.add("June"); sysUserService.list(new Wrapper<>(sysUser).in("name",arrayList)); ``` 扩展: 以上只列出部分条件构造器的方法,我们还有notNull(非空查询)、isNull(空值查询)、setSqlSelect(固定列查询)等等, 更多请查看 mybatis-plugs ## 🐮 登录认证 Mybatis-Plugs内部封装了JWT token认证,做登录功能时可直接进行使用。 1.创建JWT Mybatis-Plugs提供了JwtUtil工具类来进行token的创建,具体的方法来介绍下: ``` /** * 前三个参数为自己用户token的一些信息比如id,权限,名称等。不要将隐私信息放入(大家都可以获取到) * @param map 需要加密的信息 * @param security 加密字符串 * @param expire 失效时间 毫秒 * @return */ public static String createJwt(Map map,String security,long expire) { //添加构成JWT的参数 JwtBuilder builder = Jwts.builder() .setHeaderParam("typ", "JWT") .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis()+expire)) .setClaims(map) .signWith(generalKey(security),SignatureAlgorithm.HS256); //生成JWT return builder.compact(); } ``` 如果不传失效时间会默认24小时,我们提供了一个重载的方法 ``` /** * 创建JWT 默认失效时间是24小时 * @param map 需要加密的信息 * @param base64Security 加密字符串 * @return */ public static String createJwt(Map map, String base64Security) { return createJwt(map,base64Security,EXPIRE); } ``` 具体如何使用?请参照一下代码: ``` //获取登录用户名 String username =user.getUsername(); String password= MD5Util.generate(user.getPassword()); List list=list(new Wrapper().eq("username",username).eq("password",password)); Optional first= list.stream().filter(dbUser->dbUser.getUsername().equals(username)&&dbUser.getPassword().equals(password)).findFirst(); if (first.isPresent()){ user.setUsername(username); SysUser sysUser= first.get(); Map userMap = new HashMap<>(); userMap.put("userId",sysUser.getId()+""); userMap.put("name",sysUser.getName()); userMap.put("companyId",sysUser.getCompanyId()); userMap.put("username",sysUser.getUsername()); userMap.put("effective", System.currentTimeMillis()+(120*60*1000)); String token= JwtUtil.createJwt(userMap, JwtUtil.LOGIN_BASE); response.addHeader("authorization",token); Cookie cookie = new Cookie("authorization",token); cookie.setDomain(domain); cookie.setPath("/"); response.addCookie(cookie); SysUser user1= first.get(); SysUserVO vo = new SysUserVO(); BeanUtils.copyProperties(user1,vo); vo.setAuthorization(token); vo.setImgHead(sysUser.getAvatarUrl()); return ResultReturn.success(vo); } ``` 2.解析JWT Mybatis-Plugs提供了JwtUtil工具类来进行token的解析,具体的方法来介绍下: ``` /** * 解密 * @param jsonWebToken token字符串 * @param security 加密字符串 * @return */ public static Claims parseJwt(String jsonWebToken, String security) { try { Jws claimsJws = Jwts.parserBuilder() .setSigningKey(Keys.hmacShaKeyFor(security.getBytes(StandardCharsets.UTF_8))) .build().parseClaimsJws(jsonWebToken); return claimsJws.getBody(); } catch (Exception ex) { ex.printStackTrace(); return null; } } ``` 3.封装登录实体 登录成功之后,可以用token获取到登录实体Account,用来获取登录用户,具体方法如下: ``` public static Account account(String token,String security){ Claims claims= JwtUtil.parseJwt(token,security); String userId= (String)claims.get("userId"); String username= (String)claims.get("username"); Integer companyId= (Integer)claims.get("companyId"); Account account = new Account(); account.setId(Long.parseLong(userId)); account.setUsername(username); if(null!=companyId){ account.setCompanyId(Long.parseLong(Integer.toString(companyId))); } return account; } ``` 其中token是jwt生成的token,security为加密字符串,token可以从head或者cookie里面获取。 具体的使用方式见如下代码: ``` Account account = JwtUtil.account(request.getHeader("Authorization"),"xxxx"); ``` ## 🐮 拦截器 1.介绍 Mybatis-plugs的拦截器有记录请求方法执行时间、过滤非登录用户请求的功能,在controller里面使用注解即可拦截未登录请求。 使用方法:自定义拦截器并继承类:com.bitcarton.mybatisplugs.commons.Interceptor.Interceptor 实例代码如下: ``` @Component public class ReqInterceptor extends Interceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{ return super.preHandle(request,response,handler); } } ``` 接下来是注册拦截器,新建类WebConfigurer 并实现WebMvcConfigurer接口,代码如下: ``` @Configuration public class WebConfigurer implements WebMvcConfigurer { @Autowired private ReqInterceptor interceptor; /** * @Description 这个方法是用来配置静态资源的,比如html,js,css,等等 * @Param [registry] * @return void **/ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { } /** * @Description 这个方法用来注册拦截器,我们自己写好的拦截器需要通过这里添加注册才能生效 * @Date 9:34 2022/2/7 * @Param [registry] * @return void **/ @Override public void addInterceptors(InterceptorRegistry registry) { // addPathPatterns("/**") 表示拦截所有的请求, registry.addInterceptor(interceptor).addPathPatterns("/**"); } } ``` 配置完成即可实现Mybatis-Plugs拦截器的功能。 2.拦截请求 Controller方法不加任何注解或者加注解 @Login(handler = Handler.INTERCEPT)即可起到拦截请求的功能,如果用户未登录就访问接口,系统会抛出未登录的信息。 3.放行请求 有一部分请求是不需要登录就直接能访问的,比如说注册接口,登录接口等等,这时候使用注解@Login(handler = Handler.PASS)即可放行请求,即不需要登录即可访问,代码示例如下: 注册接口: ``` @Login(handler = Handler.PASS) @PostMapping("/register") public ResultReturn registerUser(@RequestBody SysUserVO sysUser){ sysUser.setCompanyId(0L); return sysUserService.registerUser(sysUser); } ``` 登录接口: ``` @Login(handler = Handler.PASS) @PostMapping("/login") public ResultReturn login(@RequestBody SysUserVO vo){ return sysUserService.login(vo,request,response); } ``` ## 🐮 枚举转换 有时候数据库里面存的是数字类型,但是在实体类里面我们要使用枚举类,这种情况Mybatils-Plugs提供了比较方便快捷的方式来实现需求。 1.定义枚举类 先自定义枚举类并实现com.bitcarton.mybatisplugs.core.enums.BaseEnum接口,代码如下: ``` import com.bitcarton.mybatisplugs.core.enums.BaseEnum; public enum StatusEnum implements BaseEnum { ORDERED(0,"已下单"), PAYED(1,"已付款"), DELIVER(2,"代发货"), DELIVERED(3,"已发货"), RECEIVED(4,"已收货"), OK(5,"订单完成"); private final Integer value; private final String description; StatusEnum(Integer value, String description) { this.value = value; this.description = description; } public StatusEnum getEnumByValue(Long value) { StatusEnum[] enums = StatusEnum.values(); for (StatusEnum e : enums) { if (e.getValue().equals(value)) { return e; } } return null; } @Override public Integer getValue() { return value; } @Override public String getDescription() { return description; } } ``` 2.实体类引用枚举 需要在实体类里面将字段更改为枚举类型,如下: ``` /** * 订单状态( */ private StatusEnum status; ``` 3.增加配置文件 需要在配置文件里面添加对枚举转换的类:com.bitcarton.mybatisplugs.core.plugin.parser .AutoEnumTypeHandler 代码如下: ``` mybatis: mapper-locations: classpath:/mapping/*.xml type-aliases-package: com.panpan.housesale.entity configuration: map-underscore-to-camel-case: true #log-impl: org.apache.ibatis.logging.stdout.StdOutImpl default-enum-type-handler: com.bitcarton.mybatisplugs.core.plugin.parser.AutoEnumTypeHandler ``` 通过这三个步骤的操作,就可以实现,数据库字段类型与枚举类型的匹配。 ## 🍺捐赠 如果觉得还不错,请作者喝杯咖啡吧 微信支持 ![Image text](f1.jpg) 支付宝扫一扫支持 ![Image text](f2.jpg)