Mybatis-Plugs为简化代码而生
mybatis增强工具包
[enbatis]
[Mybatis-Plugs]
[2022年8月]
[一阵清风]
目录
1. 介绍 1
1.1简介 1
1.2目的 1
1.3特性 1
2. 快速开始 1
2.1创建表 1
2.2 创建springboot项目 1
2.3配置maven 3
2.4配置yml 4
2.4修改启动类 5
3. 代码生成器 5
3.1配置代码生成器 5
3.2使用方法 6
3.3建立代码包 7
3.4复制代码 8
3.5启动项目 8
4. CRUD 接口 8
4.1插入接口 9
4.1.1单条插入 9
4.1.2批量插入 9
4.2删除接口 10
4.2.1单个删除 10
4.2.2批量删除 11
4.3 修改接口 11
4.3.1单个修改 11
4.3.2批量修改 12
4.4列表查询接口 13
4.5分页查询 14
4.6查询单条 15
4.7查询数量 15
5. 条件构造器Wrapper 16
5.1 eq构造 16
5.2 ne构造 16
5.3 like构造 16
5.4 in构造 17
6. 登录认证 17
6.1创建JWT 17
6.2解析JWT 20
6.3封装登录实体 21
7. 拦截器 21
7.1介绍 21
7.2拦截请求 23
7.3放行请求 23
8. 枚举转换 24
8.1定义枚举类 24
8.2实体类引用枚举 26
8.3增加配置文件 26
Mybatis-Plugs
介绍
1.1简介
Mybatis-plugs是基于mybatis开发的一款增强的持久层框架。
只需在springboot项目中引入依赖mybatis-plugs-spring-boot-starter
即可实现mybatis的CRUD简化操作,不用在书写基本的增删改查sql。
1.2目的
Mybatis-plugs为简化代码而生。
1.3特性
不对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来实现该表的增删改查我们需要做什么呢?
2.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.2 创建springboot项目
使用 idea 创建SpringBoot项目
第一步:
第二步:
第三步:选择LomBok插件
项目基本结构
2.3配置maven
springBoot项目建立好之后,在pom.xml文件加入mybatis-plugs的依赖
mybatis-plugs-spring-boot-starter
当前最新版本 mybatis-plugs-spring-boot-starter
com.enbatis
mybatis-plugs-spring-boot-starter
当前最新版本
小提示:
引入 mybatis-plugs-spring-boot-starter 之后无需再次引入mybatis
2.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
指定所使用的环境
port:8080
指定项目所启动的端口为8080端口
application-dev.yml
2.4修改启动类
在启动类上加上Mapper扫描的注解
@MapperScan("com.xxxxx.xxxxx.mapper")
3. 代码生成器
我们通过数据库表可以快速生成
entity,controller,mapper,service,serviceImpl,mapping.xml
生成代码需要连接数据库,所以我们需要进行数据库的连接,只需要通过配置数据库基本信息,利用mybatis-plugs的代码生成类 CodeGenerator2 即可
3.1配置代码生成器
在启动类的同级目录下,建立生成器类 CodeGenerate
import com.enbatis.mybatisplugs.generate.CodeGenerator2;
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代码核心生成器
3.2使用方法
执行main方法
在控制台输入作者 以及 要生成代码的表
输入完成之后点击回车
当输出以下信息表示代码生成成功
去代码生成的位置查看生成的代码
3.3建立代码包
建立代码包:entity、controller、mapper、service、impl以及xml的文件夹
3.4复制代码
将生成的代码复制到对应的文件夹
3.5启动项目
启动项目 访问 http://localhost:8080/v1/sys_user/list 查询所有用户列表
4. CRUD 接口
说明:通过封装mybatis的 BaseService接口即可快速实现数据库的CRUD操作
泛型 T 为任意实体对象;参数 Serializable 为任意类型主键 Mybatis-Plugs 不推荐使用复合主键约定每一张表都有自己的唯一 id 主键;对象 Wrapper 为 条件构造器。
4.1插入接口
4.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);
4.1.2批量插入
/**
* 批量插入
* @param entityList
* @return
*/
int saveBatch(List
使用方法:在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);
4.2删除接口
4.2.1单个删除
/**
* 根据id删除一条数据
* @param id 传入的查询ID
* @return 删除条数
*/
int deleteById(Serializable id);
使用方式:在serviceImpl层写代码示例如下
super.deleteById(12000012);
4.2.2批量删除
/**
* 批量删除
* @param wrapper
* @return
*/
int delete(Wrapper
使用方式:在serviceImpl层写代码示例如下
Wrapper wrapper = new Wrapper
(); wrapper.eq("age",30);
wrapper.like("name","张三");
super.delete(wrapper);
说明:关于条件构造器会专门讲解。
4.3 修改接口
4.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);
4.3.2批量修改
/**
* 批量修改
* @param entityList
* @return
*/
int updateBatchById(List
使用方式:在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.4列表查询接口
/**
* 查询列表数据
* @param wrapper 查询条件
* @return 集合
*/
List
使用方式:在serviceImpl层写代码示例如下
Wrapper wrapper = new Wrapper
(); wrapper.like("name","张三");
List
list = super.list(wrapper);
4.5分页查询
/**
* 分页查询
* @param page
* @param wrapper
* @return
*/
Page
使用方式:在controller层写代码示例如下
@PostMapping("/page")
public ResultReturn
> getPage(@RequestBody SysUser user){ return success(sysUserService.page( getPage(),new Wrapper(user)));
}
说明:controller需要继承BaseController
4.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));
}
4.7查询数量
/**
* 查询count
* @param wrapper 查询条件
* @return 数量
*/
int selectCount(Wrapper
使用方式:在serviceImpl层写代码示例如下
Wrapper wrapper = new Wrapper
(); wrapper.like("name","张三");
int count = super.selectCount(wrapper);
5. 条件构造器Wrapper
如果我们想快速查询数据库表sys_user 的姓名为 “Tom” 如何进行操作呢?
回答:只需service调用list 传入 条件构造器Wrapper Wrapper调用 eq 方法,下面的方法即为 查询姓名是Tom的SysUser列表
sysUserService.list(new Wrapper<>(sysUser).eq("name","Tom"));
如果我们想快速查询数据库表sys_user 的姓名不是 “Tom” 如何进行操作呢?
回答:只需service调用list 传入 条件构造器Wrapper Wrapper调用 ne 方法,下面的方法即为 查询姓名不是Tom的SysUser列表
sysUserService.list(new Wrapper<>(sysUser).ne("name","Tom"));
如果我们想根据姓名模糊查询,怎么操作呢?
回答:只需service调用list 传入 条件构造器Wrapper Wrapper调用 like 方法,下面的方法即为 根据姓名“Tom”模糊查询
sysUserService.list(new Wrapper<>(sysUser).like("name","Tom"));
如果我们想查询姓名是“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
6. 登录认证
Mybatis-Plugs内部封装了JWT token认证,做登录功能时可直接进行使用。
6.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);
}
6.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;
}
}
6.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");
7. 拦截器
7.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拦截器的功能。
7.2拦截请求
Controller方法不加任何注解或者加注解 @Login(handler = Handler.INTERCEPT)即可起到拦截请求的功能,如果用户未登录就访问接口,系统会抛出未登录的信息。
7.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);
}
8. 枚举转换
有时候数据库里面存的是数字类型,但是在实体类里面我们要使用枚举类,这种情况Mybatils-Plugs提供了比较方便快捷的方式来实现需求。
8.1定义枚举类
先自定义枚举类并实现com.enbatis.mybatisplugs.enums.BaseEnum接口,代码如下:
import com.enbatis.mybatisplugs.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;
}
}
8.2实体类引用枚举
需要在实体类里面将字段更改为枚举类型,如下:
/**
* 订单状态(
*/
private StatusEnum status;
8.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
通过这三个步骤的操作,就可以实现,数据库字段类型与枚举类型的匹配。