by qx.zhongHangzhou 29 Jun 2014
開發環境OS: Win8.1 x64JDK: 1.8 SEDB: MySQL 5.5 Lib: mysql-connector-java.jar
1. MySQL資料庫資料類型與JDK之間的特殊對應關係
下表只列舉幾個特殊的值類型對照,其餘的又需要可以參考MySQL官網的值類型說明(http://dev.mysql.com/doc/refman/5.1/zh/index.html)以及JDK的相關資料。
MySQL |
JDK |
tinyint(1) |
boolean |
int unsigined |
long |
datetime |
java.sql.Timestamp |
varchar |
String |
在MySQL中,TINYINT(1)是BOOL, BOOLEAN的同義字帶符號的範圍是-128到127。無符號的範圍是0到255。BOOLEAN非zero為真,zero為假。INT UNSIGINED值的範圍超出了JDK的int類型(JDK中的整形類型都是帶符號的)的最大取值範圍,所以需要用long裝載。
2.
採用JDK的反射機制將JDBC ResultSet的自動載入到Bean類
首先要確保MySQL中的列名和JavaBean類的屬性名稱是一一對應的,然後就可以使用反射機制調用setter對Bean進行賦值,關鍵代碼:
/** * Using reflection to storage the result from database into Bean class. * */public static List<Object> resultSetToList(ResultSet rs, Class<?> cls) { Method[] methods = cls.getDeclaredMethods(); int methodLength = methods.length; int index; Map<String, Integer> map = new HashMap<String, Integer>(); // record all methods name in a HashMap, for quickly locate. for (index = 0; index < methodLength; index++) { map.put(methods[index].getName().toLowerCase(), index); } ResultSetMetaData meta = null; Object obj = null; List<Object> list = new ArrayList<Object>(); try { meta = rs.getMetaData(); int colCount = meta.getColumnCount();while (rs.next()) { obj = cls.newInstance(); for (int i = 1; i <= colCount; i++) { String colName = meta.getColumnName(i); String setMethodName = "set" + colName; // System.out.println(setMethodName); int j = map.get(setMethodName.toLowerCase()); //get index of method array setMethodName = methods[j].getName(); Object value = rs.getObject(colName); if(value == null){ continue; } try { Method setMethod = obj.getClass().getMethod(setMethodName, value.getClass()); setMethod.invoke(obj, value); } catch (Exception e) { System.out.println(setMethodName + " exception"); e.printStackTrace(); } } list.add(obj); }} catch (InstantiationException | IllegalAccessException | SQLException e) {e.printStackTrace();} return list; }
3. 其他說明
資料庫的串連於釋放是JDBC中最耗費時間及系統開銷的,因此推薦採用資料庫連接池處理。一個池設定最小串連數和最大串連數。最小串連數是串連池啟動時預設的初始化建立的串連,建多了會影響代碼的啟動時間,建立少了會出現不夠用的現象(雖然實際運行中,串連池檢測到需求數量大於最小串連數時,會自動新增串連)。故串連池的最小串連數是需要根據項目實際情況斟酌的。
4. 樣本項目4.1 資料庫表設計1)設計一個cake表,詳情如下:
mysql> describe cake;+--------------+---------------------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+--------------+---------------------+------+-----+---------+-------+| name | varchar(20) | NO | PRI | NULL | || serialNumber | int(10) unsigned | YES | | NULL | || buildDate | datetime | YES | | NULL | || isSweet | tinyint(1) unsigned | YES | | NULL | |+--------------+---------------------+------+-----+---------+-------+
2)初始化的資料:
mysql> select * from cake;+--------+--------------+---------------------+---------+| name | serialNumber | buildDate | isSweet |+--------+--------------+---------------------+---------+| Danisa | 2021344 | 2013-11-19 10:20:00 | 1 || Orion | 2004720 | 2014-06-29 22:00:00 | 0 |+--------+--------------+---------------------+---------+
4.2 Bean類設計1)Cake類的屬性:
private String name; private long serialNumber; private Timestamp buildDate; private boolean isSweet;
2)Bean中特殊值類型變數的Setter的設計細節: JDK整形類型的setter參數需用java.lang中的類,如long對應java.lang.Long, int對應java.lang.Integer。 這樣的動機是,可以使Bean的屬性符合2中敘述的resultSetToList的形參Class<?> cls。 本例中,ResultSet取出的MySql的int unsigned,會自動在記憶體中轉化為Long類型,故setter需要使用Long;
public void setSerialNumber(Long /*long*/ serialNumber) { //Type was java.lang.Long but not 'long'. this. serialNumber = serialNumber; }
從MySql取出的tinyint(1)存為Boolean,故Bean類的setter形參是Boolean類型。 此外,屬性isSweet在eclipse中自動產生的setter名為setSweet,在反射賦值時,就會出現找不到方法的異常,因為反射賦值搜尋的方法是'setissweet',所以要把自動產生的setter改名。
public void /*setSweet*/setIsSweet( /*boolean*/Boolean isSweet) { // Type was java.lang.Boolean but not boolean this. isSweet = isSweet; }