Dao层设计思想、JdbcUtils类、数据库连接池技术

简介: Dao层设计思想、JdbcUtils类、数据库连接池技术

1 Dao设计思想

Java语言要操作数据库表里面的数据时,要使用jdbc,但是jdbc的代码非常的繁琐,如果经常操作数据的话,这些代码的重复度会很高。所以我们把经常对表的相关操作封装到我们的dao类。这样就提高了代码的利用率,提高了系统的可维护性,可扩展性。

Dao(data access object)数据访问对象。


Dao里面需要有以下几个组件:


1.Person类。实体类。

a) 这个类跟表是一一对应的。

b) 他里面的属性跟表里面的字段(列)是一一对应的。

c) 属性私有,要有get和set方法。以及构造方法。

d) 实现序列化接口。


2.PersonDao类。Dao类

a) 里面五个方法,增删改查。

b) Void insert(Person p)

c) Void delete(int id)

d) Vodi update(Person p)

e) List selectAll()

f) Person selectOne(int id)


3.Test类测试类

a) 调用dao方法,对dao方法进行测试。


Dao的作用:

1.提高代码的可利用率

2.让各个组件功能更加单一,满足单一职能原则。


下面是一个Dao类的增删改查方法:

package jdb
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class PersonDao {
  /*
   * 到数据库表里面把p插入进去
   */
  public void insert(Person p){
//    System.out.println(p.getId()+"\t"+p.getName());
    Connection conn=null;
    PreparedStatement ps=null;
    ResultSet rs=null;
    try{
      conn=JdbcUtils.getConnection();
      //3.写sql
      String sql="insert into person values(person_seq.nextval,?,?,?,?)";
      //4.创建ps
      ps=conn.prepareStatement(sql);
      //5.给占位符赋值
      ps.setString(1,p.getName());
      ps.setInt(2,p.getAge());
      ps.setString(3,p.getTel());
      ps.setString(4,p.getAddress());
      //6.执行
      ps.executeUpdate();
    }catch(Exception e){
      e.printStackTrace();
    }finally{
      JdbcUtils.closeAll(conn,ps,rs);
    }
  }
  /**
   * 根据id把数据库表里面对应的数据删除掉
   * @param id 要删除的数据的编号
   */
  public void delete(int id){
    Connection conn=null;
    PreparedStatement ps=null;
    ResultSet rs=null;
    try{
      conn=JdbcUtils.getConnection();
      //3.写sql
      String sql="delete from person where id=?";
      //4.创建ps
      ps=conn.prepareStatement(sql);
      //5.给占位符赋值
      ps.setInt(1,id);
      //6.执行
      ps.executeUpdate();
    }catch(Exception e){
      e.printStackTrace();
    }finally{
      JdbcUtils.closeAll(conn, ps, rs);
    }
  }
  public void update(Person p){
    Connection conn=null;
    PreparedStatement ps=null;
    ResultSet rs=null;
    try{
      conn=JdbcUtils.getConnection();
      //3.写sql
      String sql="update person set name=?,age=?,tel=?,address=? where id=?";
      //4.创建ps
      ps=conn.prepareStatement(sql);
      //5.给占位符赋值
      ps.setString(1,p.getName());
      ps.setInt(2,p.getAge());
      ps.setString(3,p.getTel());
      ps.setString(4,p.getAddress());
      ps.setInt(5,p.getId());
      //6.执行
      ps.executeUpdate();
    }catch(Exception e){
      e.printStackTrace();
    }finally{
      JdbcUtils.closeAll(conn,ps,rs);
    }
  }
  public Person selectOne(int id){
    Connection conn=null;
    PreparedStatement ps=null;
    ResultSet rs=null;
    Person p=null;
    try{
      conn=JdbcUtils.getConnection();
      //3.写sql
      String sql="select * from person where id=?";
      //4.创建ps
      ps=conn.prepareStatement(sql);
      //5.执行
      ps.setInt(1, id);
      rs=ps.executeQuery();
      if(rs.next()){
        //获取表中每一个字段的值
        String name=rs.getString("name");
        int age=rs.getInt("age");
        String tel=rs.getString("tel");
        String address=rs.getString("address");
        //把上面这些数据封装到person对象里面
        p=new Person(id,name,age,tel,address);
      }
    }catch(Exception e){
      e.printStackTrace();
    }finally{
      JdbcUtils.closeAll(conn,ps,rs);
    } 
    return p;
  }
  /*
   * 到数据库里面把所有的person实体查询出来,封装到list集合,然后返回该list集合。
   */
  public List<Person> selectAll(){
    Connection conn=null;
    PreparedStatement ps=null;
    ResultSet rs=null;
    List<Person> perList=new ArrayList<Person>();
    try{
      conn=JdbcUtils.getConnection();
      //3.写sql
      String sql="select * from person";
      //4.创建ps
      ps=conn.prepareStatement(sql);
      //5.执行
      rs=ps.executeQuery();
      while(rs.next()){
        //获取表中每一个字段的值
        int id=rs.getInt("id");
        String name=rs.getString("name");
        int age=rs.getInt("age");
        String tel=rs.getString("tel");
        String address=rs.getString("address");
        //把上面这些数据封装到person对象里面
        Person p=new Person(id,name,age,tel,address);
        //把person放入list集合
        perList.add(p);
      }
    }catch(Exception e){
      e.printStackTrace();
    }finally{
      JdbcUtils.closeAll(conn,ps,rs);
    }   
    return perList;
  }
}

main, Test测试类:

package jdbc;
import java.util.List;
public class Test {
  public static void main(String[] args) {
    //实例化对象,才能调用该类里面的方法。
    PersonDao pd=new PersonDao();
    /*//调用insert方法时,需要的实参
    Person p=new Person(1,"zhangsan",20,"152226565","郑州市");
    Person p2=new Person("lisi",20,"152226565","郑州市");
    //调用pd对象的insert方法。
    pd.insert(p);*/
//    List<Person> perList=pd.selectAll();
//    for(Person p:perList){
//      System.out.println(p.getName()+"====="+p.getAge());
//    }
//    pd.delete(76);
//    Person p=new Person(77,"wangwu",21,"152226566","郑州市");
//    pd.update(p);
    Person p=pd.selectOne(77);
    System.out.println(p.getName()+"\t"+p.getAge());
  }
}

上面代码存在的问题:

1.dao类中的增删改查方法里面的代码的重复度非常高

2.每个方法开始都是要建立数据库连接

3.每个方法的结尾都是要释放资源。

4.我们要去除代码的重复度。

解决办法:

在dao类抽取两个方法。

Public Connection getConnection();

Public void closeAll(Connection conn,PreparedStatement ps,ResultSet rs);

这样,增删改查方法就可以重用上面两个方法的代码。


代码改进后又有新的问题:

1.后期项目复杂后,一个项目中对应多个表。

2.多个表就会有多个dao类

3.每个dao类中都需要数据库连接和释放资源。

4.因为刚才我们把建立连接和释放资源的代码封装到了PersonDao。那么其他的dao类调用这两个方法就非常麻烦。

2 JdbcUtils类

为了解决上面的问题,我们可以把建立连接和释放资源这两个方法封装到一个公共的工具类中JdbcUtils.这个类为所有dao类服务。

因为getConnection方法和closeAll跟JdbcUtils的对象没有关系。我们就把这两个方法定义成静态方法。这样dao类在使用这个两个方法时,就可以直接使用类名调用,而不用创建JdbcUtils对象了。

Dao类做增删改查操作,JdbcUtils类和实体类协助dao。

3 在JdbcUtils类里面使用Properties对象

虽然抽出来两个方法使得我们在开发的时候代码的重复度降低,但是现在项目还存在一个问题,就是加载驱动和创建数据库连接都是我们直接写死的,但是这些字符串常量是有可能要修改的。在真实运行环境中是没有源码的。没有源码就不能修改JdbcUtils类。


所以我们就可以把这些字符串常量抽取出来存放在一个文件中,然后每次读取的时候从这个文件中读取数据,这样就很好的解决了可以单独修改连接条件。

java Jdk中有一个类叫Properties。

1.他本身是一个map集合,可以存储数据。

2.他有load(Reader r);方法,该方法可以自动加载文本文件中的数据。

3.要使用文本文件中的数据时,可以调用getProperties(String)获取文本文件中的数据。


JdbcUtil类:

package com.macw.util;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
/**
 * @author 超伟
 * @2019年5月28日 下午1:51:58
 * @博客:https://blog.csdn.net/MacWx
 */
public class JdbcUtil {
  public static final Properties prop = new Properties(); 
  //把流操作提取到静态代码块里面。
  static{
    InputStream in = null;
    //使用类加载读取jdbc.properties文件
    in = JdbcUtil.class.getResourceAsStream("/jdbc.properties");
    try {
      //读取文件中的数据
      prop.load(in);
      Class.forName(prop.getProperty("DriverClassName"));
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      throw new RuntimeException(e);
    } catch (ClassNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      throw new RuntimeException(e);
    }finally{
      if (in!=null) {
        try {
          in.close();
        } catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    }
  }
  /**
   * @return Connection
   */
  public static Connection getConnection(){
    Connection conn = null;
    try {
      conn = DriverManager.getConnection(prop.getProperty("url"),prop.getProperty("username"),prop.getProperty("password"));
    } catch (SQLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      throw new RuntimeException(e);
    }
    return conn;
  }
  /**
   * 
   * @param conn
   * @param ps
   * @param rs
   */
  public static void toClose(Connection conn,PreparedStatement ps,ResultSet rs){
    try {
      if (rs!=null) {
        rs.close();
      }
    } catch (SQLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    try {
      if(ps!=null){
        ps.close();
      }
    } catch (SQLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    try {
      if (conn!=null) {
        conn.close();
      }
    } catch (SQLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
  public static void toClose(Connection conn,PreparedStatement ps){
    try {
      if(ps!=null){
        ps.close();
      }
    } catch (SQLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    try {
      if (conn!=null) {
        conn.close();
      }
    } catch (SQLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}

优化JdbcUtils类

1.在src里面创建一个jdbc.properties文件。在src右键—》new—》file—>jdbc.propertis

2.在这个文件中去写键值对,键值之间用=隔开

DriverClassName=oracle.jdbc.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:xe
username=hr
password=mcw

4 数据库连接池技术

为什么要使用数据库连接池:

1.频繁建立连接和释放连接非常浪费资源。

2.可以把一些连接存储起来,有人需要使用时,就从里面获取空闲连接

怎么使用数据库连接池?

C3P0,DBCP,DRUID,JDNI

DRUID是阿里实现的一种数据库连接池技术。

1.导入druid的相关jar包

2.将druid内部使用的字符串常量配置到properties配置文件中。

3.在代码中使用数据库连接池。

a) 创建出数据库连接池对象。(静态代码块)

b) 从数据库连接池对象里面获取连接。(getConnection())

c) 使用完后,把数据库连接归还给连接池。(closeAll())

可以参考JdbcUtils工具类里面的代码。

目录
相关文章
|
10天前
|
数据库 索引
深入探索数据库索引技术:回表与索引下推解析
【10月更文挑战第15天】在数据库查询优化的领域中,回表和索引下推是两个核心概念,它们对于提高查询性能至关重要。本文将详细解释这两个术语,并探讨它们在数据库操作中的作用和影响。
34 3
|
10天前
|
数据库 索引
深入理解数据库索引技术:回表与索引下推详解
【10月更文挑战第23天】 在数据库查询性能优化中,索引的使用是提升查询效率的关键。然而,并非所有的索引都能直接加速查询。本文将深入探讨两个重要的数据库索引技术:回表和索引下推,解释它们的概念、工作原理以及对性能的影响。
27 3
|
18天前
|
存储 缓存 监控
数据库优化技术:提升性能与效率的关键策略
【10月更文挑战第15天】数据库优化技术:提升性能与效率的关键策略
46 8
|
16天前
|
存储 NoSQL 关系型数据库
数据库技术深度解析:从基础到进阶
【10月更文挑战第17天】数据库技术深度解析:从基础到进阶
39 0
|
2月前
|
存储 NoSQL 关系型数据库
非关系型数据库-MongoDB技术(二)
非关系型数据库-MongoDB技术(二)
|
2月前
|
NoSQL 关系型数据库 MongoDB
非关系型数据库-MongoDB技术(一)
非关系型数据库-MongoDB技术(一)
|
9天前
|
负载均衡 网络协议 数据库
选择适合自己的数据库多实例负载均衡技术
【10月更文挑战第23天】选择适合自己的数据库多实例负载均衡技术需要全面考虑多种因素。通过深入的分析和评估,结合自身的实际情况,能够做出明智的决策,为数据库系统的高效运行提供有力保障。
|
7天前
|
SQL Java 数据库连接
在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,有效减少连接开销,提升访问效率
在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,有效减少连接开销,提升访问效率。本文介绍了连接池的工作原理、优势及实现方法,并提供了HikariCP的示例代码。
20 3
|
9天前
|
缓存 负载均衡 监控
数据库多实例的负载均衡技术深入
【10月更文挑战第23天】数据库多实例负载均衡技术是确保数据库系统高效运行的重要手段。通过合理选择负载均衡策略、实时监控实例状态、不断优化调整,能够实现资源的最优分配和系统性能的提升。在实际应用中,需要根据具体情况灵活运用各种负载均衡技术,并结合其他相关技术,以满足不断变化的业务需求。
|
9天前
|
Java 数据库连接 数据库
优化之路:Java连接池技术助力数据库性能飞跃
在Java应用开发中,数据库操作常成为性能瓶颈。频繁的数据库连接建立和断开增加了系统开销,导致性能下降。本文通过问题解答形式,深入探讨Java连接池技术如何通过复用数据库连接,显著减少连接开销,提升系统性能。文章详细介绍了连接池的优势、选择标准、使用方法及优化策略,帮助开发者实现数据库性能的飞跃。
18 4