1 MyBatis Plus 介绍
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。MyBatis-Plus最直接的优点有:
(1)提供Mapper基类接口, 可以自动完成简单的CRUD操作;
(2)提供QueryWrapper包装器,它支持类似Hibernate的Criteria的多于条件查询和排序;
(3)提供MyBatis拦截器,能自动实现分页。
官网:Redirect
官方推荐学习视频:https://www.imooc.com/learn/1130
2 搭建Spring boot 的 Mybatis Plus 支持
(1)添加依赖
代码语言:javascript复制 <dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
(2)配置应用 application.yml
代码语言:javascript复制spring:
datasource:
url: jdbc:mysql://localhost:3306/mycinema?serverTimezone=GMT+8
username: root
password: 1234
mybatis-plus:
# 如果是放在resource目录 classpath:/mapper/*Mapper.xml
mapper-locations: classpath:mapper/*Mapper.xml
#实体扫描,多个package用逗号或者分号分隔
typeAliasesPackage: mycinema.entity
configuration:
#配置返回数据库(column下划线命名&&返回java实体是驼峰命名),自动匹配无需as(没开启这个,SQL需要写as: select user_id as userId)
map-underscore-to-camel-case: false
(3)数据实体 Category.java
代码语言:javascript复制@Data
@AllArgsConstructor
@NoArgsConstructor
public class Category {
@TableId(type = IdType.AUTO) //数据库主键自增,保存后带回自增值
private int id;
private String name;
}
(4)mapper接口
代码语言:javascript复制// 继承的 mapper 接口
public interface CategoryMapper extends BaseMapper<Category> {
}
// spring boot 启动类,加入 @MapperScan
@MapperScan("mycinema.mapper")
@SpringBootApplication
public class MycinemaMpApplication {
public static void main(String[] args) {
SpringApplication.run(MycinemaMpApplication.class, args);
}
}
(5)测试接口中的CRUD操作
代码语言:javascript复制@SpringBootTest
public class CategoryMapperTest {
@Autowired
private CategoryMapper target;
@Test
public void testSelectById() { assertEquals("战争", target.selectById(2).getName()); }
@Test
public void testInsert() {
Category c = new Category(0, "测试1");
target.insert(c);
assertTrue(c.getId()>0);
}
@Test
public void testUpdateById() {
Category c = new Category(3, "言情");
target.updateById(c);
assertEquals("言情", target.selectById(3).getName());
}
@Test
public void testDeleteById() { target.deleteById(5); }
}
3 多条件查询
MyBatis Plus 提供了 QueryWrapper 对象,它有点类似 Hibernate 的 Criteria,可以灵活的为查询添加条件。
编写一个Movie实体类:
代码语言:javascript复制@Data
public class Movie {
@TableId(type = IdType.AUTO)
private int id;
private String title;
private String movieCode;
private String director;
private Date dateReleased;
private int categoryId;
}
使用 QueryWrapper 实现灵活的多条件查询:
代码语言:javascript复制@Service
public class MovieBizImpl implements MovieBiz {
@Autowired
private MovieMapper movieDb;
@Override
public List<Movie> findMovies(int cid, String title) {
QueryWrapper<Movie> queryWrapper = new QueryWrapper<Movie>();
if(cid>0)
queryWrapper.eq("categoryId", cid);
if(title!=null && !title.isBlank())
queryWrapper.like("title", "%" title "%");
return movieDb.selectList(queryWrapper);
}
}
4 排序
QueryWrapper 对象还提供了 “orderByDesc” 和 “orderByAsc” 等方法,可以简单实现排序
queryWrapper.orderByDesc("dateReleased");
5 分页
(1)配置分页拦截器:
在配置类(也可以是SpringBoot启动类)中声明分页拦截器Bean
代码语言:javascript复制 @Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
(2)使用分页对象 IPage<T> 控制当前页码和每页大小
代码语言:javascript复制 public IPage<Movie> findMoviesPage(..., int pageNum, int pageSize){
QueryWrapper<Movie> query = new QueryWrapper<Movie>();
......
Page<Movie> page = new Page<Movie>(pageNum, pageSize); //设置分页对象
return movieDb.selectPage(page, query);
}
IPage<T> 返回对象中可以获取当前页数据实体集合 getRecords(),总行数 getTotal(),总页数 getPages(),当前页 getCurrent(),每页大小 getSize() 等数据
6 一种简单的外键对象加载策略
(1)在实体类中先配置外键对象(Category)不是数据库的字段(@TableField(exist=false))
代码语言:javascript复制@Data
public class Movie {
@TableId(type = IdType.AUTO)
private int id;
private String title;
private String movieCode;
private String director;
private Date dateReleased;
private int categoryId;
@TableField(exist = false)
private Category category;
}
(2)在加载时使用单独查询外键的方式加载
代码语言:javascript复制@Service
@Transactional
public class MovieServiceImpl {
@Autowired
private MovieMapper movieDb;
@Autowired
private CategoryMapper categoryDb;
@Transactional(readOnly=true) //亲测:如果没有事务管理,二次查询Categoy就没有一级缓存了
public IPage<Movie> findMoviesWithCategoryPage(Integer cateId, String title, String orderByColumn, Boolean orderByAsc, int pageNum, int pageSize){
QueryWrapper<Movie> query = new QueryWrapper<Movie>();
......
IPage<Movie> page = movieDb.selectPage(new Page<Movie>(pageNum, pageSize), query);
//循环添加Category对象
page.getRecords().forEach(x->x.setCategory(categoryDb.selectById(x.getCategoryId())));
return page;
}
}