JDBC項目實踐

jopen 8年前發布 | 23K 次閱讀 JDBC Java開發

原文  http://www.cnblogs.com/fengdashen/p/5078190.html

這幾天學習了JDBC的接口,從簡單的連接,到不斷地對JDBC的代碼進行優化,最后到實體類,DAO類的設計,現在對這幾天所學做一個總結:

首先是軟件的系統組成:

數據庫中有很多的表:Customer,Department,Order,Account等等,為了訪問每個表,在java中建立相關的DAO,這些DAO構成數據訪問層。java通過調用DAO,達到訪問數據庫的目的

下面是工程的創建步驟:

1:導入工具包以及配置文件

1.1:導入訪問JDBC的驅動包:commons-dbcp2-2.1.1.jar,commons-logging-1.2.jar,commons-pool2-2.42.jar,ojdbc6.jar并對不同的包buildpath;

1.2: 創建Utils包,導入工具類DBUtils.java和配置文件db.properties,這兩個工具類是JDBC的核心包,里面有連接數據庫,斷開連接的方法

DBUTils.java的源代碼:

package utils;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import org.apache.commons.dbcp2.BasicDataSource;

public class DBUtils {
    private static String driver = null;
    private static String url = null;
    private static String user = null;
    private static String password = null;

    private static BasicDataSource ds = null;
    //靜態塊
    static{
        Properties props = new Properties();
        try {
            //路徑使用包路徑
            String path = "utils/db.properties";
            props.load(
                       DBUtils.class.getClassLoader()
                       .getResourceAsStream(path));

            driver  = props.getProperty("driver");
            url  = props.getProperty("url");
            user  = props.getProperty("user");
            password  = props.getProperty("password");
            //ds中已經有了幾個創建好的連接
            ds = new BasicDataSource();//創建連接池
            ds.setDriverClassName(driver);
            ds.setUrl(url);
            ds.setUsername(user);
            ds.setPassword(password);
            ds.setInitialSize(
                    Integer.parseInt(props.getProperty("intialSize")));


        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*創建連接*/
    public static Connection getConnection()
       throws ClassNotFoundException, SQLException{
        Connection conn = null;
        if(ds!=null){
             conn = ds.getConnection();
        }
        return conn;
    }

    /*關閉連接*/
    public static void closeConnection(Connection conn) throws SQLException{
        if(conn!=null)
            conn.close();
    }

}

View Code

讀取的配置文件db.properties,里面放了Oracle的驅動,url,用戶user密碼 格式是key = value

db.properties的源代碼:

#key = value
driver =   oracle.jdbc.OracleDriver
url =   jdbc:oracle:thin:@localhost:1521:xe
user =   fengweijie
password=   1070937053

#driver = com.mysql.jdbc.Driver
#url = jdbc:mysql:localhost:3306/test?useUni

intialSize = 10

View Code

完成之后項目截圖:

2:創建實體包entity:里面存放的是數據庫里面的表,例如部門表Dept,員工表Emp,根據表的數據類型創建Dept.java和Emp.java,并在Dept.java和Emp.java中添加get(),set()方法,以及tostring()方法;完成之后項目如圖;

3:創建iDAO包:里面存放的是訪問數據庫的接口,以員工表和部門表為例,對應的是IEmp.java,Idept.java

4:創建DAO包:里面是實現IDAO的數據訪問層,對應EmpDAO.java,Dept.java,用來實現訪問數據庫中對用的表

由于2,3,4步驟是體力活,所以一步到位,項目截圖如圖所示:

下面概述一下項目框架中的技巧:

由于在DAO中,每一個方法都需要獲得連接數據庫,以find函數為例,實現部門表的查找,每次都需要進行連接,查詢,關閉,代碼如下:

public void find(){
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;

        try {

            conn = DBUtils.getConnection();
            //事務開始
            conn.setAutoCommit(false);
            //業務邏輯




            conn.commit();

        } catch (Exception e) {
            try {
                conn.rollback();
            } catch (SQLException sqkex) {
                // TODO Auto-generated catch block
                sqkex.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            try {
                conn.setAutoCommit(true);
                if(conn !=null)  conn.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

        }

    }

不同函數之間,例如按照部門編號查找,按照部門所處位置查找,等等,只是代碼中的業務邏輯不同,其他的部分一致,而除了部門表以外,其他比如員工表也需要進行查詢,也是業務邏輯不同,為了解決這個問題,需要寫一個總的find方法,放在BaseDAO中

BaseDAO的源代碼:

package DAO;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import utils.DBUtils;

public abstract class BaseDAO<T> {
    /*
     * 所有find方法的三大差別
     * 1:SQL語句不通
     * 2:?參數有幾個不確定,類型不確定
     * 解決方法:類型不確定用:用object接住
     *       個數不確定用數組解決
     * Object[] params能接住所有的
     * 3:返回值對象不確定,解決 泛型類 */
    protected List<T> find(String sql,Object[] params)throws Exception{

        List<T> l = new ArrayList<T>();

        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;

        try {
            conn = DBUtils.getConnection();
            pstmt = conn.prepareStatement(sql);

            //問題1:不知道set什么,set幾次
            //有Object[]params
            if(params!=null)
                for (int i = 0; i < params.length; i++) {
                    pstmt.setObject(i+1, params[i]);
                }
            rs = pstmt.executeQuery();
            while(rs.next()){
                l.add(toEntity(rs));

            }

            return l;
        } catch (Exception ex) {
            throw ex;

        }finally {
            if(rs!= null) rs.close();
            if(pstmt != null) pstmt.close();

            DBUtils.closeConnection(conn);

        }    
    }

    /*
     * 因為while中的對象屬性差異無法統一
     * 完全交給子類自行完成
     * */
    public abstract T toEntity(ResultSet rs) throws Exception;

}

View Code

在BaseDAO 中,面臨的問題有三:

1:SQL語句的不同,

2:SQL語句中的參數類型不能確定

3:返回的對象不能確定

解決的方法分別是:

1:SQL語句不同,定義String sql變量

2:SQL語句中的參數類型不確定,使用Object[]params接住所有的參數

3:返回值對象不確定,使用泛型,當其他的DAO繼承BaseDAOI時候,將T改寫為對應的類型即可;

因此find的生命定義為:protected List<T> find(String sql,Object[] params)throws Exception{}

find 函數中的經典代碼:

1:在業務邏輯中填入參數:

//問題1:不知道set什么,set幾次
//有Object[]params
if(params!=null)
     for (int i = 0; i < params.length; i++) {
             pstmt.setObject(i+1, params[i]);
   }

2:返回結果:

while(rs.next()){
        l.add(toEntity(rs));
}

因為在while中的數據類型差異太大,無法統一,完全交給子類處理,定義抽象方法:

public abstract T toEntity(ResultSet rs) throws Exception;

項目源代碼下載地址: http://download.csdn.net/detail/generoius/9378231

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!