官方链接https://baomidou.com/pages/24112f/
基本使用
Springboot依赖配置
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3.4</version>
</dependency>
基本使用,以分页查询为例
配置
@Configuration
@MapperScan("com.lff.dr.mapper")
public class MybatisPlusConfig {
// 最新版
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}
}
Model实体类
public class DictType {
private Short id;
private String name;
private String value;
private String intro;
//getter and setter
}
mapper层
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lff.dr.pojo.po.DictType;
public interface DictTypeMapper extends BaseMapper<DictType> {
}
service层
接口要继承IService并泛型要查询的对象
public interface DictTypeService extends IService<DictType> { //IService包含很多处理数据库的方法
void list(DictTypeQuery query); //可以自定义方法
}
Service实现层
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lff.dr.mapper.DictTypeMapper;
import com.lff.dr.pojo.po.DictType;
import com.lff.dr.pojo.query.DictTypeQuery;
import com.lff.dr.service.DictTypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
@Service
@Transactional
public class DictTypeServiceImpl extends ServiceImpl<DictTypeMapper,DictType> implements DictTypeService {
@Autowired
private DictTypeMapper dictTypeMapper;
public void list(DictTypeQuery query) {
//设置查询条件
LambdaQueryWrapper<DictType> wrapper = new LambdaQueryWrapper<>();
if (!StringUtils.isEmpty(query.getKeyWord())){ //判断条件是否为空
wrapper.like(DictType::getName,query.getKeyWord()).or()
.like(DictType::getIntro,query.getKeyWord());
}
//分页查询对象
Page<DictType> page = new Page<>(query.getPage(),query.getSize());
//执行查询
page = dictTypeMapper.selectPage(page,wrapper);
//保存查询的总页数
query.setTotal(page.getTotal());
//保存查询的结果集
query.setData(page.getRecords());
//保存当前页数据
query.setCurrent(page.getCurrent());
}
}
Controller层
@Controller
public class DictTypeController {
@Autowired
private DictTypeService dictTypeService;
@RequestMapping("/dictType")
public String fetchDictType(DictTypeQuery query,Model model){
dictTypeService.list(query);
model.addAttribute("query",query);
return "list";
}
}
自定义分页方法
我们可以在Dao层也就是mapper里面自定义分页方法
public interface XxxMapper extends BaseMapper<T> {
}
如果自定义的方法想分页查询,只需模仿官方的写法即可,官方的示例如下:
/**
* 根据 entity 条件,查询全部记录(并翻页)
*
* @param page 分页查询条件(可以为 RowBounds.DEFAULT)
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
<P extends IPage<T>> P selectPage(P page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
官方第一个参数是分页对象,返回值也是分页对象,查询条件加了 @Param(Constants.WRAPPER),Constants._WRAPPER就是常量字符串ew。也就是_queryWrapper起个参数名称叫ew。其实@Param()里面的参数名称可以随便写,但官方推荐使用ew。
自定义分页功能
在自定义方法中,如果第一个参数传的是Page类型的对象,返回类型也是Page类型的对象,mybatis-plus
�内部会做拦截,自动为我们加分页语句即limit语句
自定义查询条件(官方链接)
如果也想自动加where语句的条件,需要如下2步:1.参数为Wrapper类型的参数,前面要加@Param(Constants.WRAPPER),官方推荐写法。 2.xml的SQL语句中最后加${ew.customSqlSegment}
Wrapper对象有个方法getCustomSqlSegment。${ew.customSqlSegment}就会调用getCustomSqlSegment方法返回查询条件。
/**
* 获取自定义SQL 简化自定义XML复杂情况
* <p>
* 使用方法: `select xxx from table` + ${ew.customSqlSegment}
* <p>
* 注意事项:
* 1. 逻辑删除需要自己拼接条件 (之前自定义也同样)
* 2. 不支持wrapper中附带实体的情况 (wrapper自带实体会更麻烦)
* 3. 用法 ${ew.customSqlSegment} (不需要where标签包裹,切记!)
* 4. ew是wrapper定义别名,不能使用其他的替换
*/
public String getCustomSqlSegment() {
MergeSegments expression = getExpression();
if (Objects.nonNull(expression)) {
NormalSegmentList normal = expression.getNormal();
String sqlSegment = getSqlSegment();
if (StringUtils.isNotBlank(sqlSegment)) {
if (normal.isEmpty()) {
return sqlSegment;
} else {
return Constants.WHERE + StringPool.SPACE + sqlSegment;
}
}
}
return StringPool.EMPTY;
}
�示例
Page selectPagesVo(Page page, @Param(Constants.WRAPPER) Wrapper<具体泛型的pojo对象> queryWrapper);
条件包装括号
使用nested函数可以把条件加()好,官方链接
QueryWrapper<ExamPlaceCourseVo> queryWrapper = new QueryWrapper<>();
queryWrapper.nested(w->{
w.like("name","张三").or().lt("age",18);
});
遇到的问题:
问题1
如果使用LambdaQueryWrapper作为条件,里面又使用了方法的引用比如User::getName就会报错误
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.like(User::getName,"匹配的内容");
baseMapper.selectPagesVo(new Page(1,20),queryWrapper);
报错信息
can not find lambda cache for this entity [com.lff.dr.pojo.vo.User]
原因是:在泛型LambdaQueryWrapper
public interface DictTypeMapper extends BaseMapper<DictType> {
}
解决方法:
解决方法1:使用QueryWrapper并且不使用方法引用
解决方法2:mybatis-plus可以单独为一个类添加lambda cache,这需要手动配置,因为只需配置一次可以在InitializingBean方法里面配置
@Configuration
@MapperScan("com.lff.dr.mapper")
public class MybatisPlusConfig implements InitializingBean {
// 最新版
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}
@Override
public void afterPropertiesSet() throws Exception {
//实体类添加lambda cache,固定写法
MapperBuilderAssistant assistant = new MapperBuilderAssistant(new MybatisConfiguration(), "");
//添加具体的实体类
TableInfoHelper.initTableInfo(assistant, User.class);
TableInfoHelper.initTableInfo(assistant, xxx.class);
}
}
问题2
报类似如下信息
Column 'name' in where clause is ambiguous //name为表里面的字段
这一般是在多表关联查询时,name字段在关联表、多个表中都有这个字段引起的,比如SQL语句这样写
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.like(User::getName,"匹配的内容"); //User::getName会直接转成name
baseMapper.selectPagesVo(new Page(1,20),queryWrapper);
对应的XML语句
<select id="selectXXX"
resultMap="hahha">
select name,xxx
from table_name1 join table_name2 on table_name1.id = table_name2.id
${ew.customSqlSegment}
</select>
在${ew.customSqlSegment}生成的where条件中name字段在table_name1表、table_name2表中都有name字段引起的。
解决方法:
显示指定name字段是哪个表里面的,是table_name1的还是table_name2的。不要使用LambdaQueryWrapper改为使用QueryWrapper。
QueryWrapper<Entity> queryWrapper = new QueryWrapper<>();
queryWrapper.like("table_name1.name","xxx");
�在做条件查询的时候,最后标明哪个字段是哪个表中的,写全一点。