JDK+JDBC+MySQL实例及注意事项

by qx.zhong
Hangzhou 29 Jun 2014

开发环境
OS:  Win8.1 x64
JDK: 1.8 SE
DB:  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的同义词带符号的范围是-128127。无符号的范围是0255。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;
 }






JDK+JDBC+MySQL实例及注意事项,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。