Hibernate 批次寫入 Oracle 時拋出 ORA-01461: can bind a LONG value only for insert into a LONG column。經查,欄位定義為 VARCHAR2(1024),但實際寫入資料超過 4000 位元組上限,導致 Oracle 隱式轉換為 LONG 型別,JDBC 驅動無法綁定而報錯。
Caused by: java.sql.BatchUpdateException: ORA-01461: 僅能綁定要插入 LONG 列的 LONG 值
at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(...)
VARCHAR2 最大長度為 4000 位元組(MAX_STRING_SIZE=STANDARD 時)。LONG 型別處理。PreparedStatement.setString() 綁定的是 VARCHAR2,不支援 LONG 綁定,因而拋出 ORA-01461。VARCHAR2(1024),但若字元集為 UTF-8,1024 字元最多 3072 位元組,仍在 4000 內;問題通常發生在 CLOB/大文本誤存入 VARCHAR2 或 字元集轉換膨脹。// 寫入前檢查
if (str.getBytes("UTF-8").length > 4000) {
str = truncateToBytes(str, 4000, "UTF-8");
}
確保資料長度符合 VARCHAR2 物理限制。
ALTER TABLE ... MODIFY COL_NAME CLOB;@Lob @Column(columnDefinition="CLOB") private String content;setCharacterStream() 或 setClob()。| 誤區 | 正確認知 |
|---|---|
| VARCHAR2(4000) 就能存 4000 字元 | 上限是 4000 位元組,UTF-8 下中文僅能存 ~1333 字元 |
| 超過 4000 會自動轉 CLOB | 會轉為 LONG(已棄用),不支援綁定,需顯式用 CLOB |
| LONG 可正常用 JDBC 操作 | LONG 已不建議使用,Oracle 12c+ 可能完全移除 |
SELECT OWNER, TABLE_NAME, COLUMN_NAME, DATA_TYPE, CHAR_LENGTH, CHAR_USED
FROM DBA_TAB_COLUMNS
WHERE DATA_TYPE IN ('VARCHAR2','NVARCHAR2','CHAR','NCHAR')
AND CHAR_LENGTH * CASE WHEN CHAR_USED='C' THEN 1 ELSE 3 END > 4000
ORDER BY OWNER, TABLE_NAME;
此查詢可找出定義長度可能超過 4000 位元組的欄位,提前排查。