今天在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数据库。
分享到:
相关推荐
"auth-web-app"项目中的"其他字符串安全示例"着重强调了在Java环境下处理字符串时可能遇到的安全问题和最佳实践。以下是对这个主题的详细阐述: 1. **防止SQL注入**:在Java Web应用中,直接将用户输入的数据拼接到...
在这个例子中,`my_procedure`是存储过程名,`123`是传递给存储过程的`IN`参数,而`OUT`参数是一个字符串类型,我们使用`getString()`方法读取。 请注意,不同的数据库可能需要不同的JDBC驱动和特定的语法。上述...
- **参数绑定**:PreparedStatement允许设置参数,数据库只需处理参数值,而非整个SQL字符串,减少了字符串拼接的开销。 - **缓存执行计划**:预编译后的执行计划会被数据库缓存,下次执行相同SQL时可直接复用,...
而${index}则是在SQL字符串中直接替换变量,不进行预编译,存在安全风险。 在多参数的情况下,MyBatis通常推荐使用Map或者注解@Param来传递参数。例如: ```java public User getUser(@Param("id") int id, @Param...
当你需要将一个字符串或者Reader对象插入到CLOB字段时,MyBatis默认可能无法正确处理。此时,你需要自定义一个TypeHandler来处理这种转换。创建一个实现`org.apache.ibatis.type.TypeHandler`接口的类,重写`...
在IT项目的开发过程中,遇到各种异常是难以避免的,这些异常不仅考验着开发者的耐心,更考验其解决问题的能力。从给定的文件信息来看,主要围绕Struts框架中出现的各种异常及其解决办法进行了详细的阐述。下面,我们...
例如,在测试环境中,我们可能需要替换数据库连接字符串,以便连接到测试数据库而不是生产数据库。此外,参数替换也可以用于动态调整SQL查询的行为,如根据条件决定是否包含某个子查询或过滤条件。在开发过程中,...
`setNonNullParameter`则是在插入或更新数据时,将Java对象转换为JSON字符串并设置到PreparedStatement中。 在实际应用中,你需要根据具体的需求和Java对象的结构,定义一个合适的TypeHandler,然后在MyBatis的...
示例代码展示了如何在不覆盖现有内容的情况下(`true`参数表示追加模式)向一个名为`filename`的文件中写入字符串`"aString"`。在`try`块中创建`BufferedWriter`实例,随后调用`write()`方法写入文本。如果在写入...
2. 使用PreparedStatement:避免直接拼接SQL字符串,而是使用PreparedStatement来设置参数。这样可以防止由于字符串格式化造成的精度丢失,同时还能防止SQL注入攻击。 3. 配置JDBC驱动:某些JDBC驱动可能有特定的...
3. 使用`PreparedStatement`的`setString()`方法时,确保字符串已经被正确编码。 4. 从结果集中获取数据时,使用`ResultSet.getString()`时,可能需要解码为正确的字符集。 5. 对于B/S应用,确保Web服务器和浏览器...
这是因为单引号是 SQL 语句中的特殊字符,用于定义字符串的开始和结束。如果插入的数据中包含单引号,SQL 语句将无法正确解析。 解决这个问题的方法是将单引号替换成两个单引号。在 SQL 语句中,连续两个单引号表示...
使用Array.join()方法连接字符串比使用string += "xx"更高效,特别是在大量字符串连接时,性能差距显著。 这些面试题覆盖了Java基础、Web开发、数据库操作、脚本语言JavaScript、操作系统和框架等多个领域,反映了...
在Java中,字符串默认使用Unicode(UTF-16)编码,但与其他系统交互时,可能需要进行编码转换。 3. **输入输出流的编码设置** 当Java程序读取或写入文件或网络流时,必须指定正确的字符编码。`InputStreamReader`...
`args`是命令行参数数组,`parseInt`用于将其中的字符串转换为整数。 4. **日期和时间处理**: - `new Date().toLocaleString()`:虽然已废弃,但仍然可用,它将当前日期和时间转换为本地格式的字符串。 - `...
本文将详细介绍如何通过调整 MySQL 的配置以及正确设置 JDBC 连接字符串来彻底解决中文乱码问题。 #### 二、MySQL 字符集配置 ##### 2.1 修改 MySQL 配置文件 **步骤 1:** 打开 MySQL 配置文件 `my.ini` (通常...
当使用`#{ruleName}`时,MyBatis会尝试将整个字符串`'A','B','C'`作为一个参数传递,而不是将其解析为三个独立的参数,这会导致SQL语法错误。所以,错误的处理方式是`AND a.rule_name IN (#{ruleName})`。 正确的...
例如,MySQL的连接字符串中可以包含`useUnicode=true&characterEncoding=UTF-8`来确保使用UTF-8编码。 3. SQL语句:在插入或查询数据时,SQL语句中涉及的字符串需要按照正确的编码进行处理。比如,使用...
具体来说,可以在连接字符串中添加`useCursorFetch=true`和`defaultFetchSize=100`两个参数。前者表示启用游标模式,后者指定每次从服务器获取的行数。 示例连接字符串: ``` jdbc:mysql://192.168.1.252:3306/lims...
在资源文件(如message.properties或message_zh_CN.properties)中,使用UTF-8编码存储中文字符串,并在页面中通过`<fmt:message>`标签显示。 7. **异常处理** - 在处理中文数据过程中,可能出现的乱码问题通常会...