Dao设计模式简单实现

一、什么是Dao设计模式

  Dao设计模式封装了操作具体数据库的细节,对业务层提供操作数据库的接口,因此降低了业务层代码与具体数据库之间的耦合,有利于人员分工,增加了程序的可移植性。

  Dao设计模式中主要包含这5个模块:

    1、VO类:VO(Value Object)即值对象,每一个值对象对应一张数据库表,便于我们传递数据。

    2、Dao接口:Dao接口定义了操作数据库的方法,业务层通过调用这些方法来操作数据库。

    3、Dao实现类:操作数据库的方法的具体实现,封装了操作数据库的细节。

    4、Dao工厂类:用于代替new操作,进一步降低业务层与数据层之间的耦合。

    5、数据库连接类:封装了连接数据库、关闭数据库等常用的操作,减少重复编码。

  下面我们应用Dao设计模式来实现一个简单的转账操作,加深对其的理解。

二、Dao设计模式实现

  首先,我们创建vo、dao、factory、util包来分别存放Dao设计模式5个模块的代码。因为我们使用的是JDBC连接MySQL数据库,所以还需要创建一个lib包存放并引用JDBC驱动。除此之外,我们还需要创建一个test包进行代码的测试。创建好后的目录结构如下:

  接着设计一张user表,表中包含了用户基本信息和余额,并插入一些数据。

  根据user表在vo包中创建VO类user.java。

 1 package vo;
 2 
 3 public class User {
 4 
 5     private int id;
 6     
 7     private String username;
 8     
 9     private int sum;
10 
11     public int getId() {
12         return id;
13     }
14 
15     public void setId(int id) {
16         this.id = id;
17     }
18 
19     public String getUsername() {
20         return username;
21     }
22 
23     public void setUsername(String username) {
24         this.username = username;
25     }
26 
27     public int getSum() {
28         return sum;
29     }
30 
31     public void setSum(int sum) {
32         this.sum = sum;
33     }
34 
35     @Override
36     public String toString() {
37         return "User [id=" + id + ", username=" + username + ", sum=" + sum + "]";
38     }
39     
40 }

  在util包中创建数据库连接类JDBC.java。

 1 package util;
 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 
 9 public class JDBC {
10     //获取数据库链接
11     public static Connection getConnection() {
12         Connection con = null;
13         try {
14             String url = "jdbc:mysql://localhost:3306/user?serverTimezone=Asia/Shanghai";
15             Class.forName("com.mysql.cj.jdbc.Driver");
16             con = DriverManager.getConnection(url, "root", "root");
17         } catch (Exception e) {
18             e.printStackTrace();
19         }
20         return con;
21     }
22     //关闭资源
23     public static void close(Connection con, Statement st, ResultSet rs) {
24         try {
25             if (rs != null) {
26                 rs.close();
27             }
28             if (st != null) {
29                 st.close();
30             }
31             if (con != null) {
32                 con.close();
33             }
34         } catch (SQLException e) {
35             e.printStackTrace();
36         }
37     }
38 }

  经过分析,该转账系统需要两类数据库操作,分别是“查询用户信息”和“更新用户余额”。因此我们在dao包中创建IUserDao.java接口并定义这两种方法。

 1 package dao;
 2 
 3 import java.sql.Connection;
 4 import java.sql.SQLException;
 5 
 6 import vo.User;
 7 
 8 public interface IUserDao {
 9     //根据用户名查找用户信息
10     public User selectUserByName(Connection con, User user);
11     //根据用户名更新用户余额
12     public int updateSumByName(Connection con, User user) throws SQLException;
13 }

  接着在dao包中创建该接口的实现类UserDaoImpl.java,实现这两种方法。

 1 package dao;
 2 
 3 import java.sql.Connection;
 4 import java.sql.PreparedStatement;
 5 import java.sql.ResultSet;
 6 import java.sql.SQLException;
 7 
 8 import util.JDBC;
 9 import vo.User;
10 
11 public class UserDaoImpl implements IUserDao {
12 
13     @Override
14     public User selectUserByName(Connection con, User user) {
15         String sql = "select * from user where username = ?";
16         PreparedStatement pStatement = null;
17         ResultSet rs = null;
18         try {
19             pStatement = con.prepareStatement(sql);
20             pStatement.setString(1, user.getUsername());
21             rs = pStatement.executeQuery();
22             if (rs.next()) {
23                 user.setId(rs.getInt("id"));
24                 user.setUsername(rs.getString("username"));
25                 user.setSum(rs.getInt("sum"));
26                 return user;
27             }
28         } catch (SQLException e) {
29             e.printStackTrace();
30         }finally {
31             JDBC.close(null, pStatement, rs);
32         }
33         return null;
34     }
35 
36     @Override
37     public int updateSumByName(Connection con, User user) throws SQLException {
38         String sql = "update user set sum = ? where username = ?";
39         PreparedStatement pStatement = null;
40         try {
41             pStatement = con.prepareStatement(sql);
42             pStatement.setInt(1, user.getSum());
43             pStatement.setString(2, user.getUsername());
44             return pStatement.executeUpdate();
45         } catch (SQLException e) {
46             e.printStackTrace();
47             //抛出异常,便于进行事务处理
48             throw e;
49         }finally {
50             JDBC.close(null, pStatement, null);
51         }
52     }
53 }

  最后,我们还需要在factory包中创建Dao工厂类DaoFactory.java。

 1 package factory;
 2 
 3 import dao.IUserDao;
 4 import dao.UserDaoImpl;
 5 
 6 public class DaoFactory {
 7     public static IUserDao getUserDao() {
 8         return new UserDaoImpl();
 9     }
10 }

  到这里,转账系统的Dao层就设计好了。我们在test包中创建Main.java进行测试。

 1 package test;
 2 
 3 import java.sql.Connection;
 4 import java.sql.SQLException;
 5 
 6 import dao.IUserDao;
 7 import factory.DaoFactory;
 8 import util.JDBC;
 9 import vo.User;
10 
11 public class Main {
12 
13     public static void main(String[] args) {
14         Connection con = JDBC.getConnection();
15         IUserDao userDao = DaoFactory.getUserDao();
16         //被转账的用户
17         User user_in = new User();
18         user_in.setUsername("ysy");
19         user_in = userDao.selectUserByName(con, user_in);
20         System.out.println(user_in);
21         //转账的用户
22         User user_out = new User();
23         user_out.setUsername("管理员");
24         user_out = userDao.selectUserByName(con, user_out);
25         System.out.println(user_out);
26         //转账30元
27         user_in.setSum(user_in.getSum() + 30);
28         user_out.setSum(user_out.getSum() - 30);
29         //事务处理
30         try {
31             con.setAutoCommit(false);
32             userDao.updateSumByName(con, user_in);
33             userDao.updateSumByName(con, user_out);
34             con.commit();
35         } catch (Exception e) {
36             e.printStackTrace();
37             try {
38                 con.rollback();
39             } catch (SQLException e1) {
40                 e1.printStackTrace();
41             }
42         }
43         //查询转账结果
44         user_in = userDao.selectUserByName(con, user_in);
45         System.out.println(user_in);
46         user_out = userDao.selectUserByName(con, user_out);
47         System.out.println(user_out);
48         JDBC.close(con, null, null);
49     }
50 }

  执行结果如下:

  最终的目录结构如下:

posted @ 2019-11-27 12:25  牛cattle  阅读(1011)  评论(0编辑  收藏  举报