Mybatis-plus介绍
mybatis-puls是对mybatis的增强,没有很大的改变,使用时感觉不到太大的变化,可以和springboot很好的整合使用,详情参考mybatis-plus官网,使用springboot整合mybatis-plus必须得导入以下依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
首先的创建出实体类,mybatis-plus注解使用可以参考mybatis-plus注解描述
@Data
@TableName("user")
public class User {
@TableId
private Long id;
@TableField("name")
private String name;
@TableField("age")
private Integer age;
@TableField("email")
private String email;
@TableField(fill = FieldFill.INSERT)// 配合mybatis-plus的自动填充功能,在插入时更新
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)// 配合mybatis-plus的自动填充功能,在插入时和修改时更新
private Date updateTime;
@Version // 配合mybatis-plus乐观锁使用
@TableField(fill = FieldFill.INSERT)
private Integer version;
@TableLogic // 配合mybatis的逻辑删除使用
private Boolean deleted;
}
mybatis-plus与springboot整合简单CRUD使用
创建一个简单的UserMapper类继承Mybatis-plus所封装的一个基础类
BaseMaper<T>
,泛型写当前所需要操作的实体类,BaseMapper封装了很多基础的CRUD方法基本能满足我们的的使用
public interface UserMapper extends BaseMapper<User> {
}
mybatis对相关的Service也进行了封装,Service接口继承
IService<T>
接口泛型写需要操作的相关实体,Service实现类继承ServiceImpl<M,T>
泛型写相关的Mapper接口和需要操作的实体,且实现本应该实现的Service接口进行操作,当前Service就可以使用简单的CRUD操作
/**
* UserService接口
*/
public interface UserService extends IService<User> {
}
/**
* UserServiceImpl实现类
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
还需要创建一个mybatis-plus的配置类在其中,使用@MapperScan注解扫描到mapper所在的地方,在其中可以注入相关的插件的bean供后续使用
@Configuration
@MapperScan("com.percent.bootmybatispuls.mapper")
public class MpConfig {
/**
* 乐观锁插件
*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
/**
* 分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
使用简单的CRUD查询
@Autowired
private UserService userService;
/**
* 查询出所有的数据
*/
@Test
void list() {
List<User> users = userService.list();
logger.info("users : {}",users);
}
/**
* 添加相关的数据
*/
@Test
void addUser() {
User user = new User();
user.setAge(10);
user.setEmail("1111111111@qq.com");
user.setName("zhangsan");
userService.save(user);
}
/**
* 多个id批量查询
*/
@Test
void selectBatchIds() {
List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
logger.info("users : {}",users);
}
/**
* 简单条件查询
*/
@Test
void selectByMap() {
Map<String, Object> columnMap = new HashMap<>();
columnMap.put("name", "Jack");
columnMap.put("age", 20);
List<User> users = userMapper.selectByMap(columnMap);
logger.info("users : {}",users);
}
/**
* 通过ID删除
*/
@Test
void deleteById(){
userService.removeById(1L);
}
/**
* 修改
*/
@Test
void update(){
User user = new User();
user.setId(1l);
user.setAge(10);
user.setEmail("1111111111@qq.com");
user.setName("zhangsan");
userService.updateById(user);
}
更多的简单操作可以看mybatis-plus IService封装相关方法或者是mybatis-plus BaseMapper封装相关方法
Mybatis-plus使用分页查询
必须得定义一个mybatis配置类在其中注入
PaginationInterceptor
分页插件
/**
* 分页查询
*/
@Test
public void testSelectPage() {
Page<User> page = new Page(1, 3); // 构建一个page类这个Page类是Myatis-plus包下的第一个参数代表当前页码,第二个参数表示当前页显示多少条数据
Page<User> userPage = userService.page(page,null); // 调用分页查询方法进行分页查询,第一个参数代表page对象,第二个参数代表查询条件
//返回对象得到分页所有数据
long pages = userPage.getPages(); //总页数
long current = userPage.getCurrent(); //当前页
List<User> records = userPage.getRecords(); //查询数据集合
long total = userPage.getTotal(); //总记录数
boolean hasNext = userPage.hasNext(); //是否有下一页
boolean hasPrevious = userPage.hasPrevious(); //是否有上一页
System.out.println(pages);
System.out.println(current);
System.out.println(records);
System.out.println(total);
System.out.println(hasNext);
System.out.println(hasPrevious);
}
mybatis-plus逻辑删除
在平常的删除数据业务逻辑中一般不会吧数据真正的删除掉一般都是使用逻辑删除,通过一个字段定义当前数据是无效的,mybatis-plus通过在其字段上标明
@TableLogic
注解来使用逻辑删除
#在yml文件中写入当前的配置
mybatis-plus:
config-location:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 可以打印出其中sql语句的日志
global-config:
db-config:
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
在现在这种情况下使用删除语句不会把数据库中的数据直接删除掉,并且可以在控制台发现不是执行的delete语句而是执行的update语句将当前所需要删除的数据的逻辑删除字段的值改为了1
/**
* 通过ID删除
*/
@Test
void deleteById(){
userService.removeById(1L);
}
控制台输出
mybatis-plus 乐观锁
乐观锁( Optimistic Locking ) 相对悲观锁而言,乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做。在mybatis-plus中使用乐观锁必须在乐观锁字段上添加
@Version
注解并且在配置类中注入OptimisticLockerInterceptor
类
/**
* 带乐观锁修改
*/
@Test
void update(){
User user = new User();
user.setId(00000000000000000001l);
user.setAge(10);
user.setEmail("1112211111@qq.com");
user.setName("zhangsan");
user.setVersion(2); // 带上当前要修改的数据的版本号
userService.updateById(user);
}
控制台打印,version会带入到条件中
更新完成后数据库中
version
字段会自动加一
mybatis-plus自动填充功能
mybatis-plus的自动填充功能,通过注解
@TableField(fill = FieldFill.INSERT)
其中的fill
属性设置值表示该字段在什么过程中进行自增,实现MetaObjectHandler
接口来定义自动填充的值
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
/**
* 在数据新增时进行操作
*/
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
this.setFieldValByName("version",1,metaObject);
}
/**
* 在数据修改时进行操作
*/
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
mybatis-plus使用 Wrapper
进行复杂的操作
Wrapper
是mybatis-plus提供出来使用的条件构造器
Wrapper
: 条件构造抽象类,最顶端父类
AbstractWrapper
: 用于查询条件封装,生成 sql 的 where 条件
QueryWrapper
: 查询条件封装
UpdateWrapper
: Update 条件封装
AbstractLambdaWrapper
: 使用Lambda 语法
LambdaQueryWrapper
:用于Lambda语法使用的查询Wrapper
LambdaUpdateWrapper
: Lambda 更新封装Wrapper
测试使用
ge、gt、le、lt、isNull、isNotNull
@Test
public void testQuery() {
QueryWrapper<User>queryWrapper = newQueryWrapper<>();
queryWrapper
.isNull("name")
.ge("age", 12)
.isNotNull("email");
int result = userMapper.delete(queryWrapper);
System.out.println("delete return count = " + result);
}
eq、ne
注意:
seletOne()
返回的是一条实体记录,当出现多条时会报错 @Test
public void testSelectOne() {
QueryWrapper<User>queryWrapper = newQueryWrapper<>();
queryWrapper.eq("name", "Tom");
Useruser = userMapper.selectOne(queryWrapper);//只能返回一条记录,多余一条则抛出异常
System.out.println(user);
}
between、notBetween
包含大小边界
@Test
public void testSelectCount() {
QueryWrapper<User>queryWrapper = newQueryWrapper<>();
queryWrapper.between("age", 20, 30);
Integer count = userMapper.selectCount(queryWrapper); //返回数据数量
System.out.println(count);
}
like、notLike、likeLeft、likeRight
selectMaps()
返回Map集合列表,通常配合select()使用
@Test
public void testSelectMaps() {
QueryWrapper<User>queryWrapper = newQueryWrapper<>();
queryWrapper
.select("name", "age")
.like("name", "e")
.likeRight("email", "5");
List<Map<String, Object>>maps = userMapper.selectMaps(queryWrapper);//返回值是Map列表
maps.forEach(System.out::println);
}
orderBy、orderByDesc、orderByAsc
@Test
public void testSelectListOrderBy() {
QueryWrapper<User>queryWrapper = newQueryWrapper<>();
queryWrapper.orderByDesc("age", "id");
List<User>users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
Wrapper对应的查询方式
更多详情可参考官方 条件构造器
查询方式 | 说明 |
---|---|
setSqlSelect | 设置 SELECT 查询字段 |
where | WHERE 语句,拼接 + WHERE 条件 |
and | AND 语句,拼接 + AND 字段=值 |
andNew | AND 语句,拼接 + AND (字段=值) |
or | OR 语句,拼接 + OR 字段=值 |
orNew | OR 语句,拼接 + OR (字段=值) |
eq | 等于= |
allEq | 基于 map 内容等于= |
ne | 不等于<> |
gt | 大于> |
ge | 大于等于>= |
lt | 小于< |
le | 小于等于<= |
like | 模糊查询 LIKE |
notLike | 模糊查询 NOT LIKE |
in | IN 查询 |
notIn | NOT IN 查询 |
isNull | NULL 值查询 |
isNotNull | IS NOT NULL |
groupBy | 分组 GROUP BY |
having | HAVING 关键词 |
orderBy | 排序 ORDER BY |
orderAsc | ASC 排序 ORDER BY |
orderDesc | DESC 排序 ORDER BY |
exists | EXISTS 条件语句 |
notExists | NOT EXISTS 条件语句 |
between | BETWEEN 条件语句 |
notBetween | NOT BETWEEN 条件语句 |
addFilter | 自由拼接 SQL |
last | 拼接在最后,例如:last(“LIMIT 1”) |