PreparedStatement中setString方法的異常

來源:互聯網
上載者:User
PreparedStatement中setString方法的異常


其實也不應該說是異常,應該是多種因素導致的使用問題。
一般在有了一定Java編程經驗之後,大家都習慣用PreparedStatement代替Statement。
其好處就不用多說了。
但是卻在開發中出現了問題。
如有表:
create table test(
 id int,
 name   varchar2(3000)
)
當執行插入語句到
stmt.setString(2, myString);
的時候,出現如下異常: java.sql.SQLException: 資料大小超出此類型的最大值 而myString變數的內容為超過700的中文字元(測試的英文字元為2000個)。
也就是說一個中文字元佔據了3-4個位元組,而且英文字元個數也不對,這好像有點不可思議。
分析原因:
1、驅動程式在把SQL語句發給資料庫前,PreparedStatement會對字串進行預先處理並進行轉義替換;
2、字元集原因。 通過閱讀PreparedStatement文檔,發現有一個setCharacterStream方法可以解決這個問題:
stmt.setCharacterStream(2,new InputStreamReader(myString, myString.length());
替換之後中文字元可達1400多。


上次對PreparedStatement的setString中字串長度這個問題沒有解決透徹,
也沒有深入分析其中的原因。 現在通過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()方法;
2、使用OCI驅動串連Oracle資料庫。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.