使用NamedParameterJdbcTemplate向oracle插入枚舉類型數據

来源:http://www.cnblogs.com/ngchen/archive/2017/11/24/7892019.html
-Advertisement-
Play Games

使用NamedParameterJdbcTemplate向資料庫插入含有枚舉類型數據的對象時會出現的JAVA和SQL類型不匹配的情況,例如對於如下的JAVA類定義和對應的Oracle表定義: 執行如下代碼插入數據時出現了“無效的列類型”錯誤 從Oracle中讀取varchar2類型數據裝配到相應的枚 ...


 使用NamedParameterJdbcTemplate向資料庫插入含有枚舉類型數據的對象時會出現的JAVA和SQL類型不匹配的情況,例如對於如下的JAVA類定義和對應的Oracle表定義:



 1 public class MetaPhysicColumn {
 2 
 3     public enum DataType{NUMBER, STRING, DATE, TIMESTAMP}
 4 
 5     private String id;
 6     private String name;
 7     private String description;
 8     private String tableId;
 9     private DataType dataType;
10     private boolean primaryKey;
11 }


1 create table meta_physic_column
2 (
3   id              varchar2(128),
4   name            varchar2(128),
5   description     varchar2(512),
6   table_id        varchar2(128),
7   data_type       varchar2(128),
8   primary_key     varchar2(1)
9 );

執行如下代碼插入數據時出現了“無效的列類型”錯誤

1 public void insertPhysicColumn(MetaPhysicColumn physicColumn) {
2     String sql = "insert into meta_physic_column (id, name, description, table_id, data_type, primary_key) values( :id, :name, :description, :tableId, :dataType, :primaryKey)"3     SqlParameterSource paramSource = new BeanPropertySqlParameterSource(physicColumn);
4     this.getNamedParameterJdbcTemplate().update(sql, paramSource);
5 }
org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [insert into cngtest(id, name, description, table_id, data_type, primary_key)  values( ?, ?, ?, ?, ?, ?)]; SQL state [99999]; error code [17004]; 無效的列類型; nested exception is java.sql.SQLException: 無效的列類型

    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:84)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:649)

從Oracle中讀取varchar2類型數據裝配到相應的枚舉類型不會出現問題,但是插入數據時,BeanPropertySqlParameterSource沒有提供枚舉類型到varchar2的映射,執行時會報錯。從源碼分析:SqlParameterSource是用來實現命名參數傳遞的介面,NamedParameterJdbcTemplate.update()通過調用其中的getSqlType(var)和getValue(var)兩個函數來獲取列對應的SQL類型和JAVA中綁定的對象,BeanPropertySqlParameterSource是SqlParameterSource的一個實現,繼承結構為BeanPropertySqlParameterSource extends AbstractSqlParameterSource implements SqlParameterSource,AbstractSqlParameterSource類中提供了registerSqlType()函數手動註冊列的類型,可以通過這個介面把枚舉對應列註冊為varchar2類型,代碼如下,但是每個對象中的枚舉屬性名字都不同,這個方法不具有一般性;

1 public void insertPhysicColumn(MetaPhysicColumn physicColumn) {
2     String sql = "insert into meta_physic_column (id, name, description, table_id, data_type, primary_key)      
3                   values( :id, :name, :description, :tableId, :dataType, :primaryKey)";
4     BeanPropertySqlParameterSource paramSource = new BeanPropertySqlParameterSource(physicColumn);
5     paramSource.registerSqlType("dataType", Types.VARCHAR);
6     this.getNamedParameterJdbcTemplate().update(sql, paramSource);
7 }

另一個解決方法是繼承BeanPropertySqlParameterSource,在子類中覆蓋getSqlType()方法,其中先調用父類的getSqlType(),如果沒有找到列對應的SQL類型,並且這個列對應對象為枚舉類型,則返回Varchar2, 在使用上子類和BeanPropertySqlParameterSource完全一樣,但是提供了對枚舉類型的支持,代碼如下

 1 public class MyBeanPropertySqlParameterSource extends BeanPropertySqlParameterSource {
 2 
 3     public MyBeanPropertySqlParameterSource(Object object) {
 4         super(object);
 5     }
 6     @Override
 7     public int getSqlType(String var) {
 8         int sqlType = super.getSqlType(var);
 9         if (sqlType == TYPE_UNKNOWN && hasValue(var)) {
10             if (getValue(var).getClass().isEnum()) {
11                 sqlType = Types.VARCHAR;
12             }
13         }
14         return sqlType;
15     }
16 }
1 public void insertPhysicColumn(MetaPhysicColumn physicColumn) {
2     String sql = "insert into meta_physic_column (id, name, description, table_id, data_type, primary_key) values( :id, :name, :description, :tableId, :dataType, :primaryKey)"3     SqlParameterSource paramSource = new MyBeanPropertySqlParameterSource(physicColumn);
4     this.getNamedParameterJdbcTemplate().update(sql, paramSource);
5 }

ps:對於boolean類型,BeanPropertySqlParameterSource將其映射為SQL的varchar2,將表結構對應類型設為number會報錯;從資料庫讀取varchar2類型到boolean類型時,JdbcTemplate只能識別0和1,其他字元同樣會報錯。

 

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 121,什麼是線程? 線程是操作系統能夠進行運算調度的最小單位,它被包含在進程之中,是進程中的實際運作單位。程式員可以通過它進行多處理器編程,你可以使用多線程對運算密集型任務提速。比如,如果一個線程完成一個任務要100毫秒,那麼用十個線程完成改任務只需10毫秒。 122,線程和進程有什麼區別? 線程 ...
  • 【直接上代碼】 #coding=utf-8#1、先將正則表達式的字元串形式編譯為Pattern實例 #2、使用Pattern實例處理文本並獲得匹配結果 #3、最後使用Match實例獲得消息,進行其他操作 import re # 【1】 re.compile(string[,flag]) 將正則表達式 ...
  • 《瘋狂java講義·第三版》,全書共851頁,18章。 目錄如下: 第1章 Java語言概述與開發環境 第2章 理解面向對象 第3章 數據類型和運算符 第4章 流程式控制制與數組 第5章 面向對象(上) 第6章 面向對象(下) 第7章 Java基礎類庫 第8章 Java集合 第9章 泛型 第10章 異常 ...
  • 1、單一界面的創建 2、常用操作方法 3、有些組件setSize不起作用時,用setPreferredSize,例如button.setPreferredSize(new Dimension(60, 22)); 4、表格一般用模型創建,方便更新管理: 表格數據的清除和更新: 5、消息提示框 ...
  • 什麼是virtualenv? virtualenv可以創建獨立Python開發環境,比如當前的全局開發環境是python3.6,現在我們有一個項目需要使用django1.3,另一個項目需要使用django1.9,這個時候就可以使用virtualenv創建各自的python開發環境了。 virtual ...
  • 最近看到了 一篇關於cookie和session的文章,寫的非常詳細全面,受益匪淺。寫一下從中學到了些什麼吧! 首先我們知道cookie和session是用來跟蹤會話的,因為http協議是無狀態的,也就是說伺服器和瀏覽器一旦結束會話,再次交換數據時就會創建新的會話。就像是A買了一件東西放入購物車,當 ...
  • 二進位的前導的零 二進位的前導的零 題目內容: 電腦內部用二進位來表達所有的值。一個十進位的數字,比如18,在一個32位的電腦內部被表達為00000000000000000000000000011000。可以看到,從左邊數過來,在第一個1之前,有27個0。我們把這些0稱作前導的零。 現在,你的任 ...
  • crud指資料庫或者持久層的基本操作,包括 增加(Create)、讀取查詢(Retrieve 取回)、更新(Update)和刪除(Delete) Spring不僅對JDBC進行了封裝,也對Hibernate進行了封裝,還有Ibatis jdbcTemplate與Java Web時的dbutils小型 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...