對於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+"\t"+f.getType()+"\t"+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+"\t"+f.getType()+"\t"+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進行了簡單封裝。

一般情況下,我們不太會遇到這種異常的出現,因為強大的框架已經幫助我們完成了這些瑣碎問題的處理,但是適時的了解一下底層的東西,還是有一定好處的

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM