集成方式
引入依赖,MyBatisPlus依赖了MyBatis,所以MyBatis不用引入了
最新版本可到官网Github仓库查看,可搭配mybatis-plus-join使用,关联查询更方便
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>Latest Version</version>
</dependency>
配置
mybatis-plus:
configuration:
# 链接超时时间
default-statement-timeout: 15
# 开启驼峰命名规则映射(用于数据返回映射到实体类)
map-underscore-to-camel-case: true
# xml路径
mapper-locations: classpath:mapper/*.xml
记得在启动类上指定扫描包
@MapperScan("com.example.mapper")
将Mapper类都继承BaseMapper
并指定实体类
public interface UserMapper extends BaseMapper<User> {
}
然后该Mapper就有了很多基础查询的方法
实体类注解
import com.baomidou.mybatisplus.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@TableName("user")
public class User {
/**
* ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 姓名
*/
@TableField(value = "name")
private String name;
/**
* 年龄
*/
@TableField(value = "age")
private Integer age;
/**
* 性别:0-男,1-女
*/
@TableField(value = "sex")
private Integer sex;
/**
* 创建时间
*/
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Date createTime;
/**
* 更新时间
*/
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
/**
* 性别:男
*/
public static final int SEX_MAN = 0;
/**
* 性别:女
*/
public static final int SEX_WOMAN = 1;
/**
* 性别显示,数据表中不存在
*/
@TableField(exist = false)
private String sexName;
/**
* 通过Get处理性别的显示
*/
public String getSexName() {
if (sex == null) {
return "不明";
} else if (sex == 0) {
return "男";
} else if (sex == 1) {
return "女";
}
return "不明";
}
}
注意:实体类中不要使用基本数据类型,会自动填充,例如使用了int
类型字段,在updateById
时会更新该字段为0,只有为null
的字段才不会更新
IDEA插件
MybatisX
是苞米豆提供了一款全免费且强大的IDEA插件,支持跳转,自动补全生成SQL,代码生成
查看SQL日志
只需要将输入日志的级别调整到debug
即可
# 日志级别
logging:
level:
com.example: debug
主键策略
通过@TableId(value = "id", type = IdType.AUTO)
中的IdType
可以指定ID的生成策略
类型 | 说明 |
---|---|
AUTO | 数据库ID自增 |
NONE | 无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于INPUT) |
INPUT | insert前自行set主键值 |
ASSIGN_ID | 分配ID(主键类型为Number(Long和Integer)或String)(since 3.3.0),使用接口IdentifierGenerator的方法nextId(默认实现类为DefaultIdentifierGenerator雪花算法) |
ASSIGN_UUID | 分配UUID,主键类型为String(since 3.3.0),使用接口IdentifierGenerator的方法nextUUID(默认default方法) |
简单CRUD
/**
* 添加
*/
@Test
void insert() {
User user = User.builder()
.name("张三")
.age(20)
.createTime(new Date())
.build();
int row = userMapper.insert(user);
// 可以直接获取到插入成功后的主键
System.out.println(user.getId());
}
/**
* 修改
*/
@Test
void update() {
User user = User.builder()
.id(1L)
.name("李四")
.age(21)
.updateTime(new Date())
.build();
int row = userMapper.updateById(user);
System.out.println(row);
}
/**
* 删除
*/
@Test
void delete() {
int row = userMapper.deleteById(3);
System.out.println(row);
}
/**
* 查询
*/
@Test
void query() {
// 根据ID查询
User user = userMapper.selectById(1L);
System.out.println(user);
// 根据Map条件查询List
Map<String, Object> userMap = new HashMap<>();
userMap.put("age", 20);
List<User> users = userMapper.selectByMap(userMap);
System.out.println(users);
}
Service CRUD接口
MyBatisPlus提供了很多Service层的通用接口,文档说明
接口定义
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.entity.User;
/**
* User Service
* 需要通过泛型指定要操作的实体类
*/
public interface UserService extends IService<User> {
// 这里写自己定义的方法
}
实现接口
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.entity.User;
import com.example.mapper.UserMapper;
import com.example.service.UserService;
import org.springframework.stereotype.Service;
/**
* 继承通用ServiceImpl实现,并指定要操作的实体类
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
// 实现自己写方法
}
mapper继承
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.fan.entity.Users;
public interface UserMapper extends BaseMapper<Users> {
}
使用方法,需要注意的是,MyBatisPlus在Mapper命名采用的是SQL关键字方式,而Service层采用的是get
,save
等方式
/**
* 添加
*/
@Test
void save() {
User user = User.builder()
.name("王五")
.age(18)
.createTime(new Date())
.build();
boolean save = userService.save(user);
System.out.println("操作状态:" + save + ",ID:" + user.getId());
}
/**
* 修改
*/
@Test
void saveOrUpdate() {
User user = User.builder()
.id(6L)
.name("王五")
.age(24)
.createTime(new Date())
.build();
// 根据ID先查询再更新,如果没有ID直接插入
boolean save = userService.saveOrUpdate(user);
System.out.println("操作状态:" + save + ",ID:" + user.getId());
}
分页插件
分页的使用需要先配置分页插件,已内置,需要开启
// 最新版
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
示例
/**
* 分页
*/
public Result<List<Question>> list(@RequestBody @Valid QuestionListReqVo params) {
// 查询条件
QueryWrapper<Question> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(Question::getType, params.getType());
if (Objects.nonNull(params.getCateId())) {
wrapper.lambda().eq(Question::getCateId, params.getCateId());
}
if (StringUtils.hasLength(params.getKeyword())) {
wrapper.lambda().like(Question::getTitle, params.getKeyword());
}
// 分页
Page<Question> page = new Page<>();
page.setSize(params.getPageSize());
page.setCurrent(params.getPageIndex());
Page<Question> pageObj = questionService.page(page, wrapper);
// 列表
List<Question> list = pageObj.getRecords();
// 当前页
long current = pageObj.getCurrent();
// 页大小
long size = pageObj.getSize();
// 总页数
long pages = pageObj.getPages();
return Result.data(list);
}
注意:Page
的index
从1开始
Wapper
在所以需要Wapper的地方都可以,实现更为复杂的操作
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
// 可指定查询的字段
queryWrapper.select("id","name")
// 添加控制
.eq("name", "张三");
// Lambda方式
queryWrapper.lambda()
.select(User::getId, User::getName)
.eq(User::getName, "张三");
List<User> users = userService.list(queryWrapper);
System.out.println(users);
LambdaQueryWrapper
都能以Lambda形式操作,再写字符字段,推荐
LambdaQueryWrapper<Busmanager> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Busmanager::getState, 0);
queryWrapper.eq(Busmanager::getSmsType, 1);
List<Busmanager> list = busmanagerService.list(queryWrapper);
自动填充
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/**
* 更新时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
需要配置
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* 自动填充
*/
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("开始插入填充...");
this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
this.strictInsertFill(metaObject, "updateTime", Date.class, new Date());
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "updateTime", Date.class, new Date());
}
}
注意填充类型,官方示例是字符类型,可根据自己的填充类型修改
逻辑删除
https://baomidou.com/guides/logic-delete/
or语句
wrapper.like(Article::getName, params.getKeyword())
.or()
.like(Article::getContent, params.getKeyword());