MySQL数据库学习笔记 DAO设计模式实现数据库的增删改查

一、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)

package com.util.db;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ResourceBundle;

/**
 * 数据库操作工具类
 * @author lamp
 *
 */
public class DBUtils {
    
    //数据库连接地址
    public static String URL;
    //用户名
    public static String USERNAME;
    //密码
    public static String PASSWORD;
    //mysql的驱动类
    public static String DRIVER;
    
    private static ResourceBundle rb = ResourceBundle.getBundle("com.util.db.db-config");
    
    private DBUtils(){}
    
    //使用静态块加载驱动程序
    static{
        URL = rb.getString("jdbc.url");
        USERNAME = rb.getString("jdbc.username");
        PASSWORD = rb.getString("jdbc.password");
        DRIVER = rb.getString("jdbc.driver");
        try {
            Class.forName(DRIVER);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    //定义一个获取数据库连接的方法
    public static Connection getConnection(){
        Connection conn = null;
        try {
            conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
        } catch (SQLException e) {
            e.printStackTrace();
            System.out.println("获取连接失败");
        }
        return conn;
    }
    
    /**
     * 关闭数据库连接
     * @param rs
     * @param stat
     * @param conn
     */
    public static void close(ResultSet rs,Statement stat,Connection conn){
            try {
                if(rs!=null)rs.close();
                if(stat!=null)stat.close();
                if(conn!=null)conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
    }
    
}

注意: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)

package com.vae.domain;

public class Person {
    private int id;
    private String name;
    private int age;
    private String description;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public Person(int id, String name, int age, String description) {
        super();
        this.id = id;
        this.name = name;
        this.age = age;
        this.description = description;
    }
    public Person(String name, int age, String description) {
        super();
        this.name = name;
        this.age = age;
        this.description = description;
    }
    public Person() {
        super();
        // TODO Auto-generated constructor stub
    }
    @Override
    public String toString() {
        return "Person [id=" + id + ", name=" + name + ", age=" + age
                + ", description=" + description + "]";
    }
    
    
}

这个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)

package com.vae.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.util.db.DBUtils;
import com.vae.dao.PersonDao;
import com.vae.domain.Person;

/**
 * PersonDao的具体实现类
 * @author lamp
 *
 */
public class PersonDaoImpl implements PersonDao{

    /**
     * 实现添加方法
     */
    @Override
    public void add(Person p) throws SQLException {
        Connection conn = null;
        PreparedStatement ps = null;
        String sql = "insert into person(name,age,description)values(?,?,?)";
        try{
            conn = DBUtils.getConnection();
            ps = conn.prepareStatement(sql);
            ps.setString(1, p.getName());
            ps.setInt(2, p.getAge());
            ps.setString(3, p.getDescription());
            ps.executeUpdate();
        }catch(SQLException e){
            e.printStackTrace();
            throw new SQLException("添加数据失败");
        }finally{
            DBUtils.close(null, ps, conn);
        }
    }

    /**
     * 更新方法
     */
    @Override
    public void update(Person p) throws SQLException {
        Connection conn = null;
        PreparedStatement ps = null;
        String sql = "update person set name=?,age=?,description=? where id=?";
        try{
            conn = DBUtils.getConnection();
            ps = conn.prepareStatement(sql);
            ps.setString(1, p.getName());
            ps.setInt(2, p.getAge());
            ps.setString(3, p.getDescription());
            ps.setInt(4, p.getId());
            ps.executeUpdate();
        }catch(SQLException e){
            e.printStackTrace();
            throw new SQLException("更新数据失败");
        }finally{
            DBUtils.close(null, ps, conn);
        }        
    }

    /**
     * 删除方法
     */
    @Override
    public void delete(int id) throws SQLException {
        Connection conn = null;
        PreparedStatement ps = null;
        String sql = "delete from person where id=?";
        try{
            conn = DBUtils.getConnection();
            ps = conn.prepareStatement(sql);
            ps.setInt(1,id);
            ps.executeUpdate();
        }catch(SQLException e){
            e.printStackTrace();
            throw new SQLException(" 删除数据失败");
        }finally{
            DBUtils.close(null, ps, conn);
        }        
    }

    /**
     * 根据ID查询一个对象
     */
    @Override
    public Person findById(int id) throws SQLException {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        Person p = null;
        String sql = "select name,age,description from person where id=?";
        try{
            conn = DBUtils.getConnection();
            ps = conn.prepareStatement(sql);
            ps.setInt(1, id);
            rs = ps.executeQuery();
            if(rs.next()){
                p = new Person();
                p.setId(id);
                p.setName(rs.getString(1));
                p.setAge(rs.getInt(2));
                p.setDescription(rs.getString(3));
            }
        }catch(SQLException e){
            e.printStackTrace();
            throw new SQLException("根据ID查询数据失败");
        }finally{
            DBUtils.close(rs, ps, conn);
        }
        return p;
    }

    /**
     * 查询所有数据
     */
    @Override
    public List<Person> findAll() throws SQLException {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        Person p = null;
        List<Person> persons = new ArrayList<Person>();
        String sql = "select id,name,age,description from person";
        try{
            conn = DBUtils.getConnection();
            ps = conn.prepareStatement(sql);
            rs = ps.executeQuery();
            while(rs.next()){
                p = new Person();
                p.setId(rs.getInt(1));
                p.setName(rs.getString(2));
                p.setAge(rs.getInt(3));
                p.setDescription(rs.getString(4));
                persons.add(p);
            }
        }catch(SQLException e){
            e.printStackTrace();
            throw new SQLException("查询所有数据失败");
        }finally{
            DBUtils.close(rs, ps, conn);
        }
        return persons;
    }

}

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

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

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值