使用NamedParameterJdbcTemplate向oracle插入枚舉類型資料

來源:互聯網
上載者:User

標籤:.exe   sla   temp   frame   定義   date()   end   匹配   error   

 使用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_column2 (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,其他字元同樣會報錯。

 

使用NamedParameterJdbcTemplate向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.