目录

一、首先介绍一下开发框架,SpringBoot+Mybatis,SpringBoot集成了Tomcat因此,不需要下载Tomcat服务运行,开发完直接build出jar包运行即可,Mybatis-Plus增加条件构造器EntityWrapper很好用,可以把需要查询的条件全部放构造器里,执行就好。

二、下面回顾一下开发中遇到的一些坑,希望互相参考

2.1 properties配置文件错误导致无法启动

比较典型就是数据库地址配置有误,导致服务启动不起来,需要我们连接检查,二报错却会显示是mapper或者sql注入等错误,需要格外注意。

2.2 Mapper.xml文件映射出错

由于字段映射出现的错误,由于Mapper作为数据库和Entity的桥梁,字段检查是必须的,随便一个写错,系统及可能跑不起来。

2.3 Mybatis-Plus 语句异常总结

​
/*** Copyright (c) 2011-2016, hubin (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>* 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);@Autowiredprotected 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());}@Transactionalpublic boolean insert(T entity) {return retBool(baseMapper.insert(entity));}@Transactionalpublic boolean insertAllColumn(T entity) {return retBool(baseMapper.insertAllColumn(entity));}@Transactionalpublic boolean insertBatch(List<T> entityList) {return insertBatch(entityList, 30);}/*** 批量插入** @param entityList* @param batchSize* @return*/@Transactionalpublic 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*/@Transactionalpublic 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;}@Transactionalpublic 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;}@Transactionalpublic boolean insertOrUpdateBatch(List<T> entityList) {return insertOrUpdateBatch(entityList, 30);}@Transactionalpublic boolean insertOrUpdateBatch(List<T> entityList, int batchSize) {return insertOrUpdateBatch(entityList, batchSize, true);}@Transactionalpublic boolean insertOrUpdateAllColumnBatch(List<T> entityList) {return insertOrUpdateBatch(entityList, 30, false);}@Transactionalpublic 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;}@Transactionalpublic boolean deleteById(Serializable id) {return retBool(baseMapper.deleteById(id));}@Transactionalpublic boolean deleteByMap(Map<String, Object> columnMap) {if (MapUtils.isEmpty(columnMap)) {throw new MybatisPlusException("deleteByMap columnMap is empty.");}return retBool(baseMapper.deleteByMap(columnMap));}@Transactionalpublic boolean delete(Wrapper<T> wrapper) {return retBool(baseMapper.delete(wrapper));}@Transactionalpublic boolean deleteBatchIds(List<? extends Serializable> idList) {return retBool(baseMapper.deleteBatchIds(idList));}@Transactionalpublic boolean updateById(T entity) {return retBool(baseMapper.updateById(entity));}@Transactionalpublic boolean updateAllColumnById(T entity) {return retBool(baseMapper.updateAllColumnById(entity));}@Transactionalpublic boolean update(T entity, Wrapper<T> wrapper) {return retBool(baseMapper.update(entity, wrapper));}@Transactionalpublic boolean updateBatchById(List<T> entityList) {return updateBatchById(entityList, 30);}@Transactionalpublic boolean updateBatchById(List<T> entityList, int batchSize) {return updateBatchById(entityList, batchSize, true);}@Transactionalpublic boolean updateAllColumnBatchById(List<T> entityList) {return updateAllColumnBatchById(entityList, 30);}@Transactionalpublic 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 {@Beanpublic PaginationInterceptor paginationInterceptor() {PaginationInterceptor paginationInterceptor = new PaginationInterceptor();paginationInterceptor.setLocalPage(true);// 开启 PageHelper 的支持return paginationInterceptor;}
}

2.4 SQL语句异常

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 t1inner join xxx_PROCESS_STATE t2 on t1.MID = t2.MIDwhere TRANS_SERIAL_SN is not nulland t2.PROCESS_RESULT = -2 and t1.MID &gt;= #{start} and t1.MID &lt; #{end} and t1.ENT_OccurTime > '2018-01-01 00:00:00'</select>​

这种查询也很容易错,最好还是先在数据库写好执行过了再粘上来。参数#{}的方式传入xml

2.5 SpringBoot的接口

​
@RestController
@RequestMapping("/front")
public class XXXFrontController extends BaseController {
}​

之前项目就出现调试很久,HTTP请求接口就是收不到,后来发现@RestController的问题,@Controller是可以返回视图解析器可以解析的Html,jsp页面的,而@RestController相当于@Controller和@ResponseBody结合体,返回的结果以接口方法的return的值。一般项目都是以json的格式返回的,现在很少通过服务端配置进行页面跳转,对多移动开发自由度也很不好,所以建议大家还是使用@RestController注解。

最后,在开发中还会遇到各种问题,会尽量补充上来,谢谢。


后台SpringBoot + Mybatis开发遇到的一些坑相关推荐

  1. 基于SpringBoot+Mybatis开发的前后端ERP系统Saas平台

    源码介绍 基于SpringBoot+Mybatis开发的前后端ERP系统Saas平台 ,专注于中小微企业的ERP软件.进销存系统,是一套基于SpringBoot2.2.0, Mybatis, JWT, ...

  2. 微信小程序后端mysql数据库_微信小程序后台springboot+mybatis+mysql“采坑”集锦

    "采坑"错误集锦 1.service层 错误描述:2019-04-14 22:09:52.027 ERROR 8416 --- [nio-8082-exec-5] o.a.c.c. ...

  3. 「newbee-mall新蜂商城开源啦」SpringBoot+MyBatis开发JavaWeb线上商城项目

    我的想法很简单,就是做一个大家都能运行的商城项目,而不是缺胳膊少腿的项目,不求有多么完善,也不求有多少技术栈,我目前的想法就是大家都可以运行它.使用它,至于完善它嘛,给我点时间哈. 本项目开源地址: ...

  4. java后台oa项目整套,[VIP源码]【S020】springboot+mybatis+bootstrap开发员工oa后台管理系统项目源码...

    java源码项目名称:springboot+mybatis+bootstrap开发员工oa后台管理系统项目源码springboot项目源码0 `" C+ a" `" ~0 ...

  5. SpringBoot + MyBatis + Thymeleaf开发的个人博客。集成了:博客前台,后台管理。

    推荐一款分分钟在线搭建SpringBoot + Mybatis框架 地址:https://blog.csdn.net/qq_22067469/article/details/90523169 Kyri ...

  6. springboot 技术图谱_java后台(Springboot)开发知识图谱高频技术汇总-学习路线...

    [原创]java后台(Springboot)开发知识图谱&&高频技术汇总 1.引言: 学习一个新的技术时,其实不在于跟着某个教程敲出了几行.几百行代码,这样你最多只能知其然而不知其所以 ...

  7. Java SpringBoot+Mybatis Layui+JQuery+html微信公众号后台管理系统

    Java SpringBoot+Mybatis Layui++html微信公众号后台管理系统 hddhln 玛雅资源 技术框架 开发语言:JAVA 数据库:MYSQL JAVA开发框架:SpringB ...

  8. Springboot+mybatis构建管理后台系统

    Springboot+mybatis构建管理后台系统 新建一个springboot工程 开发后台管理登陆功能 1.在springboot中集成mybatis 2.编写登陆接口 2.编写登陆页面 登陆功 ...

  9. DB数据源之SpringBoot+MyBatis踏坑过程(三)手工+半自动注解配置数据源与加载Mapper.xml扫描...

    DB数据源之SpringBoot+MyBatis踏坑过程(三)手工+半自动注解配置数据源与加载Mapper.xml扫描 liuyuhang原创,未经允许禁止转载    系列目录连接 DB数据源之Spr ...

最新文章

  1. java 移动支付接口开发,移动支付平台间接口报文解析技术核心架构实现、及平台交易处理项目全程实录教程...
  2. Apache服务器和tomcat服务器有什么区别?
  3. ZZ:new/delete 和malloc/free 的区别
  4. Ubuntu:成功解决ubuntu使用su切换root出现Authentication failure用户时认证失败
  5. qt 制作记事本_23.QT记事本
  6. 9.使用原生js实现类似于jquery的动画
  7. python pandas库 画图_python绘图:matplotlib和pandas的应用
  8. python批量修改labelme(COCO)标注的json文件的label标签名称
  9. APP论坛社区软件源码 APP封装
  10. Akka创建第一个Actor《nine》译
  11. 【一分钟知识】梯度下降与牛顿法对比
  12. 用python写论文_[文章] 编写高质量 Python 的 6 个技巧
  13. javascript学习-常用内置对象
  14. java正则匹配性能,Java正则表达式的性能问题
  15. CC2530存储器映射
  16. Binding.scala使用教程8--binding.scala结合semanticUI
  17. 研华服务器显示不了全屏啊,ppt不能全屏显示怎么办 ppt全屏显示不了的解决方法...
  18. 计算机基础:12、计算机CPU--控制器
  19. java17长期支持版本_Java 8后的首个长期支持版本Java 11
  20. visio添加连接点

热门文章

  1. 【YOLO v4 相关理论】Normalization: BN、CBN、CmBN
  2. 配置Python开发环境
  3. 云计算的优点,主要包含哪几个方面?
  4. 计算机板块:外包引领软件业高成长
  5. 四川2021高考体考成绩查询,2021年四川体育类专业成绩查询时间及入口_中职中专网...
  6. 地理信息系统专业考研 GIS专业考研 名词解释大全[转]
  7. 关于js中获取div中的数据
  8. 捷俊通无人值守自动称重过磅智能系统智能地磅
  9. 如何识别企业内的“千里马”?
  10. 计算机设计大赛应用软件组,组一览表(计算机设计大赛).pdf