一个JDBC驱动的陷阱

财务系统金额计算误差,Decimal精度丢失背后的JDBC陷阱 深夜11点,财务同事紧急电话:“日终跑批后,应收应付差0.01元,但所有订单金额总和显示平账!金额计算的精度如同瑞士钟表,任何环节的疏忽都会让整个系统陷入信任危机。• 建表语句 → Java实体 → Mapper XML → 最终显示,全程需标注精度。→ JDBC驱动按数据库连接默认精度(通常2位)截断。作为搜索关键词,确保所有金额处理路径都显式声明精度。但数据库查询结果却出现精度丢失。当财务系统出现0.01元误差时,检查订单金额计算逻辑,确认使用。,导致驱动忽略元数据精度。核查问题订单发现,金额。 阅读详情

近期公司的项目在升级Oracle 12C,除了要替换wm_concat之类的不能用的函数之类的预料中的问题外,我还遇到了一个挺奇怪的JDBC驱动问题:


就是使用JDBC调用存储过程时,发现获取的CallableStatement接口对象的setObject方法,用“命名参数”时有问题。


为了描述方便,我写成了一个小DEMO。


首先,有一个存储过程

CREATE OR REPLACE PROCEDURE PRINT_USER
(
       USERID        IN  VARCHAR2,
       USERNAME      IN  VARCHAR2,
       PRINTINFO     OUT VARCHAR2
)
AS
BEGIN
      PRINTINFO := '您的   用户ID是:['||USERID||']    用户名是:['||USERNAME||']';
EXCEPTION
  WHEN OTHERS THEN
    PRINTINFO := SQLCODE||'-'||SQLERRM;
END;


然后,编写一个简单的Java程序来调用一下它,并打印出它的出参。

package com.dullchap.db.driverproblem;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class TestDao {

	static Connection 		 conn;
	static ResultSet 		 rs;
	static PreparedStatement stmt;
	
	public static void main(String[] args) throws Exception{
		try {
			//加载驱动,获取链接
			Class.forName("oracle.jdbc.driver.OracleDriver");
			conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl1", "scott", "scott");
			
			//获取存储过程执行对象
			CallableStatement lcs_state = conn.prepareCall("BEGIN PRINT_USER(:USERID,:USERNAME,:PRINTINFO); END;");
			
			//设置存储过程出/入参数
			lcs_state.setObject("USERNAME", "张三");
			lcs_state.setObject("USERID", "123");
			lcs_state.registerOutParameter("PRINTINFO", java.sql.Types.VARCHAR);
			
			//执行存储过程
			lcs_state.executeUpdate();
			
			//打印存储过程结果
			System.out.println(lcs_state.getObject("PRINTINFO"));
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			//释放连接
			if (rs != null)		rs.close();
			if (stmt != null)	stmt.close();
			if (conn != null)	conn.close();
		}
	}
}

未升级Oracle 12C前,执行结果当然是没问题的,如下:

您的   用户ID是:[123]    用户名是:[张三]



但升级了Oracle 12C,并使用新的jdbc驱动包(ojdbc7.jar)时,问题来了,发现打印结果如下:

您的   用户ID是:[张三]    用户名是:[123]


经调查之后,发现ojdbc7.jar完全忽略了CallableStatement对应对象的setObject方法的第一个参数,


它完全按照先后顺序来给存储过程入参赋值了。


也就是说,我如果把代码的setObject那两行交换一下顺序,程序的输出也是正常的。


我在Oracle官网也查看了一下,有提到setObject(String,Object)是不推荐使用的方法了。还是老老实实用回setObject(int,Ojbect),乖乖写问号吧。

package com.dullchap.db.driverproblem;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class TestDao {

	static Connection 		 conn;
	static ResultSet 		 rs;
	static PreparedStatement stmt;
	
	public static void main(String[] args) throws Exception{
		try {
			//加载驱动,获取链接
			Class.forName("oracle.jdbc.driver.OracleDriver");
			conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl1", "scott", "scott");
			
			//获取存储过程执行对象
//			CallableStatement lcs_state = conn.prepareCall("BEGIN PRINT_USER(:USERID,:USERNAME,:PRINTINFO); END;");
			CallableStatement lcs_state = conn.prepareCall("BEGIN PRINT_USER(?,?,?); END;");
			
			//设置存储过程出/入参数
//			lcs_state.setObject("USERNAME", "张三");
//			lcs_state.setObject("USERID", "123");
//			lcs_state.registerOutParameter("PRINTINFO", java.sql.Types.VARCHAR);
			lcs_state.setObject(2, "张三");
			lcs_state.setObject(1, "123");
			lcs_state.registerOutParameter(3, java.sql.Types.VARCHAR);
			
			//执行存储过程
			lcs_state.executeUpdate();
			
			//打印存储过程结果
//			System.out.println(lcs_state.getObject("PRINTINFO"));
			System.out.println(lcs_state.getObject(3));
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			//释放连接
			if (rs != null)		rs.close();
			if (stmt != null)	stmt.close();
			if (conn != null)	conn.close();
		}
	}
}



【DBeaver】手把手教你配置MongoDB JDBC驱动 本文详细介绍了如何在DBeaver中手动配置MongoDB JDBC驱动,解决社区版无内置驱动的问题。从驱动下载、安全注意事项到具体配置步骤和常见错误排查,提供一站式解决方案,帮助开发者高效连接和操作MongoDB数据库。 阅读详情

相关推荐

解决Dbeaver连接人大金仓的常见问题:JDBC驱动配置避坑指南

本文详细解析了使用Dbeaver连接人大金仓数据库时常见的JDBC驱动配置问题。针对驱动类名、URL模板、默认端口等关键配置项,提供了精确的填写指南和验证方法,并重点阐述了如何通过Maven仓库或官方渠道正确获取驱动库文件,以彻底解决“ClassNotFoundException”等典型连接失败错误。

vim8coder的博客 920

Mybatis报错解决: Your driver may not support getAutoCommit() or setAutoCommit()

在mybatis配置文件中加如下配置 <environments default="abc"> <environment id="abc"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driv

王鹤霖的专栏 三人行必有我师 1018

Mac环境下DBeaver配置达梦数据库JDBC驱动的完整指南

本文提供了一份在macOS系统上为DBeaver配置达梦数据库JDBC驱动的详细指南。文章从驱动包的获取与选择讲起,重点介绍了如何在DBeaver驱动管理器中正确添加DmJdbcDriver18.jar驱动文件,并设置关键的driver.class和url.template属性。随后,逐步演示了新建连接时如何填写主机、端口、认证信息,并通过指定schema属性解决常见连接问题,最后附带了连接测试与基础故障排查方法,帮助Mac用户快速建立稳定的达梦数据库连接。

u0v1w2x3的博客 502

support getGeneratedKeys method *and* without a specific SQL dialect sqlite

10:38:47,746 |-ERROR in ch.qos.logback.core.joran.spi.Interpreter@42:16 - RuntimeException in Action for tag [appender] java.lang.IllegalStateException: DBAppender cannot function if the JDBC driver ...

hantanxin的专栏 4964

ClickHouse JDBC驱动升级指南:从ru.yandex到com.clickhouse的平滑迁移与常见问题解决

本文详细介绍了将ClickHouse JDBC驱动从老旧的`ru.yandex.clickhouse`迁移到官方新版`com.clickhouse`的完整指南。内容涵盖版本选择、依赖配置更新、驱动类(Driver class)的显式指定,并重点解决了迁移过程中常见的驱动类找不到、批量插入异常及时间类型转换等核心问题,帮助开发者实现平滑升级。

Python的专栏 815

Unity URP风格化水面Shader全流程实现与性能优化指南

在游戏开发中,Shader是实现特定视觉风格的核心技术,它通过编写在GPU上运行的程序,控制模型每个像素的最终颜色与光照表现。其原理在于对顶点位置、纹理坐标、光照信息及深度等数据进行一系列数学运算与插值。这项技术的价值在于能够以极高的自由度创造从写实到卡通的各种渲染效果,同时通过算法优化实现对硬件资源的精准控制。在移动游戏、独立游戏等对性能与风格化有强烈需求的场景中,自定义Shader尤为重要。本文聚焦于使用Unity URP渲染管线,从零构建一个高效的风格化水面Shader,详细拆解了深度色、波浪动画、边

weixin_34320724的博客 371

Orcle 存储过程调用封装类-备忘

主调用: import java.io.InputStream; import java.net.URL; import java.sql.Date; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Time; import java.util.ArrayList; import ex

flyinf_guo的专栏 1666

python音频信号分析

声音以具有诸如频率、带宽、分贝等参数的音频信号的形式表示,典型的音频信号可以表示为幅度和时间的函数

MAY的博客 2785

通过JDBC连接oracle数据库的十大技巧

发布日期:2002-01-10作者:b-i-d阅读人次:5126     Java数据库连接(JDBC)API是一系列能够让Java编程人员访问数据库的接口,各个开发商的接口并不完全相同。在使用多年的Oracle公司的JDBC后,我积累了许多技巧,这些技巧能够使我们更好地发挥系统的性能和实现更多的功能。     1、在客户端软件开发中使用Thin驱动程序    

EclipseLab 1892

【计算机三级-数据库技术】操作题大题(第1套)

从触发器的语法中可知,【1】处应该填写的是执行触发器的表,【2】处应该填写指定在表或视图上执行哪些数据修改语句时将激活触发器的关键字。使用FOR或AFTER选顶定义的触发器为后触发器,即只有在引发触发器执行的语句中的操作都已成功执行,并且所有的约束检查也成功完成后,才执行触发器。转换成新的独立的模式,模式的属性由联系本身的属性及两个实体的键构成,主键由两端实体的键组合而成。实体的转换:在从ER图转换为关系模式时,一个实体转换成一个关系模式,实体的属性就是关系模式的属性,实体的键就是关系的主键。

放纵小开爱的博客 1101

航空发动机轴承故障诊断

《航空发动机主轴承故障诊断的挑战与HIT数据集研究》 摘要: 航空发动机主轴承作为关键部件,其可靠性直接影响飞行安全。然而,主轴承故障诊断面临信号信噪比低、传输路径复杂、故障类型多样、变工况运行等挑战。哈尔滨工业大学团队开发的HIT数据集为研究提供了真实工况下的实验数据,包含正常、内圈和外圈故障三种状态,具有高仿真度和强挑战性特点。研究表明,传统诊断方法在该数据集上准确率仅71-85%,突显了诊断难度。团队提出的ISONet新方法通过输入空间过参数化技术,将诊断准确率提升至99%以上,为航空发动机轴承故障诊

tyutwuxuan的博客 996

mysql uuid() replace_MySQL JDBC 在查询中调用 REPLACE(UUID(),'-','') 查出重复的 UUID

MySQL版本是5.7.25,最近升级了JDBC驱动,5.1.45 -> 8.0.13,导致一个SQL报异常,SQL是用一个子查询,拿到数据后插入到另一张表用的。123INSERT INTO table_2 (id, title, modified_date)(SELECT REPLACE(UUID(),'-','') AS id, table_1.title AS title, NOW()...

weixin_34512894的博客 814

DOSBOX 0.74模拟器安装Windows 95

DosBox本身带有5.0版的DOS系统,启动后虚拟一个Z盘存放有Dosbox特有的外部指令,如config.com、imgmount.com等,经测试,可以顺利安装各版本的windows 3.1系统,但是不能安装win95,需要用原版的dos镜像启动才能安装。1. 获取启动盘镜像文件 下载Win95启动软盘镜像文件,名为boot.img,放到DosBox 0.74的目录下。2. 制作硬盘镜像文件

xjnzhidao的博客 9310

springBoot连接数据库错误: The server time zone value ‘�й���׼ʱ��‘ is unrecognized or represents more..

测试springboot连接数据库操作时,出现了一下错误 java.sql.SQLException: The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the 'serverTimezone' configuration property) to use.

weixin_43431123的博客 2982

Jetson 平台编译安装 FFmpeg 7.1(支持 Nvmpi + SRT + x265)

摘要: 本文详细介绍了在NVIDIA Jetson平台上编译FFmpeg 7.1并集成关键功能的全过程。通过补丁方式加入Nvmpi实现硬件加速支持,同时编译集成x265编码器和SRT低延迟传输协议。步骤涵盖:1)安装x265编码器;2)配置SRT协议支持;3)编译jetson-ffmpeg的Nvmpi接口;4)定制化编译FFmpeg 7.1;5)验证模块集成情况。最终实现支持硬件编解码、高效HEVC压缩和可靠推流的增强版FFmpeg,为Jetson平台的音视频处理提供完整解决方案。

J。 345

超声波传感器(CHx01) 学习笔记 Ⅲ-API介绍

超声波传感器(CHx01) API介绍

nicole088的专栏 1387

JDBC驱动包的隔离加载与卸载

JDBC驱动包的类加载隔离与卸载一、驱动包的加载在"工具"和"服务"中的区别二、驱动包的管理——类加载隔离三、抛弃DriverManager四、驱动类的卸载五、警惕静态代码块 对于sqoop或者datax这样以JDBC通用方式来进行数据迁移的工具来说,总是绕不开驱动包的加载。sqoop和datax只是迁移工具,所以不会暴露驱动包加载相关的问题,但如果考虑实现一个数据迁移服务的时候,就需要仔细考虑驱动包的加载问题了。 一、驱动包的加载在"工具"和"服务"中的区别 通过jdbc的方式进行数据迁移总是绕不过要加

Catyee's tech blogs 2152

ComfyUI整合包、秋叶ComfyUI、Florence节点报错下载并加载Florence2模型No module named ‘timm.layers‘、ComfyUI报错解决

步骤操作1打开2地址栏输入cmd并回车3输入命令:4安装完成后重新打开 ComfyUI,执行工作流,即可解决报错。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 1243

致命精度陷阱:PostgreSQL JDBC驱动中extra_float_digits参数的演进与最佳实践

当金融系统出现"一分钱错误",当科学计算结果与理论值偏差0.0000001,当分布式系统因浮点表示不一致引发数据同步异常——这些看似微小的差异背后,可能隐藏着同一个被忽视的技术细节:**PostgreSQL JDBC驱动中的extra_float_digits参数**。本文将深入解析这个参数从PostgreSQL 9.0到2025年最新版本的演进历程,通过12个实战案例、7组对比实验和完整的配置指...

gitblog_07204的博客 575

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Access denied for user ‘‘@‘localhost‘ (using password: YES)

jdbc连接mysql报错如标题所示,重点是报错信息是这样 的’‘@’localhost‘,说明程序没有解析到用户名,在配置环境里面,Drive获取连接用户名的字段名时user,不是username,巨坑无比,如果用户名和主机名都在错误信息里面显示了,那就是真的密码错了,可能是远程登录密码和本地登录的密码不一样 ...

weixin_44481341的博客 676

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

JDBC批处理陷阱:为什么你的MySQL批量插入没加速?rewriteBatchedStatements详解

本文深入解析了MySQL JDBC批处理性能不佳的核心原因,并详细介绍了`rewriteBatchedStatements`参数的关键作用。通过对比启用前后的性能差异,揭示了其将多条INSERT语句重写为单条多值语句以大幅减少网络往返和服务器解析开销的工作原理,并提供了实战配置与优化建议,帮助开发者实现数十倍的批量插入性能提升。

lg888的博客 798

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

为什么你的JDBC连接总是超时?深入剖析网络层与驱动层的3大陷阱

解决Java JDBC数据库连接超时难题,深入解析网络延迟、连接池配置与驱动兼容性三大陷阱。涵盖高并发场景下的优化策略与排查方法,提升系统稳定性与响应速度,值得收藏。

VarIsle的博客 842

【JDBC】JDBC连接mySQL数据库常见错误

正确的代码: package java_project_jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class JDBC_demo { static { // 加载驱动 try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException

竹子的博客 1万+

5分钟极速上手:ClickHouse JDBC驱动完全指南

ClickHouse JDBC驱动是连接Java应用与高性能列式数据库ClickHouse的官方桥梁,专为实时分析和大数据处理场景设计。无论你是需要构建电商实时报表系统、日志分析平台,还是处理海量数据的业务应用,这款驱动都能帮你轻松搞定数据连接问题。 ## 🎯 快速启动:三步搞定基础连接 ### 第一步:添加项目依赖 在你的Maven项目中,添加以下依赖配置: ```xml <depen

gitblog_00928的博客 1149

JDBC实战避坑指南:驱动加载、URL解析与连接池真相

JDBC是Java应用访问数据库的基础技术,其核心在于驱动注册机制、连接URL协议解析和连接资源管理。从JDBC 4.0起,SPI服务发现取代了脆弱的Class.forName()显式加载,但ClassLoader隔离问题仍导致常见ClassNotFoundException;MySQL 8+与OceanBase等国产数据库的JDBC URL参数(如useSSL、serverTimezone、loadbalance)并非可选配置,而是直接影响连接建立、时区转换与高可用路由的关键控制项;而DataSource

mxdxm8899的专栏 451

致命陷阱:PostgreSQL JDBC驱动未设置bytea参数导致的PreparedStatement.toString()异常分析与解决方案

你是否遇到过这样的场景:生产环境日志中突然出现`NullPointerException`,堆栈指向`PgPreparedStatement.toString()`方法?或者发现数据库审计日志中出现不完整的SQL语句,包含`?`占位符而非预期的`bytea`参数值?这些问题很可能源于PostgreSQL JDBC驱动(pgjdbc)在处理未设置的`bytea`类型参数时的特殊行为。 本文将深入分...

gitblog_07897的博客 384
下一篇: LoadRunner12.x简易入门教程--(一)回放与录制
兜茄破
博客等级 码龄14年 246粉丝 12原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值