DAO设计模式实现数据库的增删改查(进一步封装JDBC工具类)
DAO设计模式实现数据库的增删改查(进一步封装JDBC工具类)
一、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,最终的工程文件结构如下:
- 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 }
DAO设计模式实现数据库的增删改查(进一步封装JDBC工具类)的更多相关文章
- MySQL数据库学习笔记(十一)----DAO设计模式实现数据库的增删改查(进一步封装JDBC工具类)
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...
- Java操作数据库实现"增删改查"
本文主要讲解JDBC操作数据库 主要实现对MySql数据库的"增删改查" 综合概述: JDBC的常用类和接口 一 DriverManager类 DriverManage类 ...
- MySQL数据库学习笔记(十二)----开源工具DbUtils的使用(数据库的增删改查)
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...
- 开源工具DbUtils的使用(数据库的增删改查)
开源工具DbUtils的使用(数据库的增删改查) 一.DbUtils简介: DBUtils是apache下的一个小巧的JDBC轻量级封装的工具包,其最核心的特性是结果集的封装,可以直接将查询出来的结果 ...
- Android学习---数据库的增删改查(sqlite CRUD)
上一篇文章介绍了sqlite数据库的创建,以及数据的访问,本文将主要介绍数据库的增删改查. 下面直接看代码: MyDBHelper.java(创建数据库,添加一列phone) package com. ...
- Android 系统API实现数据库的增删改查和SQLite3工具的使用
在<Android SQL语句实现数据库的增删改查>中介绍了使用sql语句来实现数据库的增删改查操作,本文介绍Android 系统API实现数据库的增删改查和SQLite3工具的使用. 系 ...
- Android SQL语句实现数据库的增删改查
本文介绍android中的数据库的增删改查 复习sql语法: * 增 insert into info (name,phone) values ('wuyudong','111') * 删 delet ...
- java jdbc 连接mysql数据库 实现增删改查
好久没有写博文了,写个简单的东西热热身,分享给大家. jdbc相信大家都不陌生,只要是个搞java的,最初接触j2ee的时候都是要学习这么个东西的,谁叫程序得和数据库打交道呢!而jdbc就是和数据库打 ...
- 利用API方式进行数据库的增删改查
/* 将数据库的增删改查单独放进一个包 */ package com.itheima28.sqlitedemo.dao; import java.util.ArrayList; import java ...
随机推荐
- MSSQL - 视图操作
查询语句(包含使用Where子句): string sql = @"SELECT TableName, TablePosition,TableSate, TabelType,OpenTime ...
- Join的实现步骤 以及连接的概念
Join的实现步骤 以及连接的概念 我们常说连接有三种,即 交叉连接.内连接.外连接,这三者的概念很容易模糊,现在我们先放下概念,搞清楚完整连接实现的步骤: 一个完整的连接有三个步骤:.做笛卡儿积: ...
- poll调用深入解析
poll调用深入解析http://blog.csdn.net/zmxiangde_88/article/details/8099049 poll调用和select调用实现的功能一样,都是网络IO利用的 ...
- Ch02 从零开始实例学习5
演练:添加模型 原文链接:http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/adding-a-model ...
- QT之深入理解QThread
QT之深入理解QThread 理解QThread之前需要了解下QThread类,QThread拥有的资源如下(摘录于QT 5.1 帮助文档): 在以上资源中,本文重点关注槽:s ...
- Ubuntu 挂载ISO文件的方法
1.在终端中输入:sudo mkdir /media/iso 在/media下生成一个iso文件夹用来挂载iso文件2.然后输入:sudo mount -o loop /home/X/X/XXXX.i ...
- 挺苹果的声音,iPhone 5s的两处进步
苹果iPhone 5s发布后的两处重大进步让我很关注,但看了网上众多网友的点评,又深深的被中国当前手机发烧友圈的这种屌丝文化所震撼,这不是一条正确的道路,这将把中国的手机产业引向歧途,所以我不得不说几 ...
- 收货MIGO
FUNCTION zrfc_mm003. *"---------------------------------------------------------------------- * ...
- Eclipse用法和技巧一:还原视图和编辑器
链接地址:http://blog.csdn.net/maybe_windleave/article/details/8763744 在实际使用eclipse过程中,由于经常关闭或者打开视图,某一刻你会 ...
- [置顶] 应广大童鞋的要求提供一个封装模块,直接和ADB 服务进程交互
很多童鞋在用ADB 的时候都是直接启动ADB 的进程,然后通过管道的方式获取输出,这样多个线程同时使用ADB 的时候任务管理器一闪一闪的,是不是很不爽啊,原先介绍过可以直接和ADB 服务进程通信,不用 ...