Mybatis学习笔记(九)

常见问题与解决方案

简要描述:总结MyBatis-Plus开发过程中常见的问题、错误及其解决方案,帮助开发者快速定位和解决问题。

核心概念

  • 常见错误:开发中经常遇到的错误类型
  • 性能问题:性能相关问题的排查和解决
  • 配置问题:配置相关的常见问题
  • 最佳实践:推荐的开发实践和规范

常见错误及解决

简要描述:MyBatis-Plus开发中常见的错误类型及其解决方法。

核心概念

  • SQL错误:SQL语法和执行错误
  • 映射错误:实体类和数据库字段映射错误
  • 配置错误:配置文件相关错误
  • 注解错误:注解使用不当导致的错误

SQL相关错误

// 1. 字段不存在错误
// 错误示例:
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("user_name", "张三"); // 数据库字段是username,不是user_name// 解决方案:
@TableField("username") // 明确指定数据库字段名
private String userName;// 或者在QueryWrapper中使用正确的字段名
wrapper.eq("username", "张三");// 2. 表名不存在错误
// 错误示例:
@TableName("sys_user") // 数据库表名是user,不是sys_user
public class User {// ...
}// 解决方案:
@TableName("user") // 使用正确的表名
public class User {// ...
}// 3. 主键策略错误
// 错误示例:
@TableId(type = IdType.AUTO) // 数据库主键不是自增的
private Long id;// 解决方案:
@TableId(type = IdType.ASSIGN_ID) // 使用雪花算法生成ID
private Long id;// 4. 逻辑删除字段错误
// 错误示例:
@TableLogic
private Integer deleted; // 数据库字段类型是TINYINT,但使用了Integer// 解决方案:
@TableLogic(value = "0", delval = "1")
private Boolean deleted; // 使用Boolean类型

分页查询错误

// 1. 分页插件未配置
// 错误现象:分页查询返回全部数据
// 解决方案:正确配置分页插件
@Configuration
public class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}
}// 2. 分页参数错误
// 错误示例:
Page<User> page = new Page<>(0, 10); // 页码从0开始// 解决方案:
Page<User> page = new Page<>(1, 10); // 页码从1开始// 3. 分页查询count错误
// 错误示例:
Page<User> page = new Page<>(1, 10);
page.setSearchCount(false); // 禁用count查询但又需要总数// 解决方案:
Page<User> page = new Page<>(1, 10);
page.setSearchCount(true); // 启用count查询

事务相关错误

// 1. 事务不生效
// 错误示例:
@Service
public class UserService {@Transactionalprivate void updateUser(User user) { // private方法,事务不生效// ...}
}// 解决方案:
@Service
public class UserService {@Transactionalpublic void updateUser(User user) { // public方法// ...}
}// 2. 异常被捕获导致事务不回滚
// 错误示例:
@Transactional
public void updateUser(User user) {try {userMapper.updateById(user);int i = 1 / 0; // 抛出异常} catch (Exception e) {log.error("更新用户失败", e); // 异常被捕获,事务不回滚}
}// 解决方案:
@Transactional(rollbackFor = Exception.class)
public void updateUser(User user) {try {userMapper.updateById(user);int i = 1 / 0;} catch (Exception e) {log.error("更新用户失败", e);throw e; // 重新抛出异常,触发事务回滚}
}

性能问题排查

简要描述:识别和解决MyBatis-Plus应用中的性能问题。

核心概念

  • 慢查询识别:识别执行缓慢的SQL
  • 内存泄漏:排查内存泄漏问题
  • 连接池问题:数据库连接池相关问题
  • 缓存问题:缓存使用不当导致的性能问题

慢查询排查

// 1. 开启SQL日志
// application.yml
logging:level:com.example.mapper: debugorg.springframework.jdbc: debug// 2. 使用性能分析插件
@Configuration
public class PerformanceConfig {@Bean@Profile("dev")public PerformanceInterceptor performanceInterceptor() {PerformanceInterceptor interceptor = new PerformanceInterceptor();interceptor.setMaxTime(1000); // 超过1秒的SQL会被记录interceptor.setFormat(true);return interceptor;}
}// 3. 自定义慢查询监控
@Component
public class SlowQueryMonitor {private static final Logger logger = LoggerFactory.getLogger(SlowQueryMonitor.class);@EventListenerpublic void handleSlowQuery(SlowQueryEvent event) {if (event.getExecutionTime() > 1000) {logger.warn("慢查询检测: SQL={}, 执行时间={}ms, 参数={}", event.getSql(), event.getExecutionTime(), event.getParameters());// 可以发送告警通知sendSlowQueryAlert(event);}}private void sendSlowQueryAlert(SlowQueryEvent event) {// 发送告警逻辑}
}

内存泄漏排查

// 1. SqlSession未关闭导致内存泄漏
// 错误示例:
public List<User> findUsers() {SqlSession sqlSession = sqlSessionFactory.openSession();List<User> users = sqlSession.selectList("findUsers");// 未关闭SqlSession,导致内存泄漏return users;
}// 解决方案:
public List<User> findUsers() {try (SqlSession sqlSession = sqlSessionFactory.openSession()) {return sqlSession.selectList("findUsers");} // 自动关闭SqlSession
}// 2. 大结果集查询导致内存溢出
// 错误示例:
public List<User> findAllUsers() {return userMapper.selectList(null); // 查询所有数据,可能导致内存溢出
}// 解决方案:使用分页查询
public List<User> findAllUsers() {List<User> allUsers = new ArrayList<>();int pageSize = 1000;int current = 1;while (true) {Page<User> page = new Page<>(current, pageSize);IPage<User> result = userMapper.selectPage(page, null);allUsers.addAll(result.getRecords());if (result.getRecords().size() < pageSize) {break;}current++;}return allUsers;
}

版本升级注意事项

简要描述:MyBatis-Plus版本升级过程中需要注意的重要事项和兼容性问题。

核心概念

  • 版本兼容性:不同版本间的兼容性问题
  • API变更:API接口的变更和废弃
  • 配置变更:配置方式的变化
  • 依赖升级:相关依赖的升级要求

3.x升级到4.x注意事项

# 1. 依赖变更
# 旧版本(3.x)
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3</version>
</dependency># 新版本(4.x)
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>4.0.0</version>
</dependency># 2. 配置变更
# 旧配置方式
mybatis-plus:global-config:db-config:id-type: autologic-delete-value: 1logic-not-delete-value: 0# 新配置方式
mybatis-plus:global-config:db-config:id-type: autologic-delete-field: deletedlogic-delete-value: 1logic-not-delete-value: 0

API变更处理

// 1. 分页插件配置变更
// 旧版本配置
@Configuration
public class MybatisPlusConfig {@Beanpublic PaginationInterceptor paginationInterceptor() {PaginationInterceptor paginationInterceptor = new PaginationInterceptor();paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));return paginationInterceptor;}
}// 新版本配置
@Configuration
public class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}
}// 2. 性能分析插件变更
// 旧版本
@Bean
public PerformanceInterceptor performanceInterceptor() {return new PerformanceInterceptor();
}// 新版本(已废弃,建议使用第三方工具)
// 使用p6spy或其他性能监控工具

升级检查清单

// 升级前检查清单
public class UpgradeChecklist {/*** 1. 检查依赖兼容性* - Spring Boot版本兼容性* - JDK版本要求* - 其他依赖库版本*//*** 2. 检查配置文件* - application.yml配置项变更* - 插件配置方式变更* - 全局配置项变更*//*** 3. 检查代码兼容性* - 废弃API的替换* - 新增注解的使用* - 方法签名变更*//*** 4. 测试验证* - 单元测试通过* - 集成测试通过* - 性能测试对比*/
}

最佳实践总结

简要描述:MyBatis-Plus开发的最佳实践和推荐规范总结。

核心概念

  • 代码规范:代码编写规范
  • 性能优化:性能优化建议
  • 安全实践:安全相关的最佳实践
  • 维护性:提高代码可维护性的建议

开发规范总结

// 1. 实体类设计规范
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("sys_user")
public class User implements Serializable {private static final long serialVersionUID = 1L;@TableId(value = "id", type = IdType.ASSIGN_ID)private Long id;@TableField("username")@NotBlank(message = "用户名不能为空")private String username;@TableField(value = "create_time", fill = FieldFill.INSERT)private LocalDateTime createTime;@TableLogic(value = "0", delval = "1")private Boolean deleted;@Versionprivate Integer version;
}// 2. Mapper接口规范
@Mapper
public interface UserMapper extends BaseMapper<User> {/*** 自定义查询方法要有明确的注释*/List<User> selectByCustomCondition(@Param("condition") UserQueryCondition condition);
}// 3. Service层规范
@Service
@Transactional(rollbackFor = Exception.class)
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {@Overridepublic IPage<User> findUserPage(UserPageRequest request) {// 参数校验validatePageRequest(request);// 构建查询条件LambdaQueryWrapper<User> wrapper = buildQueryWrapper(request);// 执行分页查询Page<User> page = new Page<>(request.getCurrent(), request.getSize());return baseMapper.selectPage(page, wrapper);}private void validatePageRequest(UserPageRequest request) {if (request.getCurrent() < 1) {throw new IllegalArgumentException("页码不能小于1");}if (request.getSize() > 100) {throw new IllegalArgumentException("每页大小不能超过100");}}
}

性能优化总结

// 1. 查询优化
public class QueryOptimization {// 使用字段选择,避免查询不必要的字段public List<UserSimpleVO> findUserSimpleList() {LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();wrapper.select(User::getId, User::getUsername, User::getEmail);return baseMapper.selectList(wrapper);}// 使用批量操作public boolean batchUpdateStatus(List<Long> userIds, Integer status) {if (CollectionUtils.isEmpty(userIds)) {return true;}List<User> users = userIds.stream().map(id -> {User user = new User();user.setId(id);user.setStatus(status);return user;}).collect(Collectors.toList());return updateBatchById(users);}// 使用缓存@Cacheable(value = "users", key = "#id")public User findById(Long id) {return baseMapper.selectById(id);}
}// 2. 连接池优化
spring:datasource:hikari:maximum-pool-size: 20minimum-idle: 5connection-timeout: 30000idle-timeout: 600000max-lifetime: 1800000

安全实践总结

// 1. 防止SQL注入
public class SecurityPractice {// 正确:使用参数化查询public List<User> findUsersByName(String username) {LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();wrapper.eq(User::getUsername, username);return baseMapper.selectList(wrapper);}// 错误:直接拼接SQLpublic List<User> findUsersByNameBad(String username) {QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.apply("username = '" + username + "'"); // 危险!return baseMapper.selectList(wrapper);}// 2. 敏感信息处理public UserVO getUserInfo(Long userId) {User user = baseMapper.selectById(userId);if (user == null) {return null;}UserVO userVO = new UserVO();BeanUtils.copyProperties(user, userVO);userVO.setPassword(null); // 不返回密码return userVO;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/95654.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/95654.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据类型 list

一、介绍类似于数组&#xff0c;顺序表&#xff0c;deque结构图特点&#xff1a;元素有序&#xff0c;元素允许重复由于头尾高效插入删除&#xff0c;可以模拟栈&#xff0c;队列二、常见 list 命令1、lpush key elem [elem ...]头插元素&#xff0c;返回值列表长度2、lrange k…

pyqt5无法显示opencv绘制文本和掩码信息

背景&#xff1a;pyqt5无法显示opencv绘制的标签和mask&#xff1b;我们在使用YOLO做实例分割做推理时&#xff0c;会使用opencv做后处理结果绘制&#xff08;含标签绘制和掩码绘制&#xff09;&#xff1b;结果opencv绘制的解码却无法在pyqt的解码上面显示。pyqt转换代码如下&…

如何生成严格递增的分布式id?

本文字数&#xff1a;2604字预计阅读时间&#xff1a;15分钟01引言在现有分布式系统中&#xff0c;面对增长迅速的业务数据&#xff0c;id生成一直是非常重要的一环。而分布式系统的id生成方案需要满足几个重要特性&#xff1a;容错高可用、高性能高并发、全局唯一。02技术背景…

【LeetCode】二叉树相关算法题

目录1、二叉树介绍【1】核心概念【2】关键特性2、算法题【1】二叉树的前序遍历【2】二叉树的后序遍历1、二叉树介绍 【1】核心概念 结构含义节点结构二叉树由节点组成&#xff0c; 每个节点包含一个数据元素和最多两个子节点&#xff1a;左子节点和右子节点根节点树的顶部节点…

Vulnhub Deathnote靶机复现攻略

一、靶机安装 下载地址&#xff1a;https://download.vulnhub.com/deathnote/Deathnote.ova 下载好后使用VB打开&#xff0c;配置如下 二、主机发现 使用相同连接方式的kali进行后续操作(172.16.2.7)根据mac地址进行确认。 nmap -sn 172.16.2.1/24 三、端口扫描 端口开放了…

DevEco Studio 6.0.0 元服务页面跳转失败

背景&#xff0c;我使用最新的编辑器DevEco Studio 6.0.0&#xff0c;编写一个元服务&#xff0c;发现使用跳转页面的时候失败了&#xff01;然后查看官方文档&#xff0c;两种方式都测试了&#xff0c;发现都不行。 方法1&#xff1a;Navigation路由跳转无效&#xff0c;见官方…

docker重启或系统重启后harbor自动启动

docker重启或系统重启后harbor自动启动docker重启或系统重启后harbor自动启动方法 1&#xff1a;在 docker-compose.yml 中配置重启策略&#xff08;推荐&#xff09;方法 2&#xff1a;创建 Systemd 服务&#xff08;更可靠&#xff09;方法 3&#xff1a;使用 Docker 的 Rest…

OpenZeppelin Contracts 架构分层分析

OpenZeppelin Contracts 是一个面向以太坊&#xff08;及兼容 EVM 的区块链&#xff09;生态系统的​​模块化、安全性优先、标准兼容的智能合约库​​。其内部代码按照功能职责与抽象层级&#xff0c;可系统性地划分为多个逻辑层次。理解这些层次及其依赖关系&#xff0c;对于…

Java-JVM的内存模型

一.JVM内存模型JVM内存模型可以从进程生命周期和线程生命周期1.线程生命周期每个线程都会有自己各自一份数据&#xff0c;不会存在线程安全问题1.程序计数器指示当前线程执行的字节码指令的行号&#xff0c;以便线程执行时可以回到正确的位置2.虚拟机栈线程私有的&#xff0c;与…

Highcharts Dashboards | 打造企业级数据仪表板:从图表到数据驾驶舱

企业日常决策、产品运营、业务监控&#xff0c;越来越依赖数据驱动。而仪表板&#xff08;Dashboard&#xff09;作为汇总展示多维度信息的“数据驾驶舱”&#xff0c;已成为企业可视化的核心场景之一。如果你正在寻找一款能够快速、灵活、安全构建仪表板的前端图表工具&#x…

基于Java的Markdown转Word工具(标题、段落、表格、Echarts图等)

项目源于我们开发的一款基于大模型的报告生成工具。由于需要将 Markdown 格式的内容导出为 Word 文档&#xff0c;而市面上缺乏合适的现成工具&#xff0c;所以决定自己开发一个Markdown转Word的工具。 &#x1fa77;源码地址&#xff1a;daydayup-zyn/md2doc-plus &#x1f…

Unity:PlayerPrefs笔记

写在前面&#xff1a;写本系列(自用)的目的是回顾已经学过的知识、记录新学习的知识或是记录心得理解&#xff0c;方便自己以后快速复习&#xff0c;减少遗忘。一、PlayerPrefs的基本方法1、存储相关PlayerPrefs的数据存储类似于键值对存储&#xff0c;一个键对应一个值。Unity…

SQL tutorials

SQL Literature SQL运行在资料库管理系统&#xff08;Database Management System&#xff09;&#xff0c;如MySQL&#xff0c;Postgre SQL&#xff0c;Microsoft SQL Server&#xff0c; Oracle&#xff0c;etc。 SQL练习平台&#xff1a;https://sqliteviz.com/ EXAMPLE SQL…

MySQL快速恢复数据的N种方案完全教程

目录 1. 理解MySQL数据恢复的核心逻辑 1.1 数据丢失的常见场景 1.2 MySQL的“救命稻草”:关键文件和机制 2. 方案一:利用全量备份+binlog实现点对点恢复 2.1 准备工作 2.2 恢复步骤 2.3 实战案例 3. 方案二:利用InnoDB的崩溃恢复机制 3.1 崩溃恢复的原理 3.2 恢复步…

双屏加固笔记本电脑C156-2:坚固与高效的完美融合

在当今数字化时代&#xff0c;笔记本电脑已成为人们工作和生活中不可或缺的工具。然而&#xff0c;对于一些特殊行业和恶劣环境下的应用场景&#xff0c;普通笔记本电脑往往难以满足需求。此时&#xff0c;具备坚固耐用、高性能等特点的加固笔记本电脑应运而生。鲁成伟业的双屏…

Jenkins 环境部署

下载相关软件&#xff1a;Jenkins 的安装和设置 相关工具&#xff1a; Git : Git - Downloads java 17: Java Archive Downloads - Java SE 17.0.12 and earlier python : Download Python | Python.org jenkins、jenkins.war : Jenkins 的安装和设置 将所有软件安装后&am…

如何高效解决 Java 内存泄漏问题方法论

目录 一、系统化的诊断与优化方法论 二、获取内存快照:内存泄漏的第一步 (一)自动生成 Heap Dump (二)手动生成 Heap Dump 三、导入分析工具:MAT 和 JProfiler (一)MAT (Memory Analyzer Tool) (二)JProfiler (三)自身企业工具 四、深入分析:逐步排查内存…

HarmonyOS Camera Kit 全解析:从基础拍摄到跨设备协同的实战指南

在移动应用开发中&#xff0c;相机功能往往是提升用户体验的关键模块&#xff0c;但传统相机开发面临权限管理复杂、设备兼容性差、功能实现繁琐等痛点。HarmonyOS 作为面向全场景的分布式操作系统&#xff0c;其 Camera Kit&#xff08;相机服务&#xff09;通过统一的 API 接…

运用词向量模型分辨评论

代码实现&#xff1a;import jieba import pandas as pd hp pd.read_table(优质评价.txt,encodinggbk) cp pd.read_table(差评1.txt,encodinggbk) cp_segments [] contents cp.content.values.tolist() for content in contents:results jieba.lcut(content)if len(result…

基于Apache Flink的实时数据处理架构设计与高可用性实战经验分享

基于Apache Flink的实时数据处理架构设计与高可用性实战经验分享 一、业务场景描述 在现代电商平台中&#xff0c;实时用户行为数据&#xff08;点击、浏览、购物车操作等&#xff09;对业务决策、个性化推荐和风控都至关重要。我们需要搭建一个高吞吐、低延迟且具备高可用性的…