目录
比较典型就是数据库地址配置有误,导致服务启动不起来,需要我们连接检查,二报错却会显示是mapper或者sql注入等错误,需要格外注意。
由于字段映射出现的错误,由于Mapper作为数据库和Entity的桥梁,字段检查是必须的,随便一个写错,系统及可能跑不起来。
/**
* Copyright (c) 2011-2016, hubin ([email protected]).
* <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>
* http://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.service.impl;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.entity.TableInfo;
import com.baomidou.mybatisplus.enums.SqlMethod;
import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.baomidou.mybatisplus.mapper.Condition;
import com.baomidou.mybatisplus.mapper.SqlHelper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.IService;
import com.baomidou.mybatisplus.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.toolkit.MapUtils;
import com.baomidou.mybatisplus.toolkit.ReflectionKit;
import com.baomidou.mybatisplus.toolkit.StringUtils;
import com.baomidou.mybatisplus.toolkit.TableInfoHelper;
/**
* <p>
* IService 实现类( 泛型:M 是 mapper 对象,T 是实体 , PK 是主键泛型 )
* </p>
*
* @author hubin
* @Date 2016-04-20
*/
public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
private static final Log logger = LogFactory.getLog(ServiceImpl.class);
@Autowired
protected M baseMapper;
/**
* <p>
* 判断数据库操作是否成功
* </p>
* <p>
* 注意!! 该方法为 Integer 判断,不可传入 int 基本类型
* </p>
*
* @param result 数据库操作返回影响条数
* @return boolean
*/
protected static boolean retBool(Integer result) {
return SqlHelper.retBool(result);
}
@SuppressWarnings("unchecked")
protected Class<T> currentModelClass() {
return ReflectionKit.getSuperClassGenricType(getClass(), 1);
}
/**
* <p>
* 批量操作 SqlSession
* </p>
*/
protected SqlSession sqlSessionBatch() {
return SqlHelper.sqlSessionBatch(currentModelClass());
}
/**
* 获取SqlStatement
*
* @param sqlMethod
* @return
*/
protected String sqlStatement(SqlMethod sqlMethod) {
return SqlHelper.table(currentModelClass()).getSqlStatement(sqlMethod.getMethod());
}
@Transactional
public boolean insert(T entity) {
return retBool(baseMapper.insert(entity));
}
@Transactional
public boolean insertAllColumn(T entity) {
return retBool(baseMapper.insertAllColumn(entity));
}
@Transactional
public boolean insertBatch(List<T> entityList) {
return insertBatch(entityList, 30);
}
/**
* 批量插入
*
* @param entityList
* @param batchSize
* @return
*/
@Transactional
public boolean insertBatch(List<T> entityList, int batchSize) {
if (CollectionUtils.isEmpty(entityList)) {
throw new IllegalArgumentException("Error: entityList must not be empty");
}
try (SqlSession batchSqlSession = sqlSessionBatch()) {
int size = entityList.size();
String sqlStatement = sqlStatement(SqlMethod.INSERT_ONE);
for (int i = 0; i < size; i++) {
batchSqlSession.insert(sqlStatement, entityList.get(i));
if (i >= 1 && i % batchSize == 0) {
batchSqlSession.flushStatements();
}
}
batchSqlSession.flushStatements();
} catch (Throwable e) {
throw new MybatisPlusException("Error: Cannot execute insertBatch Method. Cause", e);
}
return true;
}
/**
* <p>
* TableId 注解存在更新记录,否插入一条记录
* </p>
*
* @param entity 实体对象
* @return boolean
*/
@Transactional
public boolean insertOrUpdate(T entity) {
if (null != entity) {
Class<?> cls = entity.getClass();
TableInfo tableInfo = TableInfoHelper.getTableInfo(cls);
if (null != tableInfo && StringUtils.isNotEmpty(tableInfo.getKeyProperty())) {
Object idVal = ReflectionKit.getMethodValue(cls, entity, tableInfo.getKeyProperty());
if (StringUtils.checkValNull(idVal)) {
return insert(entity);
} else {
/*
* 更新成功直接返回,失败执行插入逻辑
*/
return updateById(entity) || insert(entity);
}
} else {
throw new MybatisPlusException("Error: Can not execute. Could not find @TableId.");
}
}
return false;
}
@Transactional
public boolean insertOrUpdateAllColumn(T entity) {
if (null != entity) {
Class<?> cls = entity.getClass();
TableInfo tableInfo = TableInfoHelper.getTableInfo(cls);
if (null != tableInfo && StringUtils.isNotEmpty(tableInfo.getKeyProperty())) {
Object idVal = ReflectionKit.getMethodValue(cls, entity, tableInfo.getKeyProperty());
if (StringUtils.checkValNull(idVal)) {
return insertAllColumn(entity);
} else {
/*
* 更新成功直接返回,失败执行插入逻辑
*/
return updateAllColumnById(entity) || insertAllColumn(entity);
}
} else {
throw new MybatisPlusException("Error: Can not execute. Could not find @TableId.");
}
}
return false;
}
@Transactional
public boolean insertOrUpdateBatch(List<T> entityList) {
return insertOrUpdateBatch(entityList, 30);
}
@Transactional
public boolean insertOrUpdateBatch(List<T> entityList, int batchSize) {
return insertOrUpdateBatch(entityList, batchSize, true);
}
@Transactional
public boolean insertOrUpdateAllColumnBatch(List<T> entityList) {
return insertOrUpdateBatch(entityList, 30, false);
}
@Transactional
public boolean insertOrUpdateAllColumnBatch(List<T> entityList, int batchSize) {
return insertOrUpdateBatch(entityList, batchSize, false);
}
/**
* 批量插入修改
*
* @param entityList 实体对象列表
* @param batchSize 批量刷新个数
* @param selective 是否滤掉空字段
* @return boolean
*/
private boolean insertOrUpdateBatch(List<T> entityList, int batchSize, boolean selective) {
if (CollectionUtils.isEmpty(entityList)) {
throw new IllegalArgumentException("Error: entityList must not be empty");
}
try (SqlSession batchSqlSession = sqlSessionBatch()) {
int size = entityList.size();
for (int i = 0; i < size; i++) {
if (selective) {
insertOrUpdate(entityList.get(i));
} else {
insertOrUpdateAllColumn(entityList.get(i));
}
if (i >= 1 && i % batchSize == 0) {
batchSqlSession.flushStatements();
}
}
batchSqlSession.flushStatements();
} catch (Throwable e) {
throw new MybatisPlusException("Error: Cannot execute insertOrUpdateBatch Method. Cause", e);
}
return true;
}
@Transactional
public boolean deleteById(Serializable id) {
return retBool(baseMapper.deleteById(id));
}
@Transactional
public boolean deleteByMap(Map<String, Object> columnMap) {
if (MapUtils.isEmpty(columnMap)) {
throw new MybatisPlusException("deleteByMap columnMap is empty.");
}
return retBool(baseMapper.deleteByMap(columnMap));
}
@Transactional
public boolean delete(Wrapper<T> wrapper) {
return retBool(baseMapper.delete(wrapper));
}
@Transactional
public boolean deleteBatchIds(List<? extends Serializable> idList) {
return retBool(baseMapper.deleteBatchIds(idList));
}
@Transactional
public boolean updateById(T entity) {
return retBool(baseMapper.updateById(entity));
}
@Transactional
public boolean updateAllColumnById(T entity) {
return retBool(baseMapper.updateAllColumnById(entity));
}
@Transactional
public boolean update(T entity, Wrapper<T> wrapper) {
return retBool(baseMapper.update(entity, wrapper));
}
@Transactional
public boolean updateBatchById(List<T> entityList) {
return updateBatchById(entityList, 30);
}
@Transactional
public boolean updateBatchById(List<T> entityList, int batchSize) {
return updateBatchById(entityList, batchSize, true);
}
@Transactional
public boolean updateAllColumnBatchById(List<T> entityList) {
return updateAllColumnBatchById(entityList, 30);
}
@Transactional
public boolean updateAllColumnBatchById(List<T> entityList, int batchSize) {
return updateBatchById(entityList, batchSize, false);
}
/**
* 根据主键ID进行批量修改
*
* @param entityList 实体对象列表
* @param batchSize 批量刷新个数
* @param selective 是否滤掉空字段
* @return boolean
*/
private boolean updateBatchById(List<T> entityList, int batchSize, boolean selective) {
if (CollectionUtils.isEmpty(entityList)) {
throw new IllegalArgumentException("Error: entityList must not be empty");
}
try (SqlSession batchSqlSession = sqlSessionBatch()) {
int size = entityList.size();
SqlMethod sqlMethod = selective ? SqlMethod.UPDATE_BY_ID : SqlMethod.UPDATE_ALL_COLUMN_BY_ID;
String sqlStatement = sqlStatement(sqlMethod);
for (int i = 0; i < size; i++) {
MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>();
param.put("et", entityList.get(i));
batchSqlSession.update(sqlStatement, param);
if (i >= 1 && i % batchSize == 0) {
batchSqlSession.flushStatements();
}
}
batchSqlSession.flushStatements();
} catch (Throwable e) {
throw new MybatisPlusException("Error: Cannot execute updateBatchById Method. Cause", e);
}
return true;
}
public T selectById(Serializable id) {
return baseMapper.selectById(id);
}
public List<T> selectBatchIds(List<? extends Serializable> idList) {
return baseMapper.selectBatchIds(idList);
}
public List<T> selectByMap(Map<String, Object> columnMap) {
return baseMapper.selectByMap(columnMap);
}
public T selectOne(Wrapper<T> wrapper) {
return SqlHelper.getObject(baseMapper.selectList(wrapper));
}
public Map<String, Object> selectMap(Wrapper<T> wrapper) {
return SqlHelper.getObject(baseMapper.selectMaps(wrapper));
}
public Object selectObj(Wrapper<T> wrapper) {
return SqlHelper.getObject(baseMapper.selectObjs(wrapper));
}
public int selectCount(Wrapper<T> wrapper) {
return SqlHelper.retCount(baseMapper.selectCount(wrapper));
}
public List<T> selectList(Wrapper<T> wrapper) {
return baseMapper.selectList(wrapper);
}
@SuppressWarnings("unchecked")
public Page<T> selectPage(Page<T> page) {
return selectPage(page, Condition.EMPTY);
}
public List<Map<String, Object>> selectMaps(Wrapper<T> wrapper) {
return baseMapper.selectMaps(wrapper);
}
public List<Object> selectObjs(Wrapper<T> wrapper) {
return baseMapper.selectObjs(wrapper);
}
@SuppressWarnings({"rawtypes", "unchecked"})
public Page<Map<String, Object>> selectMapsPage(Page page, Wrapper<T> wrapper) {
SqlHelper.fillWrapper(page, wrapper);
page.setRecords(baseMapper.selectMapsPage(page, wrapper));
return page;
}
public Page<T> selectPage(Page<T> page, Wrapper<T> wrapper) {
SqlHelper.fillWrapper(page, wrapper);
page.setRecords(baseMapper.selectPage(page, wrapper));
return page;
}
}
mybatisplus提供了增删改查的接口和实现类,上图,我们只需要继承,并构造实体条件就行但是要特备注意下面几个方法
(1)
@Transactional
public boolean updateById(T entity) {
return retBool(baseMapper.updateById(entity));
}
传入的实体类必须数据表必须有ID列,否则更新会直接报错,所以这个方法开发中并不太常用,而是用
@Transactional
public boolean update(T entity, Wrapper<T> wrapper) {
return retBool(baseMapper.update(entity, wrapper));
}
(2)
@Transactional
public boolean deleteById(Serializable id) {
return retBool(baseMapper.deleteById(id));
}
这个方法也是一样,必须有列ID才行。
(3)
/**
* 批量插入
*
* @param entityList
* @param batchSize
* @return
*/
@Transactional
public boolean insertBatch(List<T> entityList, int batchSize) {
if (CollectionUtils.isEmpty(entityList)) {
throw new IllegalArgumentException("Error: entityList must not be empty");
}
try (SqlSession batchSqlSession = sqlSessionBatch()) {
int size = entityList.size();
String sqlStatement = sqlStatement(SqlMethod.INSERT_ONE);
for (int i = 0; i < size; i++) {
batchSqlSession.insert(sqlStatement, entityList.get(i));
if (i >= 1 && i % batchSize == 0) {
batchSqlSession.flushStatements();
}
}
batchSqlSession.flushStatements();
} catch (Throwable e) {
throw new MybatisPlusException("Error: Cannot execute insertBatch Method. Cause", e);
}
return true;
}
这个方法的,大家可以的看到,当传入空集合或者null的时候,直接抛出非法参数异常,所以在批量插入之前一定要对集合排空判断。
(4)
public Page<T> selectPage(Page<T> page, Wrapper<T> wrapper) {
SqlHelper.fillWrapper(page, wrapper);
page.setRecords(baseMapper.selectPage(page, wrapper));
return page;
}
Mabits的分页查询是个好方法,很方便帮我们查询出总数量和当前页集合,前端查询页面展示很方便,但是要注意,必须创建page过滤器才有效
package com.yxytech.parkingcloud.efss.config;
import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisPlusConfig {
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
paginationInterceptor.setLocalPage(true);// 开启 PageHelper 的支持
return paginationInterceptor;
}
}
Mybatis开发中不需要你写SQL语句,但是当涉及到多表的关联查询时候,只能通过自己写SQL了,他的EntityWrapper(条件构造器)就不支持了,所以就会出现以下几种:
(1)在Service接口以Mybatis注解的形式编写:
public interface IBlackFileStatusVersionService extends IBaseService<BlackFileStatusVersion> {
@Select("TRUNCATE TABLE U03_StatusList_Version")
void deleteAll();
BlackFileStatusVersion constructBlackVersion(String key, String issuerVersion, int dif, int recordCount, String zipFilePath);
boolean insert2DB(CardStatuVersion version, String fileName);
}
如上:清空表里数据,特别注意语句是够正确,最好在数据库测试执行成功后,再粘贴到代码里
(2)在xxxMapper.xml文件里编写复杂的SQL语句(推荐)
这种方法可能需要传参数:@Param
public interface XXXInfoStateMapper{
List<XXXinfo> selectListByPage(@Param("start") long start, @Param("end") long end);
}
<select id="selectListByPage" resultType="com.XXX.XXX.front.entity.XXXiNFO">
SELECT *
from xxx_TRAN_ZH t1
inner join xxx_PROCESS_STATE t2 on t1.MID = t2.MID
where TRANS_SERIAL_SN is not null
and t2.PROCESS_RESULT = -2 and t1.MID >= #{start} and t1.MID < #{end} and t1.ENT_OccurTime > '2018-01-01 00:00:00'
</select>
这种查询也很容易错,最好还是先在数据库写好执行过了再粘上来。参数#{}的方式传入xml
@RestController
@RequestMapping("/front")
public class XXXFrontController extends BaseController {
}
之前项目就出现调试很久,HTTP请求接口就是收不到,后来发现@RestController的问题,@Controller是可以返回视图解析器可以解析的Html,jsp页面的,而@RestController相当于@Controller和@ResponseBody结合体,返回的结果以接口方法的return的值。一般项目都是以json的格式返回的,现在很少通过服务端配置进行页面跳转,对多移动开发自由度也很不好,所以建议大家还是使用@RestController注解。
最后,在开发中还会遇到各种问题,会尽量补充上来,谢谢。