zoukankan      html  css  js  c++  java
  • 对于Oracle中Number类型的字段映射成Java中的具体类型的问题

    我在Oracle中给一个用户Id字段设置为Number类型,使用JDBC在完成ORM的时候,以为其可以自动转换为Integer,因为我的POJO类id使用的就是Integer。但事实是,我在测试的时候,发现所有的用户id全为null,还在奇怪明明数据库中id是有值的,为什么取不到?

    原因在于Oracle的Number类型映射为Java类型中的 java.math.BigDecimal (不可变的、任意精度的有符号十进制数)类型,并不是我简单认为的 Integer ,还会报一个错误:

    就是说BigDecimal 的字段不能set进Integer类型的属性中

    我发现,其实如果使用原生的JDBC来封装数据,在这个id字段上,直接使用rs.getInt进我们的Integer字段是没有问题的:

        public List<User> findList2() throws Exception {
            Connection connection=null;
            PreparedStatement ps=null;
            ResultSet rs=null;
            List<User> list=null;
            try {
                connection = super.getConnection();
                String sql="select eu_user_id from easybuy_user";
                ps = connection.prepareStatement(sql);
                rs = ps.executeQuery();
                list = new ArrayList<User>();
                while(rs.next()){
                    User user=new User();
                    user.setEu_user_id(rs.getInt("eu_user_id"));
                    list.add(user);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
                super.closeAll(connection, ps, rs);
            }
            return list;
        }

    那么为什么我会出现这个错误呢?

    原因在于为了方便JDBC的编写,我使用一个进行简单封装的BaseDaoImpl,它的查询使用的反射来做的,好像也必须使用反射,因为每个POJO类的属性类型不一致嘛:

    ublic List<Object> executeQuery2(String sql, Object[] objParam, Class<?> className) throws Exception {
    
            List<Object> list = new ArrayList<Object>();
    
            Connection conn = this.getConnection();
            PreparedStatement ps = conn.prepareStatement(sql);
            ResultSet rs = null;
            if (objParam != null) {
                for (int i = 0; i < objParam.length; i++) {
                    ps.setObject((i + 1), objParam[i]);
                }
            }
            rs = ps.executeQuery();
    
            //Class<?> clz = Class.forName(className);
            Class<?> clz=className;
            Field[] fs = clz.getDeclaredFields();
            while (rs.next()) {
                Object objInstrance = clz.newInstance();
    
                for (Field f : fs) {
                    try {
                        String fieldName = f.getName();
                        Object fieldValue = rs.getObject(fieldName);
                        //System.out.println(fieldName+":"+fieldValue+"	"+f.getType()+"	"+fieldValue.getClass());
                        f.setAccessible(true);
                        f.set(objInstrance, fieldValue);
                    } catch (Exception ex) {
                         ex.printStackTrace();
                    }
                }
                list.add(objInstrance);
            }
            this.closeAll(conn, ps, rs);
            return list;
        }

    没有对BigDecimal类型进行处理,我们也不太可能在POJO中使用BigDecimal类型,所以就没能将BigDecimal 的字段映射成Integer ,就报上面的异常了,稍微修改一下,加一个判断:

    public List<Object> executeQuery2(String sql, Object[] objParam, Class<?> className) throws Exception {
    
            List<Object> list = new ArrayList<Object>();
    
            Connection conn = this.getConnection();
            PreparedStatement ps = conn.prepareStatement(sql);
            ResultSet rs = null;
            if (objParam != null) {
                for (int i = 0; i < objParam.length; i++) {
                    ps.setObject((i + 1), objParam[i]);
                }
            }
            rs = ps.executeQuery();
    
            //Class<?> clz = Class.forName(className);
            Class<?> clz=className;
            Field[] fs = clz.getDeclaredFields();
            while (rs.next()) {
                Object objInstrance = clz.newInstance();
    
                for (Field f : fs) {
                    try {
                        String fieldName = f.getName();
                        Object fieldValue = rs.getObject(fieldName);
                        if("java.math.BigDecimal".equals(fieldValue.getClass().getName()))
                        {     //如果是java.math.BigDecimal类型属性,就转换为Integer,使用Integer的parseInt即可
                            fieldValue=Integer.parseInt(fieldValue.toString());
                        }
                        //System.out.println(fieldName+":"+fieldValue+"	"+f.getType()+"	"+fieldValue.getClass());
                        f.setAccessible(true);
                        f.set(objInstrance, fieldValue);
                    } catch (Exception ex) {
                         ex.printStackTrace();
                    }
                }
                list.add(objInstrance);
            }
            this.closeAll(conn, ps, rs);
            return list;
        }

    这只是一种折中的办法,因为我们的java.math.BigDecimal类型只能转换为Integer了,如果POJO中id类型为Long,又不行了。所以存在一定的局限性,不太灵活。应该是根据我们POJO类中的id属性的具体类型去转换,我不知道具体的代码应该怎样去写。

    或许我们应该使用 commons-dbutils.jar  中的QueryRunner类作为BaseDao来使用?我在(Jsp+Servlet+JDBC的使用复习)中使用了一个TxQueryRunner类就是对QueryRunner进行了简单封装。

    一般情况下,我们不太会遇到这种异常的出现,因为强大的框架已经帮助我们完成了这些琐碎问题的处理,但是适时的了解一下底层的东西,还是有一定好处的

  • 相关阅读:
    my first aws native 19c rac ​​​​
    Geeks3D FurMark
    Best Graphics Card Benchmarking Softwares in 2020
    通过机器学习发现文本中的见解和关系
    pip intsall 遇到的各种问题
    python中利用redis构建任务队列(queue)
    fake-useragent,python爬虫伪装请求头
    如何将python3.6软件的py文件打包成exe程序
    python 时间和时间戳的转换
    Python
  • 原文地址:https://www.cnblogs.com/lz2017/p/7603001.html
Copyright © 2011-2022 走看看