首页 > 代码库 > MySQL数据库学习笔记(十一)----DAO设计模式实现数据库的增删改查(进一步封装JDBC工具类)
MySQL数据库学习笔记(十一)----DAO设计模式实现数据库的增删改查(进一步封装JDBC工具类)
【声明】
欢迎转载,但请保留文章原始出处→_→
生命壹号:http://www.cnblogs.com/smyhvae/
文章来源:http://www.cnblogs.com/smyhvae/p/4059514.html
联系方式:smyhvae@163.com
【正文】
一、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 lamp13 *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 rs57 * @param stat58 * @param conn59 */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/jdbcdbjdbc.username=rootjdbc.password=smyhjdbc.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 stub48 }49 @Override50 public String toString() {51 return "Person [id=" + id + ", name=" + name + ", age=" + age52 + ", 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 @Override124 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
MySQL数据库学习笔记(十一)----DAO设计模式实现数据库的增删改查(进一步封装JDBC工具类)