java學習 -- 利用類的反射和泛型自己動手寫jdbc封裝小類庫

xiaopengyaonixi發表於2016-12-17

 自己動手來封裝jdbc訪問類庫

在公司開發專案(ssh框架)的時候,我特別煩躁的一點就是每次用jdbc方式寫一個資料訪問(hibernate 可以用但是個人覺得對於複雜查詢難以做到和好的控制,可能自己還要慢慢研究吧,自己喜歡mybatis),每次都要寫一大堆模板程式碼,比較繁瑣!

下面說下我的思路。

第一步,分析抽象


從已有的程式碼,出發會發現,訪問資料庫的套路

-->讀取配置檔案(不是必須的,但是專案中這樣做,當然可以tomcat配置資料來源之類的啊)

-->獲取Connection

-->獲取statement或者preparestatement

--->編寫你的sql(這裡說一下,如果你用的statement這裡直接憑藉字元,如果用的preparestatement就是設定引數,以後的sql語句最好不要用statement,因為他很不安全!!一個很大的問題的sql注入!no zuo no die!)

-->執行sql命令

-->封裝結果

-->返回資料

所以,抽象出來,需要做的是

1.抽象出執行查詢和執行更新(update,insert,delete)


2.抽象結果處理


主要完成的就是著兩個問題


第二步,接上一步編寫執行sql的函式

1.sql執行方法

/**
	 * 執行sql
	 * @param sql		sql文
	 * @param params	引數
	 * @return	
	 */
	public static boolean executeSQL(String sql,String...params){
		boolean flag = false;
		Connection connection = null;
		PreparedStatement statement = null;
		try {			
			connection = getConnection();			
			statement = connection.prepareStatement(sql);
			for(int i = 0,n = params.length;i<n;i++){
				statement.setString(i+1, params[i]);
			}
			statement.execute(sql);
			flag = true;
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			if(statement!=null){
				try {
					statement.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if(connection!=null){
				try {
					connection.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		return flag;		
	}

2.sql的查詢方法

 

 * 查詢結果
     * @param sql        sql文
     * @param params    引數
     * @param handler    結果處理集
     * @return            返回結果集
     */
    public static<T> List<?> queryResult(String sql,String[] params,ResultMapper<T> handler,Class<T> c){
        List<Map<String,Object>> results = null;
        Connection connection = null;
        ResultSet resultSet  = null;
        PreparedStatement statement = null;
        try {
            connection = getConnection();
            statement = connection.prepareStatement(sql);
            for (int i = 0, n = (params!=null?params.length:0); i < n; i++) {
                statement.setString(i, params[i]);
            } 
            resultSet = statement.executeQuery();
            if(resultSet!=null){
                results = new ArrayList<>();     
                String[] name = null;
                ResultSetMetaData rsm = null;
                while(resultSet.next()){
                    if(rsm==null){
                        rsm = resultSet.getMetaData();
                        System.out.println(JSON.toJSONString(rsm));
                        int count = rsm.getColumnCount();    
                        System.out.println(count);
                        name = new String[count];
                        for(int i = 0;i<count;i++){
                            name[i] = rsm.getColumnName(i+1);
                        }
                    }
                    Map<String, Object> map = new HashMap<>();
                    // 開始填充值
                    for(String keys:name){
                        map.put(keys, resultSet.getString(keys));
                    }
                    results.add(map);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(statement!=null){  
                try {  
                    statement.close();  
                } catch (SQLException e) {  
                    e.printStackTrace();  
                }  
            }  
            if(resultSet!=null){
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(connection!=null){  
                try {  
                    connection.close();  
                } catch (SQLException e) {  
                    e.printStackTrace();  
                }  
            } 
        }
        // 開始處理結合
        List<T> lists = new ArrayList<>();
        if(results!=null){
            for(Map<String, Object> e:results){
                T t = (T) handler.convert(e,c);
                lists.add(t);
            }        
            return lists;
        }else{ 
            return null;
        }
    }

第三步,編寫資料對映介面和預設實現類

package com.handkoo.dao;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;

public class DButils<T> {

    private static final Logger logger = LoggerFactory.getLogger(DButils.class);
    
    private static String url = "";
    private static String user = "";
    private static String password = "";

    static {
        InputStream inputStream = DButils.class.getResourceAsStream("/jdbc.properties");
        Properties properties = new Properties();
        try {
            properties.load(inputStream);
            url = properties.getProperty("url");
            user = properties.getProperty("user");
            password = properties.getProperty("password");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static Connection getConnection() {
        Connection connection = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection(url, user, password);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return connection;
    }

    /**
     * 執行sql
     * 
     * @param sql
     *            sql文
     * @param params
     *            引數
     * @return
     */
    public static boolean executeSQL(String sql, String... params) {
        boolean flag = false;
        Connection connection = null;
        PreparedStatement statement = null;
        try {
            connection = getConnection();
            statement = connection.prepareStatement(sql);
            for (int i = 0, n = params.length; i < n; i++) {
                statement.setString(i + 1, params[i]);
            }
            statement.execute(sql);
            flag = true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (statement != null) {
                try {
                    statement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return flag;
    }

    /**
     * 查詢結果
     * 
     * @param sql
     *            sql文
     * @param params
     *            引數
     * @param handler
     *            結果處理集
     * @return 返回結果集
     */
    public static <T> List<?> queryResult(String sql, String[] params, ResultMapper<T> handler, Class<T> c) {
        List<Map<String, Object>> results = null;
        Connection connection = null;
        ResultSet resultSet = null;
        PreparedStatement statement = null;
        try {
            connection = getConnection();
            statement = connection.prepareStatement(sql);
            for (int i = 0, n = (params != null ? params.length : 0); i < n; i++) {
                statement.setString(i+1, params[i]);
            }
            resultSet = statement.executeQuery();
            if (resultSet != null) {
                results = new ArrayList<>();
                String[] name = null;
                ResultSetMetaData rsm = null;
                while (resultSet.next()) {
                    if (rsm == null) {
                        rsm = resultSet.getMetaData();
                        System.out.println(JSON.toJSONString(rsm));
                        int count = rsm.getColumnCount();
                        System.out.println(count);
                        name = new String[count];
                        for (int i = 0; i < count; i++) {
                            name[i] = rsm.getColumnName(i + 1);                                 
                        }
                    }
                    Map<String, Object> map = new HashMap<>();
                    // 開始填充值
                    for (String keys : name) {                     
                        map.put(keys, resultSet.getString(keys));
                    }
                    results.add(map);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (statement != null) {
                try {
                    statement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        // 開始處理結合
        List<T> lists = new ArrayList<>();
        if (results != null) {
            for (Map<String, Object> e : results) {
                T t = (T) handler.convert(e, c);
                lists.add(t);
            }
            return lists;
        } else {
            return null;
        }
    }

    /**
     * 型別轉化介面
     * 
     * @author PengChan
     * 
     * @param <T>
     */
    public interface ResultMapper<T> {
        @SuppressWarnings("hiding")
        <T> T convert(Map<String, Object> resource, Class<T> c);
    }

    /**
     * 預設的型別實現
     * 
     * @author PengChan
     * 
     */
    public class DefaultMapper implements ResultMapper<T> {

        @SuppressWarnings("hiding")
        public <T> T getInstance(Class<T> c) throws InstantiationException, IllegalAccessException {
            return c.newInstance();
        }

        /**
         * 轉化的核心方法
         */
        @SuppressWarnings("hiding")
        @Override
        public <T> T convert(Map<String, Object> resource, Class<T> c) {
            T t = null;
            try {
                t = getInstance(c);
                // 獲取所有的成員變數
                Field[] declaredFields = t.getClass().getDeclaredFields();
                // 迴圈遍歷設定值
                for (Field f : declaredFields) {
                    setValute(f, t, resource.get(f.getName()));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return t;
        }

        /**
         * 設定型別的值
         * 
         * @param fieldType
         * @param value
         */
        @SuppressWarnings({ "hiding", "rawtypes" })
        private <T> void setValute(Field field, T t, Object value) {
            try {
                Class fieldType = field.getType();
                field.setAccessible(true);
                if (fieldType.equals(int.class)) {// 如果是整形
                    field.setInt(t, (int) value);
                } else if (fieldType.equals(float.class)) {
                    field.setFloat(t, (float) value);
                } else if (fieldType.equals(boolean.class)) {
                    field.setBoolean(t, (boolean) value);
                } else if (fieldType.equals(double.class)) {
                    field.setDouble(t, (double) value);
                } else if (fieldType.equals(byte.class)) {
                    field.setByte(t, (byte) value);
                } else if (fieldType.equals(short.class)) {
                    field.setShort(t, (short) value);
                } else if (fieldType.equals(long.class)) {
                    field.setLong(t, (long) value);
                } else if (fieldType.equals(char.class)) {
                    field.setChar(t, (char) value);
                } else {
                    field.set(t, value);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }
     

}

呼叫方式:

DButils.queryResult(sql, null, new DButils().new DefaultMapper(), FitType.class);


注意:該工具類有一個侷限性,就是對應的java類的屬性名稱需要與資料庫的名稱一致才能匹配。(如果這樣,還需要配置xml檔案來建立實體類和資料庫表之間的對映,這不在考慮的範圍之內,建議使用mybatis)



執行的結果如下:


以上就是我全部的分析內容了,有的地方還需要完善。

相關文章