MyBatisPlus接入、核心源码
MyBatisPlus集成
父工程pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<modules>
<module>xxx</module>
<module>xxx</module>
<module>xxx</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.10.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.sb</groupId>
<artifactId>sb-vip-mall</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>sb-vip-mall</name>
<description>xxx</description>
<!--父工程pom只留所有模块都会引用的依赖-->
<packaging>pom</packaging>
<properties>
<java.version>1.8</java.version>
<spring-clould-alibaba.version>2.2.1.RELEASE</spring-clould-alibaba.version>
</properties>
<dependencies>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--slf4j-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<!--测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.60</version>
</dependency>
</dependencies>
<!--alibaba-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-clould-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
1.引入依赖包:
<!--MyBatis Plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.2</version>
</dependency>
2.编写JavaBean会用到MyBatis Plus的相关注解,引入,只是为了防止编译不通过
<!--MyBatis Plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.2</version>
<!--scope指定provided:代表只是编译,并不是每次打包要打进去-->
<scope>provided</scope>
</dependency>
相关配置
# ====================MybatisPlus====================
mybatis-plus:
# mapper-locations:复杂的操作可能需要自己写SQL,SQL可以写到xml文件中,这里指定和Dao对应的xml文件,此时我们需要在resources中创建一个mapper目录
mapper-locations: mapper/*.xml
# type-aliases-package:指定JavaBean的别名包,和MyBatis用法一样
type-aliases-package: com.gupaoedu.vip.mall.*.model
configuration:
# map-underscore-to-camel-case:开启驼峰功能,数据库表列名如果有_,可以自动按驼峰命名规则转换
map-underscore-to-camel-case: true
# log-impl:日志开启,方便测试
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
Mp提供了通用的方法
Mapper(接口)-->exthends BaseMapper<T>
Service(接口)-->exthends IService<T>
ServiceImpl(接口)-->exthends ServiceIMpl<T>
public class BrandServiceImpl extends ServiceImpl<BradMapper, Brand> implements BrandService {
public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T>
泛型:M 是 mapper 对象,T 是实体
BaseMapper
/**
* Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能
* <p>这个 Mapper 支持 id 泛型</p>
*
* @author hubin
* @since 2016-01-23
*/
public interface BaseMapper<T> extends Mapper<T> {
/**
* 插入一条记录
*
* @param entity 实体对象
*/
int insert(T entity);
/**
* 根据 ID 删除
*
* @param id 主键ID
*/
int deleteById(Serializable id);
/**
* 根据 columnMap 条件,删除记录
*
* @param columnMap 表字段 map 对象
*/
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
/**
* 根据 entity 条件,删除记录
*
* @param wrapper 实体对象封装操作类(可以为 null)
*/
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
/**
* 删除(根据ID 批量删除)
*
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
/**
* 根据 ID 修改
*
* @param entity 实体对象
*/
int updateById(@Param(Constants.ENTITY) T entity);
/**
* 根据 whereEntity 条件,更新记录
*
* @param entity 实体对象 (set 条件值,可以为 null)
* @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
*/
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
/**
* 根据 ID 查询
*
* @param id 主键ID
*/
T selectById(Serializable id);
/**
* 查询(根据ID 批量查询)
*
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
/**
* 查询(根据 columnMap 条件)
*
* @param columnMap 表字段 map 对象
*/
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
/**
* 根据 entity 条件,查询一条记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询总记录数
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 entity 条件,查询全部记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录
* <p>注意: 只返回第一个字段的值</p>
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 entity 条件,查询全部记录(并翻页)
*
* @param page 分页查询条件(可以为 RowBounds.DEFAULT)
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
<E extends IPage<T>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录(并翻页)
*
* @param page 分页查询条件
* @param queryWrapper 实体对象封装操作类
*/
<E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
}
IService
/*
* Copyright (c) 2011-2020, baomidou (jobob@qq.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.baomidou.mybatisplus.extension.service;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.UpdateChainWrapper;
import com.baomidou.mybatisplus.extension.toolkit.ChainWrappers;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import org.springframework.transaction.annotation.Transactional;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 顶级 Service
*
* @author hubin
* @since 2018-06-23
*/
public interface IService<T> {
/**
* 默认批次提交数量
*/
int DEFAULT_BATCH_SIZE = 1000;
/**
* 插入一条记录(选择字段,策略插入)
*
* @param entity 实体对象
*/
default boolean save(T entity) {
return SqlHelper.retBool(getBaseMapper().insert(entity));
}
/**
* 插入(批量)
*
* @param entityList 实体对象集合
*/
@Transactional(rollbackFor = Exception.class)
default boolean saveBatch(Collection<T> entityList) {
return saveBatch(entityList, DEFAULT_BATCH_SIZE);
}
/**
* 插入(批量)
*
* @param entityList 实体对象集合
* @param batchSize 插入批次数量
*/
boolean saveBatch(Collection<T> entityList, int batchSize);
/**
* 批量修改插入
*
* @param entityList 实体对象集合
*/
@Transactional(rollbackFor = Exception.class)
default boolean saveOrUpdateBatch(Collection<T> entityList) {
return saveOrUpdateBatch(entityList, DEFAULT_BATCH_SIZE);
}
/**
* 批量修改插入
*
* @param entityList 实体对象集合
* @param batchSize 每次的数量
*/
boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);
/**
* 根据 ID 删除
*
* @param id 主键ID
*/
default boolean removeById(Serializable id) {
return SqlHelper.retBool(getBaseMapper().deleteById(id));
}
/**
* 根据 columnMap 条件,删除记录
*
* @param columnMap 表字段 map 对象
*/
default boolean removeByMap(Map<String, Object> columnMap) {
Assert.notEmpty(columnMap, "error: columnMap must not be empty");
return SqlHelper.retBool(getBaseMapper().deleteByMap(columnMap));
}
/**
* 根据 entity 条件,删除记录
*
* @param queryWrapper 实体包装类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
default boolean remove(Wrapper<T> queryWrapper) {
return SqlHelper.retBool(getBaseMapper().delete(queryWrapper));
}
/**
* 删除(根据ID 批量删除)
*
* @param idList 主键ID列表
*/
default boolean removeByIds(Collection<? extends Serializable> idList) {
if (CollectionUtils.isEmpty(idList)) {
return false;
}
return SqlHelper.retBool(getBaseMapper().deleteBatchIds(idList));
}
/**
* 根据 ID 选择修改
*
* @param entity 实体对象
*/
default boolean updateById(T entity) {
return SqlHelper.retBool(getBaseMapper().updateById(entity));
}
/**
* 根据 UpdateWrapper 条件,更新记录 需要设置sqlset
*
* @param updateWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper}
*/
default boolean update(Wrapper<T> updateWrapper) {
return update(null, updateWrapper);
}
/**
* 根据 whereEntity 条件,更新记录
*
* @param entity 实体对象
* @param updateWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper}
*/
default boolean update(T entity, Wrapper<T> updateWrapper) {
return SqlHelper.retBool(getBaseMapper().update(entity, updateWrapper));
}
/**
* 根据ID 批量更新
*
* @param entityList 实体对象集合
*/
@Transactional(rollbackFor = Exception.class)
default boolean updateBatchById(Collection<T> entityList) {
return updateBatchById(entityList, DEFAULT_BATCH_SIZE);
}
/**
* 根据ID 批量更新
*
* @param entityList 实体对象集合
* @param batchSize 更新批次数量
*/
boolean updateBatchById(Collection<T> entityList, int batchSize);
/**
* TableId 注解存在更新记录,否插入一条记录
*
* @param entity 实体对象
*/
boolean saveOrUpdate(T entity);
/**
* 根据 ID 查询
*
* @param id 主键ID
*/
default T getById(Serializable id) {
return getBaseMapper().selectById(id);
}
/**
* 查询(根据ID 批量查询)
*
* @param idList 主键ID列表
*/
default List<T> listByIds(Collection<? extends Serializable> idList) {
return getBaseMapper().selectBatchIds(idList);
}
/**
* 查询(根据 columnMap 条件)
*
* @param columnMap 表字段 map 对象
*/
default List<T> listByMap(Map<String, Object> columnMap) {
return getBaseMapper().selectByMap(columnMap);
}
/**
* 根据 Wrapper,查询一条记录 <br/>
* <p>结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")</p>
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
default T getOne(Wrapper<T> queryWrapper) {
return getOne(queryWrapper, true);
}
/**
* 根据 Wrapper,查询一条记录
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
* @param throwEx 有多个 result 是否抛出异常
*/
T getOne(Wrapper<T> queryWrapper, boolean throwEx);
/**
* 根据 Wrapper,查询一条记录
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
Map<String, Object> getMap(Wrapper<T> queryWrapper);
/**
* 根据 Wrapper,查询一条记录
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
* @param mapper 转换函数
*/
<V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
/**
* 查询总记录数
*
* @see Wrappers#emptyWrapper()
*/
default int count() {
return count(Wrappers.emptyWrapper());
}
/**
* 根据 Wrapper 条件,查询总记录数
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
default int count(Wrapper<T> queryWrapper) {
return SqlHelper.retCount(getBaseMapper().selectCount(queryWrapper));
}
/**
* 查询列表
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
default List<T> list(Wrapper<T> queryWrapper) {
return getBaseMapper().selectList(queryWrapper);
}
/**
* 查询所有
*
* @see Wrappers#emptyWrapper()
*/
default List<T> list() {
return list(Wrappers.emptyWrapper());
}
/**
* 翻页查询
*
* @param page 翻页对象
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
default <E extends IPage<T>> E page(E page, Wrapper<T> queryWrapper) {
return getBaseMapper().selectPage(page, queryWrapper);
}
/**
* 无条件翻页查询
*
* @param page 翻页对象
* @see Wrappers#emptyWrapper()
*/
default <E extends IPage<T>> E page(E page) {
return page(page, Wrappers.emptyWrapper());
}
/**
* 查询列表
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
default List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper) {
return getBaseMapper().selectMaps(queryWrapper);
}
/**
* 查询所有列表
*
* @see Wrappers#emptyWrapper()
*/
default List<Map<String, Object>> listMaps() {
return listMaps(Wrappers.emptyWrapper());
}
/**
* 查询全部记录
*/
default List<Object> listObjs() {
return listObjs(Function.identity());
}
/**
* 查询全部记录
*
* @param mapper 转换函数
*/
default <V> List<V> listObjs(Function<? super Object, V> mapper) {
return listObjs(Wrappers.emptyWrapper(), mapper);
}
/**
* 根据 Wrapper 条件,查询全部记录
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
default List<Object> listObjs(Wrapper<T> queryWrapper) {
return listObjs(queryWrapper, Function.identity());
}
/**
* 根据 Wrapper 条件,查询全部记录
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
* @param mapper 转换函数
*/
default <V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper) {
return getBaseMapper().selectObjs(queryWrapper).stream().filter(Objects::nonNull).map(mapper).collect(Collectors.toList());
}
/**
* 翻页查询
*
* @param page 翻页对象
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
default <E extends IPage<Map<String, Object>>> E pageMaps(E page, Wrapper<T> queryWrapper) {
return getBaseMapper().selectMapsPage(page, queryWrapper);
}
/**
* 无条件翻页查询
*
* @param page 翻页对象
* @see Wrappers#emptyWrapper()
*/
default <E extends IPage<Map<String, Object>>> E pageMaps(E page) {
return pageMaps(page, Wrappers.emptyWrapper());
}
/**
* 获取对应 entity 的 BaseMapper
*
* @return BaseMapper
*/
BaseMapper<T> getBaseMapper();
/**
* 以下的方法使用介绍:
*
* 一. 名称介绍
* 1. 方法名带有 query 的为对数据的查询操作, 方法名带有 update 的为对数据的修改操作
* 2. 方法名带有 lambda 的为内部方法入参 column 支持函数式的
*
* 二. 支持介绍
* 1. 方法名带有 query 的支持以 {@link ChainQuery} 内部的方法名结尾进行数据查询操作
* 2. 方法名带有 update 的支持以 {@link ChainUpdate} 内部的方法名为结尾进行数据修改操作
*
* 三. 使用示例,只用不带 lambda 的方法各展示一个例子,其他类推
* 1. 根据条件获取一条数据: `query().eq("column", value).one()`
* 2. 根据条件删除一条数据: `update().eq("column", value).remove()`
*
*/
/**
* 链式查询 普通
*
* @return QueryWrapper 的包装类
*/
default QueryChainWrapper<T> query() {
return ChainWrappers.queryChain(getBaseMapper());
}
/**
* 链式查询 lambda 式
* <p>注意:不支持 Kotlin </p>
*
* @return LambdaQueryWrapper 的包装类
*/
default LambdaQueryChainWrapper<T> lambdaQuery() {
return ChainWrappers.lambdaQueryChain(getBaseMapper());
}
/**
* 链式更改 普通
*
* @return UpdateWrapper 的包装类
*/
default UpdateChainWrapper<T> update() {
return ChainWrappers.updateChain(getBaseMapper());
}
/**
* 链式更改 lambda 式
* <p>注意:不支持 Kotlin </p>
*
* @return LambdaUpdateWrapper 的包装类
*/
default LambdaUpdateChainWrapper<T> lambdaUpdate() {
return ChainWrappers.lambdaUpdateChain(getBaseMapper());
}
/**
* <p>
* 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法
* 此次修改主要是减少了此项业务代码的代码量(存在性验证之后的saveOrUpdate操作)
* </p>
*
* @param entity 实体对象
*/
default boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper) {
return update(entity, updateWrapper) || saveOrUpdate(entity);
}
}
ServiceImpl
/*
* Copyright (c) 2011-2020, baomidou (jobob@qq.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.baomidou.mybatisplus.extension.service.impl;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.*;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.reflection.ExceptionUtil;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.MyBatisExceptionTranslator;
import org.mybatis.spring.SqlSessionHolder;
import org.mybatis.spring.SqlSessionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import java.io.Serializable;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* IService 实现类( 泛型:M 是 mapper 对象,T 是实体 )
*
* @author hubin
* @since 2018-06-23
*/
@SuppressWarnings("unchecked")
public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
protected Log log = LogFactory.getLog(getClass());
@Autowired
protected M baseMapper;
@Override
public M getBaseMapper() {
return baseMapper;
}
protected Class<?> entityClass = currentModelClass();
/**
* 判断数据库操作是否成功
*
* @param result 数据库操作返回影响条数
* @return boolean
* @deprecated 3.3.1
*/
@Deprecated
protected boolean retBool(Integer result) {
return SqlHelper.retBool(result);
}
protected Class<T> currentModelClass() {
return (Class<T>) ReflectionKit.getSuperClassGenericType(getClass(), 1);
}
/**
* 批量操作 SqlSession
*
* @deprecated 3.3.0
*/
@Deprecated
protected SqlSession sqlSessionBatch() {
return SqlHelper.sqlSessionBatch(entityClass);
}
/**
* 释放sqlSession
*
* @param sqlSession session
* @deprecated 3.3.0
*/
@Deprecated
protected void closeSqlSession(SqlSession sqlSession) {
SqlSessionUtils.closeSqlSession(sqlSession, GlobalConfigUtils.currentSessionFactory(entityClass));
}
/**
* 获取 SqlStatement
*
* @param sqlMethod ignore
* @return ignore
*/
protected String sqlStatement(SqlMethod sqlMethod) {
return SqlHelper.table(entityClass).getSqlStatement(sqlMethod.getMethod());
}
/**
* 批量插入
*
* @param entityList ignore
* @param batchSize ignore
* @return ignore
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean saveBatch(Collection<T> entityList, int batchSize) {
String sqlStatement = sqlStatement(SqlMethod.INSERT_ONE);
return executeBatch(entityList, batchSize, (sqlSession, entity) -> sqlSession.insert(sqlStatement, entity));
}
/**
* TableId 注解存在更新记录,否插入一条记录
*
* @param entity 实体对象
* @return boolean
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean saveOrUpdate(T entity) {
if (null != entity) {
Class<?> cls = entity.getClass();
TableInfo tableInfo = TableInfoHelper.getTableInfo(cls);
Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!");
String keyProperty = tableInfo.getKeyProperty();
Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!");
Object idVal = ReflectionKit.getFieldValue(entity, tableInfo.getKeyProperty());
return StringUtils.checkValNull(idVal) || Objects.isNull(getById((Serializable) idVal)) ? save(entity) : updateById(entity);
}
return false;
}
@Transactional(rollbackFor = Exception.class)
@Override
public boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize) {
TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass);
Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!");
String keyProperty = tableInfo.getKeyProperty();
Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!");
return executeBatch(entityList, batchSize, (sqlSession, entity) -> {
Object idVal = ReflectionKit.getFieldValue(entity, keyProperty);
if (StringUtils.checkValNull(idVal) || Objects.isNull(getById((Serializable) idVal))) {
sqlSession.insert(tableInfo.getSqlStatement(SqlMethod.INSERT_ONE.getMethod()), entity);
} else {
MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>();
param.put(Constants.ENTITY, entity);
sqlSession.update(tableInfo.getSqlStatement(SqlMethod.UPDATE_BY_ID.getMethod()), param);
}
});
}
@Transactional(rollbackFor = Exception.class)
@Override
public boolean updateBatchById(Collection<T> entityList, int batchSize) {
String sqlStatement = sqlStatement(SqlMethod.UPDATE_BY_ID);
return executeBatch(entityList, batchSize, (sqlSession, entity) -> {
MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>();
param.put(Constants.ENTITY, entity);
sqlSession.update(sqlStatement, param);
});
}
@Override
public T getOne(Wrapper<T> queryWrapper, boolean throwEx) {
if (throwEx) {
return baseMapper.selectOne(queryWrapper);
}
return SqlHelper.getObject(log, baseMapper.selectList(queryWrapper));
}
@Override
public Map<String, Object> getMap(Wrapper<T> queryWrapper) {
return SqlHelper.getObject(log, baseMapper.selectMaps(queryWrapper));
}
@Override
public <V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper) {
return SqlHelper.getObject(log, listObjs(queryWrapper, mapper));
}
/**
* 执行批量操作
*
* @param consumer consumer
* @since 3.3.0
* @deprecated 3.3.1 后面我打算移除掉 {@link #executeBatch(Collection, int, BiConsumer)} }.
*/
@Deprecated
protected boolean executeBatch(Consumer<SqlSession> consumer) {
SqlSessionFactory sqlSessionFactory = SqlHelper.sqlSessionFactory(entityClass);
SqlSessionHolder sqlSessionHolder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sqlSessionFactory);
boolean transaction = TransactionSynchronizationManager.isSynchronizationActive();
if (sqlSessionHolder != null) {
SqlSession sqlSession = sqlSessionHolder.getSqlSession();
//原生无法支持执行器切换,当存在批量操作时,会嵌套两个session的,优先commit上一个session
//按道理来说,这里的值应该一直为false。
sqlSession.commit(!transaction);
}
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
if (!transaction) {
log.warn("SqlSession [" + sqlSession + "] was not registered for synchronization because DataSource is not transactional");
}
try {
consumer.accept(sqlSession);
//非事物情况下,强制commit。
sqlSession.commit(!transaction);
return true;
} catch (Throwable t) {
sqlSession.rollback();
Throwable unwrapped = ExceptionUtil.unwrapThrowable(t);
if (unwrapped instanceof RuntimeException) {
MyBatisExceptionTranslator myBatisExceptionTranslator
= new MyBatisExceptionTranslator(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), true);
throw Objects.requireNonNull(myBatisExceptionTranslator.translateExceptionIfPossible((RuntimeException) unwrapped));
}
throw ExceptionUtils.mpe(unwrapped);
} finally {
sqlSession.close();
}
}
/**
* 执行批量操作
*
* @param list 数据集合
* @param batchSize 批量大小
* @param consumer 执行方法
* @param <E> 泛型
* @return 操作结果
* @since 3.3.1
*/
protected <E> boolean executeBatch(Collection<E> list, int batchSize, BiConsumer<SqlSession, E> consumer) {
Assert.isFalse(batchSize < 1, "batchSize must not be less than one");
return !CollectionUtils.isEmpty(list) && executeBatch(sqlSession -> {
int size = list.size();
int i = 1;
for (E element : list) {
consumer.accept(sqlSession, element);
if ((i % batchSize == 0) || i == size) {
sqlSession.flushStatements();
}
i++;
}
});
}
/**
* 执行批量操作(默认批次提交数量{@link IService#DEFAULT_BATCH_SIZE})
*
* @param list 数据集合
* @param consumer 执行方法
* @param <E> 泛型
* @return 操作结果
* @since 3.3.1
*/
protected <E> boolean executeBatch(Collection<E> list, BiConsumer<SqlSession, E> consumer) {
return executeBatch(list, DEFAULT_BATCH_SIZE, consumer);
}
}
Mp接入分页
compare接口:比较列
条件查询需要封装条件信息,MyBatis Plus提供了条件封装对象 Wrapper (它的子类 QueryWrapper 可 以直接使用),我们可以用它的子类 QueryWrapper 实现封装查询条件。
/*
* Copyright (c) 2011-2020, baomidou (jobob@qq.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.baomidou.mybatisplus.core.conditions.interfaces;
import java.io.Serializable;
import java.util.Map;
import java.util.function.BiPredicate;
/**
* 查询条件封装
* <p>比较值</p>
*
* @author hubin miemie HCL
* @since 2017-05-26
*/
public interface Compare<Children, R> extends Serializable {
/**
* ignore
*/
default <V> Children allEq(Map<R, V> params) {
return allEq(params, true);
}
/**
* ignore
*/
default <V> Children allEq(Map<R, V> params, boolean null2IsNull) {
return allEq(true, params, null2IsNull);
}
/**
* map 所有非空属性等于 =
*
* @param condition 执行条件
* @param params map 类型的参数, key 是字段名, value 是字段值
* @param null2IsNull 是否参数为 null 自动执行 isNull 方法, false 则忽略这个字段\
* @return children
*/
<V> Children allEq(boolean condition, Map<R, V> params, boolean null2IsNull);
/**
* ignore
*/
default <V> Children allEq(BiPredicate<R, V> filter, Map<R, V> params) {
return allEq(filter, params, true);
}
/**
* ignore
*/
default <V> Children allEq(BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull) {
return allEq(true, filter, params, null2IsNull);
}
/**
* 字段过滤接口,传入多参数时允许对参数进行过滤
*
* @param condition 执行条件
* @param filter 返回 true 来允许字段传入比对条件中
* @param params map 类型的参数, key 是字段名, value 是字段值
* @param null2IsNull 是否参数为 null 自动执行 isNull 方法, false 则忽略这个字段
* @return children
*/
<V> Children allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull);
/**
* ignore
*/
default Children eq(R column, Object val) {
return eq(true, column, val);
}
/**
* 等于 =
*
* @param condition 执行条件
* @param column 字段
* @param val 值
* @return children
*/
Children eq(boolean condition, R column, Object val);
/**
* ignore
*/
default Children ne(R column, Object val) {
return ne(true, column, val);
}
/**
* 不等于 <>
*
* @param condition 执行条件
* @param column 字段
* @param val 值
* @return children
*/
Children ne(boolean condition, R column, Object val);
/**
* ignore
*/
default Children gt(R column, Object val) {
return gt(true, column, val);
}
/**
* 大于 >
*
* @param condition 执行条件
* @param column 字段
* @param val 值
* @return children
*/
Children gt(boolean condition, R column, Object val);
/**
* ignore
*/
default Children ge(R column, Object val) {
return ge(true, column, val);
}
/**
* 大于等于 >=
*
* @param condition 执行条件
* @param column 字段
* @param val 值
* @return children
*/
Children ge(boolean condition, R column, Object val);
/**
* ignore
*/
default Children lt(R column, Object val) {
return lt(true, column, val);
}
/**
* 小于 <
*
* @param condition 执行条件
* @param column 字段
* @param val 值
* @return children
*/
Children lt(boolean condition, R column, Object val);
/**
* ignore
*/
default Children le(R column, Object val) {
return le(true, column, val);
}
/**
* 小于等于 <=
*
* @param condition 执行条件
* @param column 字段
* @param val 值
* @return children
*/
Children le(boolean condition, R column, Object val);
/**
* ignore
*/
default Children between(R column, Object val1, Object val2) {
return between(true, column, val1, val2);
}
/**
* BETWEEN 值1 AND 值2
*
* @param condition 执行条件
* @param column 字段
* @param val1 值1
* @param val2 值2
* @return children
*/
Children between(boolean condition, R column, Object val1, Object val2);
/**
* ignore
*/
default Children notBetween(R column, Object val1, Object val2) {
return notBetween(true, column, val1, val2);
}
/**
* NOT BETWEEN 值1 AND 值2
*
* @param condition 执行条件
* @param column 字段
* @param val1 值1
* @param val2 值2
* @return children
*/
Children notBetween(boolean condition, R column, Object val1, Object val2);
/**
* ignore
*/
default Children like(R column, Object val) {
return like(true, column, val);
}
/**
* LIKE '%值%'
*
* @param condition 执行条件
* @param column 字段
* @param val 值
* @return children
*/
Children like(boolean condition, R column, Object val);
/**
* ignore
*/
default Children notLike(R column, Object val) {
return notLike(true, column, val);
}
/**
* NOT LIKE '%值%'
*
* @param condition 执行条件
* @param column 字段
* @param val 值
* @return children
*/
Children notLike(boolean condition, R column, Object val);
/**
* ignore
*/
default Children likeLeft(R column, Object val) {
return likeLeft(true, column, val);
}
/**
* LIKE '%值'
*
* @param condition 执行条件
* @param column 字段
* @param val 值
* @return children
*/
Children likeLeft(boolean condition, R column, Object val);
/**
* ignore
*/
default Children likeRight(R column, Object val) {
return likeRight(true, column, val);
}
/**
* LIKE '值%'
*
* @param condition 执行条件
* @param column 字段
* @param val 值
* @return children
*/
Children likeRight(boolean condition, R column, Object val);
}
查询条件封装类
/*
* Copyright (c) 2011-2020, baomidou (jobob@qq.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.baomidou.mybatisplus.core.conditions;
import com.baomidou.mybatisplus.core.conditions.interfaces.Compare;
import com.baomidou.mybatisplus.core.conditions.interfaces.Func;
import com.baomidou.mybatisplus.core.conditions.interfaces.Join;
import com.baomidou.mybatisplus.core.conditions.interfaces.Nested;
import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
import com.baomidou.mybatisplus.core.enums.SqlKeyword;
import com.baomidou.mybatisplus.core.enums.SqlLike;
import com.baomidou.mybatisplus.core.toolkit.*;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlUtils;
import com.baomidou.mybatisplus.core.toolkit.sql.StringEscape;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import static com.baomidou.mybatisplus.core.enums.SqlKeyword.*;
import static com.baomidou.mybatisplus.core.enums.WrapperKeyword.APPLY;
import static com.baomidou.mybatisplus.core.enums.WrapperKeyword.BRACKET;
import static java.util.stream.Collectors.joining;
/**
* 查询条件封装
*
* @author hubin miemie HCL
* @since 2017-05-26
*/
@SuppressWarnings({"serial", "unchecked"})
public abstract class AbstractWrapper<T, R, Children extends AbstractWrapper<T, R, Children>> extends Wrapper<T>
implements Compare<Children, R>, Nested<Children, Children>, Join<Children>, Func<Children, R> {
/**
* 占位符
*/
protected final Children typedThis = (Children) this;
/**
* 必要度量
*/
protected AtomicInteger paramNameSeq;
protected Map<String, Object> paramNameValuePairs;
protected SharedString lastSql;
/**
* SQL注释
*/
protected SharedString sqlComment;
/**
* SQL起始语句
*/
protected SharedString sqlFirst;
/**
* ß
* 数据库表映射实体类
*/
private T entity;
protected MergeSegments expression;
/**
* 实体类型(主要用于确定泛型以及取TableInfo缓存)
*/
private Class<T> entityClass;
@Override
public T getEntity() {
return entity;
}
public Children setEntity(T entity) {
this.entity = entity;
return typedThis;
}
protected Class<T> getEntityClass() {
if (entityClass == null && entity != null) {
entityClass = (Class<T>) entity.getClass();
}
return entityClass;
}
public Children setEntityClass(Class<T> entityClass) {
if (entityClass != null) {
this.entityClass = entityClass;
}
return typedThis;
}
@Override
public <V> Children allEq(boolean condition, Map<R, V> params, boolean null2IsNull) {
if (condition && CollectionUtils.isNotEmpty(params)) {
params.forEach((k, v) -> {
if (StringUtils.checkValNotNull(v)) {
eq(k, v);
} else {
if (null2IsNull) {
isNull(k);
}
}
});
}
return typedThis;
}
@Override
public <V> Children allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull) {
if (condition && CollectionUtils.isNotEmpty(params)) {
params.forEach((k, v) -> {
if (filter.test(k, v)) {
if (StringUtils.checkValNotNull(v)) {
eq(k, v);
} else {
if (null2IsNull) {
isNull(k);
}
}
}
});
}
return typedThis;
}
@Override
public Children eq(boolean condition, R column, Object val) {
return addCondition(condition, column, EQ, val);
}
@Override
public Children ne(boolean condition, R column, Object val) {
return addCondition(condition, column, NE, val);
}
@Override
public Children gt(boolean condition, R column, Object val) {
return addCondition(condition, column, GT, val);
}
@Override
public Children ge(boolean condition, R column, Object val) {
return addCondition(condition, column, GE, val);
}
@Override
public Children lt(boolean condition, R column, Object val) {
return addCondition(condition, column, LT, val);
}
@Override
public Children le(boolean condition, R column, Object val) {
return addCondition(condition, column, LE, val);
}
@Override
public Children like(boolean condition, R column, Object val) {
return likeValue(condition, column, val, SqlLike.DEFAULT);
}
@Override
public Children notLike(boolean condition, R column, Object val) {
return not(condition).like(condition, column, val);
}
@Override
public Children likeLeft(boolean condition, R column, Object val) {
return likeValue(condition, column, val, SqlLike.LEFT);
}
@Override
public Children likeRight(boolean condition, R column, Object val) {
return likeValue(condition, column, val, SqlLike.RIGHT);
}
@Override
public Children between(boolean condition, R column, Object val1, Object val2) {
return doIt(condition, () -> columnToString(column), BETWEEN, () -> formatSql("{0}", val1), AND,
() -> formatSql("{0}", val2));
}
@Override
public Children notBetween(boolean condition, R column, Object val1, Object val2) {
return not(condition).between(condition, column, val1, val2);
}
@Override
public Children and(boolean condition, Consumer<Children> consumer) {
return and(condition).addNestedCondition(condition, consumer);
}
@Override
public Children or(boolean condition, Consumer<Children> consumer) {
return or(condition).addNestedCondition(condition, consumer);
}
@Override
public Children nested(boolean condition, Consumer<Children> consumer) {
return addNestedCondition(condition, consumer);
}
@Override
public Children or(boolean condition) {
return doIt(condition, OR);
}
@Override
public Children apply(boolean condition, String applySql, Object... value) {
return doIt(condition, APPLY, () -> formatSql(applySql, value));
}
@Override
public Children last(boolean condition, String lastSql) {
if (condition) {
this.lastSql.setStringValue(StringPool.SPACE + lastSql);
}
return typedThis;
}
@Override
public Children comment(boolean condition, String comment) {
if (condition) {
this.sqlComment.setStringValue(comment);
}
return typedThis;
}
@Override
public Children first(boolean condition, String firstSql) {
if (condition) {
this.sqlFirst.setStringValue(firstSql);
}
return typedThis;
}
@Override
public Children exists(boolean condition, String existsSql) {
return doIt(condition, EXISTS, () -> String.format("(%s)", existsSql));
}
@Override
public Children notExists(boolean condition, String notExistsSql) {
return not(condition).exists(condition, notExistsSql);
}
@Override
public Children isNull(boolean condition, R column) {
return doIt(condition, () -> columnToString(column), IS_NULL);
}
@Override
public Children isNotNull(boolean condition, R column) {
return doIt(condition, () -> columnToString(column), IS_NOT_NULL);
}
@Override
public Children in(boolean condition, R column, Collection<?> coll) {
return doIt(condition, () -> columnToString(column), IN, inExpression(coll));
}
@Override
public Children notIn(boolean condition, R column, Collection<?> coll) {
return not(condition).in(condition, column, coll);
}
@Override
public Children inSql(boolean condition, R column, String inValue) {
return doIt(condition, () -> columnToString(column), IN, () -> String.format("(%s)", inValue));
}
@Override
public Children notInSql(boolean condition, R column, String inValue) {
return not(condition).inSql(condition, column, inValue);
}
@Override
public Children groupBy(boolean condition, R... columns) {
if (ArrayUtils.isEmpty(columns)) {
return typedThis;
}
return doIt(condition, GROUP_BY,
() -> columns.length == 1 ? columnToString(columns[0]) : columnsToString(columns));
}
@Override
public Children orderBy(boolean condition, boolean isAsc, R... columns) {
if (ArrayUtils.isEmpty(columns)) {
return typedThis;
}
SqlKeyword mode = isAsc ? ASC : DESC;
for (R column : columns) {
doIt(condition, ORDER_BY, () -> columnToString(column), mode);
}
return typedThis;
}
@Override
public Children having(boolean condition, String sqlHaving, Object... params) {
return doIt(condition, HAVING, () -> formatSqlIfNeed(condition, sqlHaving, params));
}
@Override
public Children func(boolean condition, Consumer<Children> consumer) {
if (condition) {
consumer.accept(typedThis);
}
return typedThis;
}
/**
* 内部自用
* <p>NOT 关键词</p>
*/
protected Children not(boolean condition) {
return doIt(condition, NOT);
}
/**
* 内部自用
* <p>拼接 AND</p>
*/
protected Children and(boolean condition) {
return doIt(condition, AND);
}
/**
* 内部自用
* <p>拼接 LIKE 以及 值</p>
*/
protected Children likeValue(boolean condition, R column, Object val, SqlLike sqlLike) {
return doIt(condition, () -> columnToString(column), LIKE, () -> formatSql("{0}", SqlUtils.concatLike(val, sqlLike)));
}
/**
* 普通查询条件
*
* @param condition 是否执行
* @param column 属性
* @param sqlKeyword SQL 关键词
* @param val 条件值
*/
protected Children addCondition(boolean condition, R column, SqlKeyword sqlKeyword, Object val) {
return doIt(condition, () -> columnToString(column), sqlKeyword, () -> formatSql("{0}", val));
}
/**
* 多重嵌套查询条件
*
* @param condition 查询条件值
*/
protected Children addNestedCondition(boolean condition, Consumer<Children> consumer) {
if (condition) {
final Children instance = instance();
consumer.accept(instance);
return doIt(true, BRACKET, instance);
}
return typedThis;
}
/**
* 子类返回一个自己的新对象
*/
protected abstract Children instance();
/**
* 格式化SQL
*
* @param sqlStr SQL语句部分
* @param params 参数集
* @return sql
*/
protected final String formatSql(String sqlStr, Object... params) {
return formatSqlIfNeed(true, sqlStr, params);
}
/**
* <p>
* 根据需要格式化SQL<br>
* <br>
* Format SQL for methods: EntityQ<T>.where/and/or...("name={0}", value);
* ALL the {<b>i</b>} will be replaced with #{MPGENVAL<b>i</b>}<br>
* <br>
* ew.where("sample_name=<b>{0}</b>", "haha").and("sample_age ><b>{0}</b>
* and sample_age<<b>{1}</b>", 18, 30) <b>TO</b>
* sample_name=<b>#{MPGENVAL1}</b> and sample_age>#<b>{MPGENVAL2}</b> and
* sample_age<<b>#{MPGENVAL3}</b><br>
* </p>
*
* @param need 是否需要格式化
* @param sqlStr SQL语句部分
* @param params 参数集
* @return sql
*/
protected final String formatSqlIfNeed(boolean need, String sqlStr, Object... params) {
if (!need || StringUtils.isBlank(sqlStr)) {
return null;
}
if (ArrayUtils.isNotEmpty(params)) {
for (int i = 0; i < params.length; ++i) {
String genParamName = Constants.WRAPPER_PARAM + paramNameSeq.incrementAndGet();
sqlStr = sqlStr.replace(String.format("{%s}", i),
String.format(Constants.WRAPPER_PARAM_FORMAT, Constants.WRAPPER, genParamName));
paramNameValuePairs.put(genParamName, params[i]);
}
}
return sqlStr;
}
/**
* 获取in表达式 包含括号
*
* @param value 集合
*/
private ISqlSegment inExpression(Collection<?> value) {
return () -> value.stream().map(i -> formatSql("{0}", i))
.collect(joining(StringPool.COMMA, StringPool.LEFT_BRACKET, StringPool.RIGHT_BRACKET));
}
/**
* 必要的初始化
*/
protected void initNeed() {
paramNameSeq = new AtomicInteger(0);
paramNameValuePairs = new HashMap<>(16);
expression = new MergeSegments();
lastSql = SharedString.emptyString();
sqlComment = SharedString.emptyString();
sqlFirst = SharedString.emptyString();
}
@Override
public void clear() {
entity = null;
paramNameSeq.set(0);
paramNameValuePairs.clear();
expression.clear();
lastSql.toEmpty();
sqlComment.toEmpty();
sqlFirst.toEmpty();
}
/**
* 对sql片段进行组装
*
* @param condition 是否执行
* @param sqlSegments sql片段数组
* @return children
*/
protected Children doIt(boolean condition, ISqlSegment... sqlSegments) {
if (condition) {
expression.add(sqlSegments);
}
return typedThis;
}
@Override
public String getSqlSegment() {
return expression.getSqlSegment() + lastSql.getStringValue();
}
@Override
public String getSqlComment() {
if (StringUtils.isNotBlank(sqlComment.getStringValue())) {
return "/*" + StringEscape.escapeRawString(sqlComment.getStringValue()) + "*/";
}
return null;
}
@Override
public String getSqlFirst() {
if (StringUtils.isNotBlank(sqlFirst.getStringValue())) {
return StringEscape.escapeRawString(sqlFirst.getStringValue());
}
return null;
}
@Override
public MergeSegments getExpression() {
return expression;
}
public Map<String, Object> getParamNameValuePairs() {
return paramNameValuePairs;
}
/**
* 获取 columnName
*/
protected String columnToString(R column) {
return (String) column;
}
/**
* 多字段转换为逗号 "," 分割字符串
*
* @param columns 多字段
*/
protected String columnsToString(R... columns) {
return Arrays.stream(columns).map(this::columnToString).collect(joining(StringPool.COMMA));
}
@Override
@SuppressWarnings("all")
public Children clone() {
return SerializationUtils.clone(typedThis);
}
}
where条件抽象类
所有包装类都继承此抽象类,此抽象类代理了大部分生成 where 条件的方法
/*
* Copyright (c) 2011-2020, baomidou (jobob@qq.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.baomidou.mybatisplus.extension.conditions;
import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.interfaces.Compare;
import com.baomidou.mybatisplus.core.conditions.interfaces.Func;
import com.baomidou.mybatisplus.core.conditions.interfaces.Join;
import com.baomidou.mybatisplus.core.conditions.interfaces.Nested;
import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
import java.util.Collection;
import java.util.Map;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
/**
* 所有包装类都继承此抽象类,此抽象类代理了大部分生成 where 条件的方法
* <li> 泛型: Children ,表示子类 </li>
* <li> 泛型: Param ,表示子类所包装的具体 Wrapper 类型 </li>
*
* @author miemie
* @since 2018-12-19
*/
@SuppressWarnings({"serial", "unchecked"})
public abstract class AbstractChainWrapper<T, R, Children extends AbstractChainWrapper<T, R, Children, Param>, Param>
extends Wrapper<T> implements Compare<Children, R>, Func<Children, R>, Join<Children>, Nested<Param, Children> {
protected final Children typedThis = (Children) this;
/**
* 子类所包装的具体 Wrapper 类型
*/
protected Param wrapperChildren;
/**
* 必须的构造函数
*/
public AbstractChainWrapper() {
}
@SuppressWarnings("rawtypes")
public AbstractWrapper getWrapper() {
return (AbstractWrapper) wrapperChildren;
}
public Children setEntity(T entity) {
getWrapper().setEntity(entity);
return typedThis;
}
public Children setEntityClass(Class<T> entityClass) {
getWrapper().setEntityClass(entityClass);
return typedThis;
}
@Override
public <V> Children allEq(boolean condition, Map<R, V> params, boolean null2IsNull) {
getWrapper().allEq(condition, params, null2IsNull);
return typedThis;
}
@Override
public <V> Children allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull) {
getWrapper().allEq(condition, filter, params, null2IsNull);
return typedThis;
}
@Override
public Children eq(boolean condition, R column, Object val) {
getWrapper().eq(condition, column, val);
return typedThis;
}
@Override
public Children ne(boolean condition, R column, Object val) {
getWrapper().ne(condition, column, val);
return typedThis;
}
@Override
public Children gt(boolean condition, R column, Object val) {
getWrapper().gt(condition, column, val);
return typedThis;
}
@Override
public Children ge(boolean condition, R column, Object val) {
getWrapper().ge(condition, column, val);
return typedThis;
}
@Override
public Children lt(boolean condition, R column, Object val) {
getWrapper().lt(condition, column, val);
return typedThis;
}
@Override
public Children le(boolean condition, R column, Object val) {
getWrapper().le(condition, column, val);
return typedThis;
}
@Override
public Children between(boolean condition, R column, Object val1, Object val2) {
getWrapper().between(condition, column, val1, val2);
return typedThis;
}
@Override
public Children notBetween(boolean condition, R column, Object val1, Object val2) {
getWrapper().notBetween(condition, column, val1, val2);
return typedThis;
}
@Override
public Children like(boolean condition, R column, Object val) {
getWrapper().like(condition, column, val);
return typedThis;
}
@Override
public Children notLike(boolean condition, R column, Object val) {
getWrapper().notLike(condition, column, val);
return typedThis;
}
@Override
public Children likeLeft(boolean condition, R column, Object val) {
getWrapper().likeLeft(condition, column, val);
return typedThis;
}
@Override
public Children likeRight(boolean condition, R column, Object val) {
getWrapper().likeRight(condition, column, val);
return typedThis;
}
@Override
public Children isNull(boolean condition, R column) {
getWrapper().isNull(condition, column);
return typedThis;
}
@Override
public Children isNotNull(boolean condition, R column) {
getWrapper().isNotNull(condition, column);
return typedThis;
}
@Override
public Children in(boolean condition, R column, Collection<?> coll) {
getWrapper().in(condition, column, coll);
return typedThis;
}
@Override
public Children notIn(boolean condition, R column, Collection<?> coll) {
getWrapper().notIn(condition, column, coll);
return typedThis;
}
@Override
public Children inSql(boolean condition, R column, String inValue) {
getWrapper().inSql(condition, column, inValue);
return typedThis;
}
@Override
public Children notInSql(boolean condition, R column, String inValue) {
getWrapper().notInSql(condition, column, inValue);
return typedThis;
}
@Override
public Children groupBy(boolean condition, R... columns) {
getWrapper().groupBy(condition, columns);
return typedThis;
}
@Override
public Children orderBy(boolean condition, boolean isAsc, R... columns) {
getWrapper().orderBy(condition, isAsc, columns);
return typedThis;
}
@Override
public Children having(boolean condition, String sqlHaving, Object... params) {
getWrapper().having(condition, sqlHaving, params);
return typedThis;
}
@Override
public Children func(boolean condition, Consumer<Children> consumer) {
getWrapper().func(condition, consumer);
return typedThis;
}
@Override
public Children or(boolean condition) {
getWrapper().or(condition);
return typedThis;
}
@Override
public Children apply(boolean condition, String applySql, Object... value) {
getWrapper().apply(condition, applySql, value);
return typedThis;
}
@Override
public Children last(boolean condition, String lastSql) {
getWrapper().last(condition, lastSql);
return typedThis;
}
@Override
public Children comment(boolean condition, String comment) {
getWrapper().comment(condition, comment);
return typedThis;
}
@Override
public Children first(boolean condition, String firstSql) {
getWrapper().first(condition, firstSql);
return typedThis;
}
@Override
public Children exists(boolean condition, String existsSql) {
getWrapper().exists(condition, existsSql);
return typedThis;
}
@Override
public Children notExists(boolean condition, String notExistsSql) {
getWrapper().notExists(condition, notExistsSql);
return typedThis;
}
@Override
public Children and(boolean condition, Consumer<Param> consumer) {
getWrapper().and(condition, consumer);
return typedThis;
}
@Override
public Children or(boolean condition, Consumer<Param> consumer) {
getWrapper().or(condition, consumer);
return typedThis;
}
@Override
public Children nested(boolean condition, Consumer<Param> consumer) {
getWrapper().nested(condition, consumer);
return typedThis;
}
@Override
public String getSqlSegment() {
throw ExceptionUtils.mpe("can not use this method for \"%s\"", "getSqlSegment");
}
@Override
public String getSqlFirst() {
throw ExceptionUtils.mpe("can not use this method for \"%s\"", "getSqlFirst");
}
@Override
public String getSqlSelect() {
throw ExceptionUtils.mpe("can not use this method for \"%s\"", "getSqlSelect");
}
@Override
public String getSqlSet() {
throw ExceptionUtils.mpe("can not use this method for \"%s\"", "getSqlSet");
}
@Override
public String getSqlComment() {
throw ExceptionUtils.mpe("can not use this method for \"%s\"", "getSqlComment");
}
@Override
public String getTargetSql() {
throw ExceptionUtils.mpe("can not use this method for \"%s\"", "getTargetSql");
}
@Override
public T getEntity() {
throw ExceptionUtils.mpe("can not use this method for \"%s\"", "getEntity");
}
@Override
public MergeSegments getExpression() {
throw ExceptionUtils.mpe("can not use this method for \"%s\"", "getExpression");
}
@Override
public String getCustomSqlSegment() {
throw ExceptionUtils.mpe("can not use this method for \"%s\"", "getCustomSqlSegment");
}
@Override
public void clear() {
throw ExceptionUtils.mpe("can not use this method for \"%s\"", "clear");
}
@Override
protected Object clone() throws CloneNotSupportedException {
throw ExceptionUtils.mpe("can not use this method for \"%s\"", "clone");
}
}
分页需要配置分页拦截器
1.可以在每个模块的启动累加
package com.sb.mall.goods;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
/**
* mall-goods-service启动类
*/
@SpringBootApplication
@MapperScan(basePackages = {"com.sb.mall.goods.mapper"})
/*
MapperScan扫描到包,而不是类,加类名它会以为有一个BrandMapper的包,报错:
* NoSuchBeanDefinitionException: No qualifying bean of type 'com.sb.mall.goods.mapper.BrandMapper' available
*/
//@MapperScan(basePackages = {"com.sb.mall.goods.mapper.BrandMapper"})
public class MallGoodsApplication {
public static void main(String[] args) {
SpringApplication.run(MallGoodsApplication.class, args);
}
/**
* 分页拦截器
* @return
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
//设置数据库类型
paginationInterceptor.setDbType(DbType.MYSQL);
return paginationInterceptor;
}
}
2.直接加在dependency(我项目的公共工程)中,用@configuration做初始化启动类
package com.sb.mall.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class StartConfig {
/**
* 分页拦截器
* @return
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
//设置数据库类型
paginationInterceptor.setDbType(DbType.MYSQL);
return paginationInterceptor;
}
}
伪代码
controller
/**
* 条件分页查询
*
* @param currentPage
* @param size
* @param brand
* @return
*/
@PostMapping(value = "/list/{page}/{size}")
public RespResult<Page<Brand>> list(
@PathVariable(value = "page") Long currentPage,
@PathVariable(value = "size") Long size,
@RequestBody(required = false) Brand brand) {
// 分页查询
Page<Brand> brandPage = brandService.queryPageList(currentPage, size, brand);
return RespResult.ok(brandPage);
}
serviceImpl
/**
* 条件分页查询
* @param currentPage
* @param size
* @param brand
* @return
*/
@Override
public Page<Brand> queryPageList(Long currentPage, Long size, Brand brand) {
// 封装查询条件
Page<Brand> page = brandMapper.selectPage(
new Page<Brand>(currentPage, size),
new QueryWrapper<Brand>()
.like("name", brand.getName())
.eq("initial",brand.getInitial())
);
return page;
}