今天在JavaEye上看大牛们的博客突然看到一篇文章标题为:"PreparedStatement中setString方法的异常"让我大喜,以前在项目中遇到这个问题,一直没有得到解决今天终于明白了!
以前项目中的代码如下:
java 代码
- sql = "INSERT INTO taw_attachment (attachmentname, attachmentfilename,"
- + "attachmentsize,cruser,crtime,info) VALUES (?,?,?,?,?,?)";
- pstmt.setString( 6,info);//info.length() > 2000
- pstmt.executeUpdate();
而数据库中对应的表Interface_log.info varchar2(4000);
在方法头加入如下代码:
java 代码
- if (info!=null && info.length()>2000){
- nfo = info.substring(0,2000);
- }
当再次Debug时还是抛出:Java.sql.SQLException:数据大小超出此类型的最大值!
当使用原始的Statement接口后问题解决,郁闷啊!!!
今天在文章中看到:
现在通过Oracle提供的JDBC文档来详细看看问题的来由。
我们都知道Oracle提供了两种客户端访问方式OCI和thin,
在这两种方式下,字符串转换的过程如下:
1、JDBC OCI driver:
在JDBC文档中是这么说的:
“
If the value of NLS_LANG is set to a character set other than US7ASCII or WE8ISO8859P1, then the driver uses UTF8 as the client character set. This happens automatically and does not require any user intervention. OCI then converts the data from the database character set to UTF8. The JDBC OCI driver then passes the UTF8 data to the JDBC Class Library where the UTF8 data is converted to UTF-16. ”
2、JDBC thin driver:
JDBC文档是这样的:
“If the database character set is neither ASCII (US7ASCII) nor ISO Latin1 (WE8ISO8859P1), then the JDBC thin driver must impose size restrictions for SQL CHAR bind parameters that are more restrictive than normal database size limitations. This is necessary to allow for data expansion during conversion.
The JDBC thin driver checks SQL CHAR bind sizes when a setXXX() method (except for the setCharacterStream() method) is called. If the data size exceeds the size restriction, then the driver returns a SQL exception (SQLException: Data size bigger than max size for this type) from the setXXX() call. This limitation is necessary to avoid the chance of data corruption when conversion of character data occurs and increases the length of the data. This limitation is enforced in the following situations:
(1)Using the JDBC thin driver
(2)Using binds (not defines)
(3)Using SQL CHAR datatypes
(4)Connecting to a database whose character set is neither ASCII (US7ASCII) nor ISO Latin1 (WE8ISO8859P1)
When the database character set is neither US7ASCII nor WE8ISO8859P1, the JDBC thin driver converts Java UTF-16 characters to UTF-8 encoding bytes for SQL CHAR binds. The UTF-8 encoding bytes are then transferred to the database, and the database converts the UTF-8 encoding bytes to the database character set encoding.”
原来是JDBC在转换过程中对字符串的长度做了限制。这个限制和数据库中字段的实际长度没有关系。
所以,setCharacterStream()方法可以逃过字符转换限制,也就成为了解决此问题的方案之一。
而JDBC对转换字符长度的限制是为了转换过程中的数据扩展。
根据实际测试结果,在ZHS16GBK字符集和thin驱动下,2000-4000长度的varchar字段都只能插入1333个字节(约666个汉字)。
To sum,解决PreparedStatement的setString中字符串长度问题可以有两种办法:
1、使用setCharacterStream()方法;
java 代码
- pstmt.setCharacterStream(index,new InputStreamReader(myString, myString.length());
2、使用OCI驱动连接Oracle数据库。
分享到:
相关推荐
关于PreparedStatement插入Date类型值的方法.txt
jdbc2.0版 PreparedStatement接口的用法
java中PreparedStatement和Statement的区别
PreparedStatement详细用法
在java中向访问数据库的sql语句一般放到类PreparedStatement类构造函数中,这里遇到的问题就是向sql语句中用setDate()插入时间时不能用java.util.date,而应用java.sql.date,这里就讲述了解决方法,一种是插入...
NULL 博文链接:https://huiminchen.iteye.com/blog/1097332
练习3:使用PreparedStatement插入宠物信息.zip
JDBC基础教程之PreparedStatement.doc )
JDBC中PreparedStatement接口提供的execute、executeQuery和executeUpdate之间的区别及用法
Statement和PreparedStatement之间的区别
NULL 博文链接:https://chaoyi.iteye.com/blog/2088080
一个preparedstatement是从java.sql.connection对象和所提供的sql字符串得到的,sql字符串中包含问号(?),这些问号标明变量的位置,然后提供变量的值,最后执行语句,例如: stringsql = "select * from people ...
MySql练习3:使用PreparedStatement插入宠物信息.zip MySql练习3:使用PreparedStatement插入宠物信息.zip MySql练习3:使用PreparedStatement插入宠物信息.zip
jdbc中preparedStatement比Statement的好处
包含于PreparedStatement对象中的SQL语句具有一个或多个IN参数。IN参数的值在SQL语句创建时未被指定。该语句为每一个IN参数保留一个问号(“?”)作为占位符。每个问号的值必须在语句执行之前,通过适当的Setxxx...
NULL 博文链接:https://stevenjohn.iteye.com/blog/968877
包含于 PreparedStatement 对象中的 SQL 语句可具有一个或多个 IN 参数。IN参数的值在 SQL 语句创建时未被指定。相反的,该语句为每个 IN 参数保留一个问号(“?”)作为占位符。每个问号的值必须在该语句执行之前...
实现类 UserDaoImpl.java(实现增删改查功能 使用预编译对象PreparedStatement 安全、便捷不需要我们去拼接字符串,特别是字段很多的时候 同时效率比Statement更高 ) 测试类 UserDaoTest.java(做测试增删改查功能...
此实例意在解决预处理命令PreparedStatement的setString()方法,在sql2008数据库中写入数据时,会自动补足空格的问题, 同时此实例也解决了当存在自动补足空格的问题时,使用nvarchar可以使查找出来的数据与原输入...