JDBC项目实践

这几天学习了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


   

 

posted @ 2015-12-26 15:34  跨七海的风  阅读(2353)  评论(0编辑  收藏  举报