1. 程式人生 > >[轉帖]MySQL的sum函式返回的型別

[轉帖]MySQL的sum函式返回的型別

原帖地址: http://bylijinnan.iteye.com/blog/1984472?utm_source=tuicool

摘要 : 

  1. The SUM() and AVG() functions return a DECIMAL value for exact-value arguments (integer or DECIMAL), and a DOUBLE value for
     approximate-value arguments (FLOAT or DOUBLE). (Before MySQL 5.0.3, SUM() and AVG() return DOUBLE for all numeric arguments.)  



原文:

今天專案切換資料庫時,出錯 

訪問資料庫的程式碼大概是這樣: 

Java程式碼   收藏程式碼
  1. String sql =  "select sum(number) as sumNumberOfOneDay from tableName";  
  2. List<Map> rows = getJdbcTemplate().queryForList(sql);  
  3. for (Map row : rows) {  
  4.     SomeBean item = new SomeBean();  
  5.     item.setSumNumberOfOneDay(objectToInt(row.get("sumNumberOfOneDay")));  
  6.   
  7. }  
  8.       
  9. private int objectToInt(Object obj) {  
  10.     return Integer.parseInt("" + obj);  
  11. }  


表字段“number”的型別是int(10) unsigned 
        
連線資料庫DataBaseA,測試執行正常;切換到另一資料庫DataBaseB(資料庫表,表名,表結構一樣)時,發現報錯: 
java.lang.NumberFormatException: For input string: "10.0" 

把sql語句拷貝到MySQL命令列窗口裡面直接執行,sum(number)返回的值是10; 
但在Spring的getJdbcTemplate().queryForList(sql)返回,則變成了10.0, 
列印row.get("sumNumberOfOneDay").getClass()的結果是:class java.lang.Double 

切回DataBaseA,列印結果是java.math.BigDecimal 

兩個資料庫的查詢結果在MySQL命令列視窗返回整數,但在Java程式中返回浮點數 

那不用Spring,直接操作JDBC: 
Java程式碼   收藏程式碼
  1. Connection conn = getJdbcTemplate().getDataSource().getConnection();  
  2.            Statement st = conn.createStatement();  
  3.            ResultSet rs = st.executeQuery(sql);  
  4.            ResultSetMetaData rsmd = rs.getMetaData();  
  5.            for (int i = 1; i <= rsmd.getColumnCount(); i++) {  
  6.                String name = rsmd.getColumnName(i);  
  7.                String type = rsmd.getColumnTypeName(i);  
  8.                System.out.println(name + ", " + type);  
  9.            }  

DataBaseA列印的結果: 
sumNumberOfOneDay, DECIMAL 

DataBaseB列印的結果: 
sumNumberOfOneDay, DOUBLE 

基本可判斷是MySQL的問題 

網上搜索一下,果然: 
Java程式碼   收藏程式碼
  1. The SUM() and AVG() functions return a DECIMAL value for exact-value arguments (integer or DECIMAL), and a DOUBLE value for approximate-value arguments (FLOAT or DOUBLE). (Before MySQL 5.0.3, SUM() and AVG() return DOUBLE for all numeric arguments.)  

http://stackoverflow.com/questions/10592481/what-is-the-return-type-of-sum-in-mysql  

原來MySQL 5.0.3之前的版本,sum函式返回的是DOUBLE型別 

回頭檢查一下MySQL的版本: 

DataBaseA: 
5.1.44 Source distribution 

DataBaseB: 
4.1.7-standard-log 

果然是這樣 

解決辦法: 
1.笨方法,就是重寫objectToInt方法: 
Java程式碼   收藏程式碼
  1. if (obj instanceof Double) {  
  2.            return ((Double)obj).intValue();  
  3.        }  
  4.        if (obj instanceof BigDecimal) {  
  5.            return ((BigDecimal)obj).intValue();  
  6.        }  
  7.        return Integer.parseInt(obj.toString());  
  8.           

2.利用Spring的BeanPropertyRowMapper: 
Java程式碼   收藏程式碼
  1. List<SomeBean> list = getJdbcTemplate().query(sql, new BeanPropertyRowMapper(SomeBean.class));  

應該儘量採用方法2,避免自己處理 

檢視一下Spring的getJdbcTemplate().query(sql, new BeanPropertyRowMapper(SomeBean.class))方法, 
發現它的大體思路是這樣: 
1.通過SomeBean.class得到所有property 
2.根據property的型別,呼叫ResultSet.getXXX()得到對應的值 
在ResultSet.getXXX()方法裡面,就實現了型別轉換 
例如com.mysql.jdbc.Result的getInt方法(關鍵部分的程式碼): 
Java程式碼   收藏程式碼
  1. val = getString(columnIndex);  
  2.         if ((val != null) && (val.length() != 0)) {  
  3.             if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)  
  4.                     && (val.indexOf(".") == -1)) {  
  5.                 return Integer.parseInt(val);  
  6.             } else {  
  7.                 // Convert floating point  
  8.                 return (int) (Double.parseDouble(val));  
  9.             }  
  10.         } else {  
  11.             return 0;  
  12.         }