在路上

 找回密码
 立即注册
在路上 站点首页 学习 查看内容

JDBC项目实践

2017-2-7 13:41| 发布者: zhangjf| 查看: 471| 评论: 0

摘要: 原文 http://www.cnblogs.com/fengdashen/p/5078190.html 这几天学习了JDBC的接口,从简单的连接,到不断地对JDBC的代码进行优化,最后到实体类,DAO类的设计,现在对这几天所学做一个总结: 首先是软件的系统组 ...

原文 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的源代码:

  1. package utils;
  2. import java.sql.Connection;
  3. import java.sql.SQLException;
  4. import java.util.Properties;
  5. import org.apache.commons.dbcp2.BasicDataSource;
  6. public class DBUtils {
  7. private static String driver = null;
  8. private static String url = null;
  9. private static String user = null;
  10. private static String password = null;
  11. private static BasicDataSource ds = null;
  12. //静态块
  13. static{
  14. Properties props = new Properties();
  15. try {
  16. //路径使用包路径
  17. String path = "utils/db.properties";
  18. props.load(
  19. DBUtils.class.getClassLoader()
  20. .getResourceAsStream(path));
  21. driver = props.getProperty("driver");
  22. url = props.getProperty("url");
  23. user = props.getProperty("user");
  24. password = props.getProperty("password");
  25. //ds中已经有了几个创建好的连接
  26. ds = new BasicDataSource();//创建连接池
  27. ds.setDriverClassName(driver);
  28. ds.setUrl(url);
  29. ds.setUsername(user);
  30. ds.setPassword(password);
  31. ds.setInitialSize(
  32. Integer.parseInt(props.getProperty("intialSize")));
  33. } catch (Exception e) {
  34. e.printStackTrace();
  35. }
  36. }
  37. /*创建连接*/
  38. public static Connection getConnection()
  39. throws ClassNotFoundException, SQLException{
  40. Connection conn = null;
  41. if(ds!=null){
  42. conn = ds.getConnection();
  43. }
  44. return conn;
  45. }
  46. /*关闭连接*/
  47. public static void closeConnection(Connection conn) throws SQLException{
  48. if(conn!=null)
  49. conn.close();
  50. }
  51. }
  52. View Code
复制代码

读取的配置文件db.properties,里面放了Oracle的驱动,url,用户user密码 格式是key = value

db.properties的源代码:

  1. #key = value
  2. driver = oracle.jdbc.OracleDriver
  3. url = jdbc:oracle:thin:@localhost:1521:xe
  4. user = fengweijie
  5. password= 1070937053
  6. #driver = com.mysql.jdbc.Driver
  7. #url = jdbc:mysql:localhost:3306/test?useUni
  8. intialSize = 10
  9. 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函数为例,实现部门表的查找,每次都需要进行连接,查询,关闭,代码如下:

  1. public void find(){
  2. Connection conn = null;
  3. PreparedStatement pstmt = null;
  4. ResultSet rs = null;
  5. try {
  6. conn = DBUtils.getConnection();
  7. //事务开始
  8. conn.setAutoCommit(false);
  9. //业务逻辑
  10. conn.commit();
  11. } catch (Exception e) {
  12. try {
  13. conn.rollback();
  14. } catch (SQLException sqkex) {
  15. // TODO Auto-generated catch block
  16. sqkex.printStackTrace();
  17. }
  18. e.printStackTrace();
  19. }finally {
  20. try {
  21. conn.setAutoCommit(true);
  22. if(conn !=null) conn.close();
  23. } catch (SQLException e) {
  24. // TODO Auto-generated catch block
  25. e.printStackTrace();
  26. }
  27. }
  28. }
复制代码

不同函数之间,例如按照部门编号查找,按照部门所处位置查找,等等,只是代码中的业务逻辑不同,其他的部分一致,而除了部门表以外,其他比如员工表也需要进行查询,也是业务逻辑不同,为了解决这个问题,需要写一个总的find方法,放在BaseDAO中

BaseDAO的源代码:

  1. package DAO;
  2. import java.sql.Connection;
  3. import java.sql.PreparedStatement;
  4. import java.sql.ResultSet;
  5. import java.util.ArrayList;
  6. import java.util.List;
  7. import utils.DBUtils;
  8. public abstract class BaseDAO<T> {
  9. /*
  10. * 所有find方法的三大差别
  11. * 1:SQL语句不通
  12. * 2:?参数有几个不确定,类型不确定
  13. * 解决方法:类型不确定用:用object接住
  14. * 个数不确定用数组解决
  15. * Object[] params能接住所有的
  16. * 3:返回值对象不确定,解决 泛型类 */
  17. protected List<T> find(String sql,Object[] params)throws Exception{
  18. List<T> l = new ArrayList<T>();
  19. Connection conn = null;
  20. PreparedStatement pstmt = null;
  21. ResultSet rs = null;
  22. try {
  23. conn = DBUtils.getConnection();
  24. pstmt = conn.prepareStatement(sql);
  25. //问题1:不知道set什么,set几次
  26. //有Object[]params
  27. if(params!=null)
  28. for (int i = 0; i < params.length; i++) {
  29. pstmt.setObject(i+1, params[i]);
  30. }
  31. rs = pstmt.executeQuery();
  32. while(rs.next()){
  33. l.add(toEntity(rs));
  34. }
  35. return l;
  36. } catch (Exception ex) {
  37. throw ex;
  38. }finally {
  39. if(rs!= null) rs.close();
  40. if(pstmt != null) pstmt.close();
  41. DBUtils.closeConnection(conn);
  42. }
  43. }
  44. /*
  45. * 因为while中的对象属性差异无法统一
  46. * 完全交给子类自行完成
  47. * */
  48. public abstract T toEntity(ResultSet rs) throws Exception;
  49. }
  50. View Code
复制代码

在BaseDAO 中,面临的问题有三:

1:SQL语句的不同,

2:SQL语句中的参数类型不能确定

3:返回的对象不能确定

解决的方法分别是:

1:SQL语句不同,定义String sql变量

2:SQL语句中的参数类型不确定,使用Object[]params接住所有的参数

3:返回值对象不确定,使用泛型,当其他的DAO继承BaseDAOI时候,将T改写为对应的类型即可;

因此find的生命定义为:protected List find(String sql,Object[] params)throws Exception{}

find 函数中的经典代码:

1:在业务逻辑中填入参数:

  1. //问题1:不知道set什么,set几次
  2. //有Object[]params
  3. if(params!=null)
  4. for (int i = 0; i < params.length; i++) {
  5. pstmt.setObject(i+1, params[i]);
  6. }
复制代码

2:返回结果:

  1. while(rs.next()){
  2. l.add(toEntity(rs));
  3. }
复制代码

因为在while中的数据类型差异太大,无法统一,完全交给子类处理,定义抽象方法:

public abstract T toEntity(ResultSet rs) throws Exception;

项目源代码下载地址: http://download.csdn.net/detail/generoius/9378231

最新评论

小黑屋|在路上 ( 蜀ICP备15035742号-1 

;

GMT+8, 2025-7-9 07:07

Copyright 2015-2025 djqfx

返回顶部