zoukankan      html  css  js  c++  java
  • MySQL数据库学习笔记(十一)----DAO设计模式实现数据库的增删改查(进一步封装JDBC工具类)

    【声明】 

    欢迎转载,但请保留文章原始出处→_→ 

    生命壹号:http://www.cnblogs.com/smyhvae/

    文章来源:http://www.cnblogs.com/smyhvae/p/4059514.html

     

    【正文】

    一、DAO模式简介

    DAO即Data Access Object,数据访问接口。数据访问:故名思义就是与数据库打交道。夹在业务逻辑与数据库资源中间。

    DAO模式实际上是两个模式的组合,即Data Accessor (数据访问者)模式和 Active Domain Object(领域对象)模式。Data Accessor 模式实现了数据访问和业务逻辑的分离;Active Domain Object 模式实现了业务数据的对象化封装。

    需要注意的是,DAO设计模式是Java EE中的设计模式,而非Java SE中的23种设计模式。

    二、实现DAO模式

    一个典型的DAO实现有下列几个组件:

    • 一个DAO接口;
    • 一个实现DAO接口的具体类; 
    • 数据传递对象(DTO):有些时候叫做值对象(VO)或领域模型(domain)

    这种实现模式就是一个套路,记熟就好了。不过在这之前,如果有不明白的地方,还是要回顾一下之前几篇博文中的知识:PreparedStatement接口重构增删改查、封装JDBC工具类。好了,下面直接上代码。

    三、代码实现

    我们一下面的这张数据表为例:

    新建Java工程文件DaoTest01,最终的工程文件结构如下:

    ffbb2b6e-8d0d-4d4b-9b46-0283ee06a254

    • DBUtils:初步封装的JDBC工具类;
    • db-config.properties:属性文件,方便修改配置信息;
    • Person类就是领域模型,表示是对它(数据库表)进行增删改查。
    • PersonDao接口:专门对Person类进行操作(例如增删改查)的接口。注:这里不直接写操作类,是因为接口利于维护,可以在这里写上公共的代码。一个领域模型对应一个Dao接口。
    • PeronDaoImpl类:实现上面的PeronDao接口

    步骤如下:

    注:第(1)、(2)步操作和上一篇博文是一模一样的,这里只是为了保证本篇文章的完整性,所以重新写一下。

    (1)先新建一个DBUtils工具类:(package com.util.db)

     1 package com.util.db;
     2 
     3 import java.sql.Connection;
     4 import java.sql.DriverManager;
     5 import java.sql.ResultSet;
     6 import java.sql.SQLException;
     7 import java.sql.Statement;
     8 import java.util.ResourceBundle;
     9 
    10 /**
    11  * 数据库操作工具类
    12  * @author lamp
    13  *
    14  */
    15 public class DBUtils {
    16     
    17     //数据库连接地址
    18     public static String URL;
    19     //用户名
    20     public static String USERNAME;
    21     //密码
    22     public static String PASSWORD;
    23     //mysql的驱动类
    24     public static String DRIVER;
    25     
    26     private static ResourceBundle rb = ResourceBundle.getBundle("com.util.db.db-config");
    27     
    28     private DBUtils(){}
    29     
    30     //使用静态块加载驱动程序
    31     static{
    32         URL = rb.getString("jdbc.url");
    33         USERNAME = rb.getString("jdbc.username");
    34         PASSWORD = rb.getString("jdbc.password");
    35         DRIVER = rb.getString("jdbc.driver");
    36         try {
    37             Class.forName(DRIVER);
    38         } catch (ClassNotFoundException e) {
    39             e.printStackTrace();
    40         }
    41     }
    42     //定义一个获取数据库连接的方法
    43     public static Connection getConnection(){
    44         Connection conn = null;
    45         try {
    46             conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
    47         } catch (SQLException e) {
    48             e.printStackTrace();
    49             System.out.println("获取连接失败");
    50         }
    51         return conn;
    52     }
    53     
    54     /**
    55      * 关闭数据库连接
    56      * @param rs
    57      * @param stat
    58      * @param conn
    59      */
    60     public static void close(ResultSet rs,Statement stat,Connection conn){
    61             try {
    62                 if(rs!=null)rs.close();
    63                 if(stat!=null)stat.close();
    64                 if(conn!=null)conn.close();
    65             } catch (SQLException e) {
    66                 e.printStackTrace();
    67             }
    68     }
    69     
    70 }

    注意:26行中,注意获取属性文件的包名是否正确。稍后会定义这个属性文件。

    28行:既然是工具类,一般不要实例化,此时可以采用单例设计模式,或者将构造方法私有化。

    26行:很明显可以看到,我们是将连接数据库的URL、用户名,密码等信息编写在一个属性文件(jdbc.properties)中,稍后再来定义这个属性文件。

    31行:为避免重复代码,使用静态代码块:只会在类加载的时候执行一次。

    42行:定义一个获取数据库连接的方法

    60行:关闭数据库连接

    (2)接下来新建一个属性文件,new-->file,命名为:db-config.properties,代码如下:

    jdbc.url=jdbc:mysql://localhost:3306/jdbcdb
    jdbc.username=root
    jdbc.password=smyh
    jdbc.driver=com.mysql.jdbc.Driver

    以后如果需要修改配置信息,只需要在这里改就行了。注意在上面的DBUtils类中是怎么来调用这个配置信息的。

    紧接着新建文件,定义好Person类:(package com.vae.domain)

     1 package com.vae.domain;
     2 
     3 public class Person {
     4     private int id;
     5     private String name;
     6     private int age;
     7     private String description;
     8     public int getId() {
     9         return id;
    10     }
    11     public void setId(int id) {
    12         this.id = id;
    13     }
    14     public String getName() {
    15         return name;
    16     }
    17     public void setName(String name) {
    18         this.name = name;
    19     }
    20     public int getAge() {
    21         return age;
    22     }
    23     public void setAge(int age) {
    24         this.age = age;
    25     }
    26     public String getDescription() {
    27         return description;
    28     }
    29     public void setDescription(String description) {
    30         this.description = description;
    31     }
    32     public Person(int id, String name, int age, String description) {
    33         super();
    34         this.id = id;
    35         this.name = name;
    36         this.age = age;
    37         this.description = description;
    38     }
    39     public Person(String name, int age, String description) {
    40         super();
    41         this.name = name;
    42         this.age = age;
    43         this.description = description;
    44     }
    45     public Person() {
    46         super();
    47         // TODO Auto-generated constructor stub
    48     }
    49     @Override
    50     public String toString() {
    51         return "Person [id=" + id + ", name=" + name + ", age=" + age
    52                 + ", description=" + description + "]";
    53     }
    54     
    55     
    56 }

    这个Person类就是领域模型,表示是对它进行增删改查。

    (3)定义PersonDao接口:专门对Person类进行操作(例如增删改查)的接口(package com.vae.dao)

    package com.vae.dao;
    
    import java.sql.SQLException;
    import java.util.List;
    
    import com.vae.domain.Person;
    
    public interface PersonDao {
        //添加方法
        public void add(Person p)throws SQLException;
        
        //更新方法
        public void update(Person p)throws SQLException;
        
        //删除方法
        public void delete(int id)throws SQLException;
        
        //查找方法
        public Person findById(int id)throws SQLException;
        
        //查找所有
        public List<Person> findAll()throws SQLException;
        
    } 

    (4)定义PeronDaoImpl实现类 ,实现上面的PeronDao接口(package com.vae.dao.impl)

      1 package com.vae.dao.impl;
      2 
      3 import java.sql.Connection;
      4 import java.sql.PreparedStatement;
      5 import java.sql.ResultSet;
      6 import java.sql.SQLException;
      7 import java.util.ArrayList;
      8 import java.util.List;
      9 
     10 import com.util.db.DBUtils;
     11 import com.vae.dao.PersonDao;
     12 import com.vae.domain.Person;
     13 
     14 /**
     15  * PersonDao的具体实现类
     16  * @author lamp
     17  *
     18  */
     19 public class PersonDaoImpl implements PersonDao{
     20 
     21     /**
     22      * 实现添加方法
     23      */
     24     @Override
     25     public void add(Person p) throws SQLException {
     26         Connection conn = null;
     27         PreparedStatement ps = null;
     28         String sql = "insert into person(name,age,description)values(?,?,?)";
     29         try{
     30             conn = DBUtils.getConnection();
     31             ps = conn.prepareStatement(sql);
     32             ps.setString(1, p.getName());
     33             ps.setInt(2, p.getAge());
     34             ps.setString(3, p.getDescription());
     35             ps.executeUpdate();
     36         }catch(SQLException e){
     37             e.printStackTrace();
     38             throw new SQLException("添加数据失败");
     39         }finally{
     40             DBUtils.close(null, ps, conn);
     41         }
     42     }
     43 
     44     /**
     45      * 更新方法
     46      */
     47     @Override
     48     public void update(Person p) throws SQLException {
     49         Connection conn = null;
     50         PreparedStatement ps = null;
     51         String sql = "update person set name=?,age=?,description=? where id=?";
     52         try{
     53             conn = DBUtils.getConnection();
     54             ps = conn.prepareStatement(sql);
     55             ps.setString(1, p.getName());
     56             ps.setInt(2, p.getAge());
     57             ps.setString(3, p.getDescription());
     58             ps.setInt(4, p.getId());
     59             ps.executeUpdate();
     60         }catch(SQLException e){
     61             e.printStackTrace();
     62             throw new SQLException("更新数据失败");
     63         }finally{
     64             DBUtils.close(null, ps, conn);
     65         }        
     66     }
     67 
     68     /**
     69      * 删除方法
     70      */
     71     @Override
     72     public void delete(int id) throws SQLException {
     73         Connection conn = null;
     74         PreparedStatement ps = null;
     75         String sql = "delete from person where id=?";
     76         try{
     77             conn = DBUtils.getConnection();
     78             ps = conn.prepareStatement(sql);
     79             ps.setInt(1,id);
     80             ps.executeUpdate();
     81         }catch(SQLException e){
     82             e.printStackTrace();
     83             throw new SQLException(" 删除数据失败");
     84         }finally{
     85             DBUtils.close(null, ps, conn);
     86         }        
     87     }
     88 
     89     /**
     90      * 根据ID查询一个对象
     91      */
     92     @Override
     93     public Person findById(int id) throws SQLException {
     94         Connection conn = null;
     95         PreparedStatement ps = null;
     96         ResultSet rs = null;
     97         Person p = null;
     98         String sql = "select name,age,description from person where id=?";
     99         try{
    100             conn = DBUtils.getConnection();
    101             ps = conn.prepareStatement(sql);
    102             ps.setInt(1, id);
    103             rs = ps.executeQuery();
    104             if(rs.next()){
    105                 p = new Person();
    106                 p.setId(id);
    107                 p.setName(rs.getString(1));
    108                 p.setAge(rs.getInt(2));
    109                 p.setDescription(rs.getString(3));
    110             }
    111         }catch(SQLException e){
    112             e.printStackTrace();
    113             throw new SQLException("根据ID查询数据失败");
    114         }finally{
    115             DBUtils.close(rs, ps, conn);
    116         }
    117         return p;
    118     }
    119 
    120     /**
    121      * 查询所有数据
    122      */
    123     @Override
    124     public List<Person> findAll() throws SQLException {
    125         Connection conn = null;
    126         PreparedStatement ps = null;
    127         ResultSet rs = null;
    128         Person p = null;
    129         List<Person> persons = new ArrayList<Person>();
    130         String sql = "select id,name,age,description from person";
    131         try{
    132             conn = DBUtils.getConnection();
    133             ps = conn.prepareStatement(sql);
    134             rs = ps.executeQuery();
    135             while(rs.next()){
    136                 p = new Person();
    137                 p.setId(rs.getInt(1));
    138                 p.setName(rs.getString(2));
    139                 p.setAge(rs.getInt(3));
    140                 p.setDescription(rs.getString(4));
    141                 persons.add(p);
    142             }
    143         }catch(SQLException e){
    144             e.printStackTrace();
    145             throw new SQLException("查询所有数据失败");
    146         }finally{
    147             DBUtils.close(rs, ps, conn);
    148         }
    149         return persons;
    150     }
    151 
    152 }

    我们在各自的增删改查里都抛出了异常,如果出现异常,就会抛出相应的错误信息。

    总结:这样的话,我们就封装好了JDBC的工具类。以后如果要用的话,可以直接在主方法里调用这个类就行了。

    【工程文件】

    链接:http://pan.baidu.com/s/1qW6tew8

    密码:t98s

  • 相关阅读:
    简单区分Vmware的三种网络连接模式(bridged、NAT、host-only)
    linux创建账户并自动生成主目录和主目录下的文件
    EF 通用数据层类
    html在线美化网站
    图片在页面中居中显示
    __dopostback的用法
    rdlc报表集锦
    .NET开源免费的功能强大控件库
    使用webclient上传下载实例
    消息队列将并发变串行
  • 原文地址:https://www.cnblogs.com/qianguyihao/p/4059514.html
Copyright © 2011-2022 走看看