Java日常探秘-从小疑问到实践智慧的编程之旅(2)

文章目录

  • 前言
  • 一、常见错误
    • 400错误
    • 401错误
    • 404错误
    • MismatchedInputException
    • Mybatis的NumberFormatException
    • Mybatis的Available parameters are [collection,list]]报错
    • Mybatis之Double类型的字段的值为0.0传入不了sql中
  • 二、SQL效率
    • 数据库字段类型和传入参数类型不匹配
    • 小表驱动大表
    • 减少与数据库之间的连接
  • 总结


前言

所有分享的内容源于日常思考和实践,探讨Java编程中的小知识点和实用场景,加深自己对编程技巧和理解Java深层次的原理,期待发现妙招和解决实际问题的新思路。


一、常见错误

400错误

也称400 Bad Request,是一种HTTP状态码,表示客户端发送给服务器的请求在语法上存在问题,导致服务器无法理解或处理该请求。

在进行web开发中,参数错误是导致400 Bad Request错误的常见原因之一:

  1. 参数错误:缺少必要参数,客户端未提供必要的参数,导致服务器无法处理请求。
  2. 参数格式不正确:客户端提供的参数格式不符合服务器的要求。

举例说明:

//后端接口
public AjaxResult check(@RequestParam("ids")List<Long>ids){//执行业务代码
}

前端在传递ids参数时,不小心传成了[5,6,7]这种列表形式,服务器报400错误,后来对于ids参数传成5,6,7的形式,服务器成功处理该请求


401错误

401错误(未授权):未授权访问的提示,那就意味着你被挡在了门外,没有得到进入的许可。就像是你去参加一个派对,却被门口的保安拦住了,因为你没有邀请函或者身份验证。

常见原因:
1.缺少身份验证信息:请求未包含身份验证信息或身份验证信息不完整。通常,身份验证信息应该包含在请求的头部字段Authorization中。
2.无效的身份验证信息:请求包含的身份验证信息无效,可能是由于凭据错误、过期的凭据、无效的令牌等导致的。


404错误

404错误信息通常是在目标页面被更改或移除,或客户端输入页面地址错误后显示的页面,或者浏览器请求后端地址时路径没对应上。
前端js请求

function exportDetail(crossId){return request({url: '/system/cross/exportDetail/'+crossId,method: 'get'})
}

后端控制层代码

//后端接口
@GetMapping(value = "/system/cross/{crossId}")
public AjaxResult exportDetail(Pathvariable("crossId")String crossId){//执行业务代码
}

这时请求就会报404 Not Found错误,将后端接口路径修改为和前端js一致即可。

@GetMapping方法修改为

//后端接口
@GetMapping(value = "/system/cross/exportDetail/{crossId}")
public AjaxResult exportDetail(Pathvariable("crossId")String crossId){//执行业务代码
}

MismatchedInputException

MismatchedInputException是Java中Jackson库在反序列化过程中抛出的异常。Jackson是一个快速的JSON处理库,用于将Java对象转换成JSON格式,以及将JSON转换成Java对象。当Jackson尝试将JSON数据转换为Java对象时,如果JSON的结构与目标Java类的结构不匹配,就会抛出MismatchedInputException: Cannot deserialize instance of

通过一个简单的例子来解析Jackson的反序列化过程

public class TaskResp {private String id;private String name;// getters and setters
}public class Main {public static void main(String[] args) {String json = "[{\"id\":\"1\",\"name\":\"Task1\"},{\"id\":\"2\",\"name\":\"Task2\"}]";ObjectMapper mapper = new ObjectMapper();try {// 错误:尝试将数组反序列化为单个对象TaskResp taskResp = mapper.readValue(json, TaskResp.class);} catch (JsonProcessingException e) {e.printStackTrace();}}
}

我们尝试将一个包含多个TaskResp对象的JSON数组反序列化为单个TaskResp对象,,因此会抛出MismatchedInputException。


Mybatis的NumberFormatException

<where><if test="isExpired != null and isExpired=='Y'">and msg.expire_time &lt; now() </if>
</where>

mybatis使用字符串参数的时候 mybatis java.lang.NumberFormatException: For input string: ‘Y’

报错原因:mybatis是用OGNL表达式来解析的,在OGNL的表达式中,'Y’会被解析成字符,Java是强类型的,char和一个string会导致不等,所以if标签中的sql不会被解析。在做字符串的比较的情况下,需要将字符转为字符串类型。

<where><if test="isExpired != null and isExpired=='Y'.toString()">and msg.expire_time &lt; now() </if>
</where>

Mybatis的Available parameters are [collection,list]]报错

mybatis可以支持多种传参模式,主要讲解mybatis的list集合或数组传参时遇到的一个问题。

<select id="queryImIdByEmails" parameterType="java.util.List" resultType="java.lang.String">select uid from employee where email in<foreach collection="param1" item="item"  separator="," open="(" close=")" index="">  #{item}    </foreach> 
</select>

本地调试时报了这个错误:org.apache.ibatis.binding.BindingException: Parameter ‘customerIdList’ not found. Available parameters are [collection, list]

报错原因:集合或者数组传参给mybatis时,mybatis会使用map来封装参数,如果是list传参时,map的默认key为list,数组传参时,map默认key为array,在不指定传参名称时,必须使用默认的key为sql中collection的值

将collection="param1"改为collection=“list”

<select id="queryImIdByEmails" parameterType="java.util.List" resultType="java.lang.String">select uid from employee where email in<foreach collection="list" item="item"  separator="," open="(" close=")" index="">  #{item}    </foreach> 
</select>

Mybatis之Double类型的字段的值为0.0传入不了sql中

原因:Mybatis对于数值型的参数,如果是0会被转换成空字符串, 所以动态条件不成立无法拼接后续条件。

解决方法:如果是数值型吗,判断0.0,需要加 .toString()进行判断。

dto接收前端传入进来的0的数字,经过后端的dto接收后,变成了0.0Double类型的数据。

 @ApiModelProperty("绩点")@JsonProperty(value="GPAValue")private java.lang.Double GPAValue;

在xml文件需要加上’0’.toString()如:

<if test="GPAValue != null and GPAValue != '' or GPAValue == '0'.toString() ">and  JD = #{GPAValue,jdbcType=NUMERIC}
</if>

最好的处理方式:保持好习惯,不要乱写判断,数字类型不会出现空字符串就不要去判断,String类型才需要有空字符串判断。


二、SQL效率

数据库字段类型和传入参数类型不匹配

给employee表的name字段加上索引

CREATE TABLE `employee` (`name` varchar(30)  DEFAULT NULL COMMENT '姓名',KEY `index_name` (`name`)
) ENGINE=InnoDB;

1.查询name为数字时(全表扫描-发生了隐式类型转换,索引失效)

explain select * from employee where name=1

2.查询name为字符串时,成功走了索引

explain select * from employee where name='1'

所以在开发时一定要注意参数的类型和数据库的类型是否匹配的问题,不然一不小心就可能会导致索引失效。


小表驱动大表

小表驱动大表,也就是说用小表的数据集驱动大表的数据集。

假如有order和user两张表,其中order表有10000条数据,而user表有100条数据,现在想查询所有有效的用户下过的订单列表

可以使用in关键字实现,因为如果sql语句中包含了in关键字,则它会优先执行in里面的子查询语句,然后再执行in外面的语句。如果in里面的数据量很少,作为条件查询速度更快。

select * from order 
where user_id in (select id from user where status=1)

而如果sql语句中包含了exists关键字,它优先执行exists左边的语句(即主查询语句)。然后把它作为条件,去跟右边的语句匹配。如果匹配上,则可以查询出数据。如果匹配不上,数据就被过滤掉了。

select * from order 
where exists (select 1 from user where order.user_id = user.id and status=1)

思考:为什么小表驱动大表会提高效率,不管大表是驱动表还是小表是驱动表,单纯的分析指令执行次数,都是相同的,那提效在哪里?

//小表驱动大表
for(i = 0; i < 100; i++){for(j = 0; j < 10000; j++){//处理业务逻辑代码}
}//大表驱动小表
for(i = 0; i < 10000; i++){for(j = 0; j < 100; j++){//处理业务逻辑代码}
}

看以上两个for循环,总共循环的次数是一样的。但是对于mysql数据库而言,并不是这样了,我们尽量选择第②个for循环,也就是小表驱动大表。数据库最伤神的就是跟程序链接释放,第一个建立了10000次链接,第二个建立了50次。假设链接了两次,每次做上百万次的数据集查询,查完就走,这样就只做了两次;相反建立了上百万次链接,申请链接释放反复重复,这样系统就受不了了。


减少与数据库之间的连接

1.业务中出现在循环中频繁查询数据库对比数据,频繁连接数据库耗费资源。
优化方法:可以将数据取出放进list进行操作。

List<A> listA = dao.getAlist();
Map<String,Object> mapA = new HashMap<String,Object>();
//将a放进map中
for(A a : listA){mapA.put(a.getId(),a);
}List<B> listB =  dao.getBlist();
Map<String, Object> A_B = new HashMap<String, Object>();
for(B b : listB){A a = mapA.get(b.getAId());//业务代码
}

2.随着业务需要,有时我们需要将数据批量添加到数据库,mybatis提供了将list集合循环添加到数据库的方法,以减少频繁连接数据库。

<insert id="insertBatch">INSERT INTO t_user (name, del_flag)VALUES<foreach collection ="list" item="user" separator =",">(#{user.name}, #{user.delFlag})</foreach >
</insert>

总结

本文介绍了几种常见的HTTP状态码、Mybatis的易报错场景、数据库效率的优化。以上文索引失效的场景为例,只有我们明确了什么情况下索引会失效,才不会发生我们添加了索引,不仅占用了资源,还没有生效的场景出现。


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

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

相关文章

【手撕代码】握手机制

文章目录 为什么要握手握手信号无非3种可能 怎样实现握手案例一&#xff1a;数据反压 参考链接 为什么要握手 跨时钟域处理&#xff1a; 握手信号法其实也用到了脉冲展宽的方法&#xff0c;只是展宽信号的变化条件不同。因为如果不对脉冲进行展宽&#xff0c;慢速时钟域的时钟…

PromptCraft-Robotics部署步骤和问题记录

GitHub - microsoft/PromptCraft-Robotics: Community for applying LLMs to robotics and a robot simulator with ChatGPT integration 部署环境&#xff1a;UE4.27 Visual Studio 2022 Arisim1.8.1 可参考&#xff1a;git clone https://github.com/Microsoft/AirSim.gi…

用promise实现批量请求数据,同时支持控制请求的并发数

假设有个业务场景,要求:可以批量请求数据,所有的 URL 地址在 urls 参数中,同时可以通过 max 参数控制请求的并发度,当所有请求结束之后,需要执行 callback 回掉函数。 JavaScript代码实现 async function sendRequest(urls, max, callback) {// 用于存储所有请求的promi…

Java三方库-单元测试

文章目录 Junit注解常用类无参数单测带参数的单测 Junit 主要版本有4和5版本&#xff0c;注解不太一样&#xff0c; 4迁移5参考官方文档 主要记录下常用的一些操作 其他复杂操作见官网 https://junit.org/junit5/docs/current/user-guide/#overview-java-versions 引入5.9…

WSL Ubuntu 如何设置中文语言?

本章教程,主要介绍如何在WSL Ubuntu 如何设置中文语言。 操作系统:Windows 10 Pro 64 WSL子系统:Ubuntu 20.04 LTS 一、安装中文语言包 sudo apt install language-pack-zh-hans二、设置中文语言 sudo dpkg-reconfigure locales选择en_US.UTF-8 和 zh_CN.UTF-8 选择zh_CN.…

Java虚拟机(JVM)中符号引用(symbolic reference)和直接引用以及转化过程

在Java虚拟机&#xff08;JVM&#xff09;中&#xff0c;符号引用&#xff08;symbolic reference&#xff09;和直接引用&#xff08;direct reference&#xff09;是两种不同的引用方式。了解这两种引用方式有助于更深入地理解Java的运行时机制&#xff0c;特别是类加载和方法…

jps命令解释以及用法

JPS命令是Linux系统中的一个常用命令&#xff0c;用于显示Java进程的相关信息。下面是JPS命令的详解&#xff1a; JPS命令是Java Development Kit&#xff08;JDK&#xff09;提供的一个工具&#xff0c;用于列出JVM进程&#xff08;Java虚拟机进程&#xff09;的信息。它通常…

39 - 安全技术与防火墙

39、安全技术和防火墙 一、安全技术 入侵检测系统&#xff1a;特点是不阻断网络访问&#xff0c;主要是提供报警和事后监督。不主动介入&#xff0c;默默看着你&#xff08;监控&#xff09;。 入侵防御系统&#xff1a;透明模式工作&#xff0c;数据包&#xff0c;网络监控…

TextArea是一个用于显示和编辑多行可滚动文本的控件,通常用于需要用户输入或展示大量文本的应用中

TextArea 是一个用于显示和编辑多行可滚动文本的控件&#xff0c;通常用于需要用户输入或展示大量文本的应用中。以下是 TextArea 中常用的属性、信号和方法的详解&#xff1a; 常用属性 text: 描述&#xff1a;用于设置或获取显示的文本内容。类型&#xff1a;string示例&…

python-(opencv)视频转glf

文章目录 前言python-(opencv)视频转glf1. 下载 opencv-python2. cv2&#xff08;OpenCV&#xff09;和imageio的区别3. demo源码 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说…

youlai-boot项目的学习(4) 前后端本地部署

环境 1、macOS, brew, IntelliJ IDEA, WebStrom 2、后端&#xff1a;https://gitee.com/youlaiorg/youlai-boot.git , master, 9a753a2e94985ed4cbbf214156ca035082e02723 3、前端&#xff1a;https://gitee.com/youlaiorg/vue3-element-admin.git, master, 66b913ef01dc880ad…

mobaxterm x11 转发Ubuntu mac

目录 royal tsx —— 一款Mac平台MobaXterm平替工具 mobaxterm x11 转发Ubuntu 软件 royal tsx —— 一款Mac平台MobaXterm平替工具 Royal Apps Termius Mac mobaxterm x11 转发Ubuntu 软件 所以直接在 ssh 的时候加上 - X 就可以了 ssh -X -p xxx usernameIP 运行 xclock …

递归函数设计技巧

如何设计递归函数 要学会如何设计递归函数&#xff0c;首先要识别什么样的问题才适合递归函数求解&#xff0c;那么我们可以通过数学归纳法&#xff0c;分析问题&#xff0c;观察问题是否符合相关性质。 数学归纳法 数学归纳法&#xff0c;是一种基本的数学证明方法&#xff0c…

深度解析RocketMq源码-IndexFile

1.绪论 在工作中&#xff0c;我们经常需要根据msgKey查询到某条日志。但是&#xff0c;通过前面对commitLog分析&#xff0c;producer将消息推送到broker过后&#xff0c;其实broker是直接消息到达broker的先后顺序写入到commitLog中的。我们如果想根据msgKey检索一条消息无疑…

Zookeeper:基于Zookeeper的分布式锁

一、Zookeeper分布式锁原理 二、Zookeeper JavaAPI操作 1、Curator介绍 Curator是Apache Zookeeper的Java客户端。常见的Zookeeper Java API&#xff1a; 原生Java API。ZkClient。Curator。 Curator项目目标是简化Zookeeper客户端的使用。Curator最初是Netfix研发的&#xf…

LIMS系统选型时应该避免哪些误区呢

LIMS实验室管理系统在选型、实施及使用过程中&#xff0c;确实存在一些常见的误区。以下是对这些误区的详细解析和归纳&#xff1a; 一、误区 1、只关注功能而忽视用户需求 在LIMS系统的选型过程中&#xff0c;实验室可能过于关注系统的功能和技术特性&#xff0c;而忽视了实…

42.option方法给服务端和客户端配置参数

客户端是Bootstrap.option方法配置参数。 服务端有两个: 1.ServerBootstrap.option方法,给ServerSocketChannel配置参数的。 2.ServerBootstrap.childOption方法,给SocketChannel配置参数的。 package com.xkj.client;import com.xkj.message.*; import com.xkj.protoco…

K近邻回归原理详解及Python代码示例

K近邻回归原理详解 K近邻回归&#xff08;K-Nearest Neighbors Regression, KNN&#xff09;是一种基于实例的学习算法&#xff0c;用于解决回归问题。它通过找到输入数据点在特征空间中最相似的K个邻居&#xff08;即最近的K个数据点&#xff09;&#xff0c;并使用这些邻居的…

C++11的可变参数模板

可变参数模板 什么是可变参数模板的可变参数展开参数包emplace系列函数引例emplace系列函数 什么是可变参数 printf和scanf中就涉及可变参数 这里三个点就代表可变参数&#xff0c;意思就是不管你传多少个参数&#xff0c;都可以接收 printf("%d",x); printf("…