使用NamedParameterJdbcTemplate向oracle插入枚举类型数据

使用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,其他字符同样会报错。

 
时间: 2024-10-11 00:32:08

使用NamedParameterJdbcTemplate向oracle插入枚举类型数据的相关文章

Oracle插入timestamp类型数据

表结构: create table TEST( ID INTEGER, BIRTHDAY TIMESTAMP ); 使用JDBC将日期插入到TIMESTAMP类型字段 import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.text.SimpleDateFormat; import

Jdbc插入date类型数据到oracle中

导入数据库jar包,路径如下: E:\oracle\product\10.1.0\Db_3\jdbc\lib\ojdbc14.jar 建表语句如下: create table t_user( id int primary key, username varchar(40), password varchar(16), phone varchar(40), address varchar(255), createdate date ) Jdbc代码如下: public void save(){ C

jdbc:mysql和oracle插入一条数据返回主键

package org.sin.common.dao; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import or

DELPHI中枚举类型数据的介绍和使用方法

在看delphi程序的时候看到aa=(a,b,c,d);这样的东西,还以为是数组,同事说是函数,呵呵,当然这两个都不屑一击,原来这样式子是在声明并付值一个枚举类型的数据.下边写下来DELPHI中枚举类型数据的介绍和使用方法.见笑..------------------------------------------------------枚举类型 Pascal程序不仅用于数值处理,还更广泛地用于处理非数值的数据.例如,性别.月份.星期几.颜色.单位名.学历.职业等.1.枚举类型的定义格式: ty

Oracle关于date类型数据的总结

往Oracle数据库中插入日期型数据(to_date的用法) INSERT  INTO  FLOOR  VALUES  ( to_date ( '2007-12-20 18:31:34' , 'YYYY-MM-DD HH24:MI:SS' ) ) ; 查询显示:2007-12-20 18:31:34.0 ------------------- INSERT  INTO  FLOOR  VALUES  ( to_date ( '2007-12-14 14:10' , 'YYYY-MM-DD HH2

Android 使用BaseAdapter 插入不同类型数据

在使用过程有时要在listview中插入不同类型的数据,比如说position=0的位置插入,广告,其它列表显示数据的情况. 一定要重写两种方法 @Override public int getItemViewType(int position) { Object object = bmobIMMessageList.get(position); if (object instanceof Integer) { return TYPE_BANNER; } else { return TYPE_D

Oracle处理Clob类型数据入库(String入库)

从网上查找一堆参考,要么语焉不详,要么不可行.自己鼓捣了一堆可以正常入库了.请看最后: insert into CP_V_INFO" + "(ID, "+ "PROJECT_ID, "+ …… "V_INFO, "+ …… "VERSION)values(?,?,?,?,?,?,?,?,?,?," + "?,?,EMPTY_CLOB(),?,?,?,?,?,?,?," + "?,?,?,

oracle数据库-备份ORACLE为dmp类型数据

刘备,为自己后期脑子不灵光时可以找个可以翻阅的地方. 一.第一部分导出ORACLE数据 1.数据库地址及账号密码: 数据库地址:10.10.10.132账号密码:oracle/oracle 2.使用Xshell登录: 输入地址及用户名称 3.查看当前数据库实例名称及安装地址路径 [[email protected] abs_dmp]$ env |grep ORACLE --查看当前数据库实例ORACLE_SID=orcl --由ORACLE_SID=orcl'可知,当前数据库实例为'orcl'O

oracle 插入每年每天数据

create or replace procedure PROC_P_ABC is v_sumday number :=0; i number :=0; v_calendar_date number :=null; v_day number :=null; begin select to_date(TO_CHAR(SYSDATE,'RRRR'),'yyyy') - to_date(TO_CHAR(SYSDATE,'RRRR')-1,'yyyy') INTO v_sumday from dual;