6 Star 30 Fork 10

一阵清风 / mybatis-plugs

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
README.md 21.22 KB
一键复制 编辑 原始数据 按行查看 历史
wdyun 提交于 2022-08-25 14:59 . readme修改3

Mybatis-plugs

🍑 A mybatis tool that simplifys code

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

👉 mybatis-plugs 👈

Maven Central


🌎English Documentation

📚简介

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 第二步:
Image text 第三步:选择LomBok插件
Image text 项目基本结构
Image text

👉 3.配置Maven

在项目的pom.xml文件中加入mybatis-plugs的Maven依赖:mybatis-plugs-spring-boot-starter

最新版本:Maven Central


<dependency>
  <groupId>com.enbatis</groupId>
  <artifactId>mybatis-plugs-spring-boot-starter</artifactId>
  <version>最新版本</version>
</dependency>

👉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的代码生成类 CodeGenerator2 即可

👉1.配置代码生成器
在启动类的同级目录下,建立生成器类 CodeGenerate

public class CodeGenerate { 
  private static String url="jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false"; 
   private static String user="root"; 
   private static String psd="111111"; 
   private static String filePath="D://generate_code//"; 
   public static void main(String[] args) { 
    CodeGenerator2 codeGenerator2=new CodeGenerator2(url,user,psd,filePath); 
    codeGenerator2.generate(CodeGenerate.class); 

注释:
url: 数据库连接url
root: 数据库用户名 psd: 数据库密码
filePath: java代码生成位置(防止代码覆盖所以我们不会自动生成到对应的代码位置)
CodeGenerator2: mybatis-plugs代码核心生成器

👉2.使用方法
1.执行main方法
2.在控制台输入作者以及要生成代码的表
Image text 3.输入完成之后点击回车
4.当输出以下信息表示代码生成成功
Image text 5.去代码生成的位置查看生成的代码
Image text 👉3.建立代码包
建立代码包:entity、controller、mapper、service、impl以及xml的文件夹
Image text 👉4.复制代码
将生成的代码复制到对应的文件夹
Image text

👉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<T> entityList);

使用方法:在serviceImpl层写代码示例如下

List<SysUser> 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 wrapper
 * @return
 */
int delete(Wrapper<T> wrapper);

使用方式:在serviceImpl层写代码示例如下

Wrapper wrapper = new Wrapper<SysUser>();
wrapper.eq("age",30);
wrapper.like("name","张三");
super.delete(wrapper);

说明:关于条件构造器会专门讲解。

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<T> entityList);

使用方式:在serviceImpl层写代码示例如下

List<SysUser> 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 wrapper 查询条件
 * @return 集合
 */
List<T> list(Wrapper<T> wrapper);

使用方式:在serviceImpl层写代码示例如下

Wrapper wrapper = new Wrapper<SysUser>();
wrapper.like("name","张三");
List<SysUser> list = super.list(wrapper);

5.分页查询

/**
 * 分页查询
 * @param page
 * @param wrapper
 * @return
 */
Page<T> page(Page<T> page, Wrapper<T> wrapper);

使用方式:在controller层写代码示例如下

@PostMapping("/page")
public ResultReturn<Page<SysUser>> 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<SysUser> get(@PathVariable("id") Long id) {
    return success(sysUserService.getById(id));
}

7.查询数量

/**
 * 查询count
 * @param wrapper 查询条件
 * @return 数量
 */
int selectCount(Wrapper<T> wrapper);

使用方式:在serviceImpl层写代码示例如下

Wrapper wrapper = new Wrapper<SysUser>();
wrapper.like("name","张三");
int count = super.selectCount(wrapper);

🐮 条件构造器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<String,Object> 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<String, Object> map, String base64Security) {
    return createJwt(map,base64Security,EXPIRE);
}

具体如何使用?请参照一下代码:

//获取登录用户名
String username =user.getUsername();
String password= MD5Util.generate(user.getPassword());
List<SysUser> list=list(new Wrapper().eq("username",username).eq("password",password));
Optional<SysUser> 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<String,Object> 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<Claims> 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.enbatis.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.enbatis.mybatisplugs.enums.BaseEnum接口,代码如下:

import com.enbatis.mybatisplugs.enums.BaseEnum;
public enum StatusEnum implements BaseEnum<StatusEnum,Integer> {
    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.enbatis.mybatisplugs.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.enbatis.mybatisplugs.plugin.parser.AutoEnumTypeHandler

通过这三个步骤的操作,就可以实现,数据库字段类型与枚举类型的匹配。

🍺捐赠

如果觉得还不错,请作者喝杯咖啡吧
微信支持
Image text

支付宝扫一扫支持

Image text

Java
1
https://gitee.com/wdyun/mybatis-plugs.git
git@gitee.com:wdyun/mybatis-plugs.git
wdyun
mybatis-plugs
mybatis-plugs
dev

搜索帮助