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

 

转载于:https://www.cnblogs.com/ngchen/p/7892019.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值