原文地址:http://just-do-myself.iteye.com/blog/655227
DAO(Data Access Objects)設計模式是屬於J2EE體系架構中的數據層的操作。
一、爲什麼要用DAO?
比較在JSP頁面中使用JDBC來連接數據庫,這樣導致了JSP頁面中包含了大量的HTML代碼和JSP代碼,將顯示和功能代碼混在一起,難以維護。並且在JSP頁面中使用JDBC代碼,必須導入相應的"java.sql.*"包。基於使得JSP頁面專注於數據的表現的思想,我們只是希望JSP主要負責數據的顯示,而不需要關注數據的來源和途徑。同時在JSP進行JDBC操作,重複編碼太多。如,不同的頁面連接同一個數據庫時需要在每個頁面中都進行JDBC編碼。
DAO設計模式提供了一種通用的模式,來簡化大量的代碼,增強程序的可移植性。
二、DAO組成
DAO由5個重要部分組成:數據庫連接類、VO、DAO接口、DAO實現類和DAO工廠類。
1、數據庫連接類(DBConn):一個Java類。負責與後臺數據庫進行連接。提供了至少三個方法:
構造方法 public DBConn():進行數據庫連接,得到一個Connection對象。
返回數據庫連接Connection的public Connection getConnection():提供一個外部獲取連接的方法,返回一個Connection對象。
關閉數據庫連接public void close():關閉數據庫連接,Connection對象調用close方法。。
在JDBC中,進行數據庫連接需要四個參數:數據庫驅動類DBDriver、數據庫連接URL、用戶名、密碼。注意需要在項目的構建路徑下放入相應的數據庫連接驅動軟件包。
例:連接MySQL數據庫下的JavaWeb數據庫,用戶名爲root、密碼爲admin。
DataBaseConnection.java
- package db;
- import java.sql.* ;
- // 主要功能就是連接數據庫、關閉數據庫
- public class DataBaseConnection{
- //定義數據庫驅動類
- private final String DBDRIVER = "com.mysql.jdbc.Driver" ;
- //定義數據庫連接URL
- private final String DBURL = "jdbc:mysql://localhost:3306/javaweb" ;
- //定義數據庫連接用戶名
- private final String DBUSER = "root" ;
- //定義數據庫連接密碼
- private final String DBPASSWORD = "admin" ;
- //定義數據庫連接對象
- private Connection conn = null ;
- //構造方法,加載驅動
- public DataBaseConnection(){
- try{
- Class.forName(DBDRIVER) ;
- this.conn = DriverManager.getConnection(DBURL,DBUSER,DBPASSWORD) ;
- }
- catch (Exception e){
- System.out.println("加載驅動失敗");
- }
- }
- // 取得數據庫連接
- public Connection getConnection(){
- return conn ;
- }
- // 關閉數據庫連接
- public void close(){
- try{
- conn.close() ;
- }catch (Exception e){
- System.out.println("數據庫連接關閉失敗");
- }
- }
- }
同樣,需要在項目的構建路徑下放入Mysql的JDBC數據庫驅動包:mysql-connector-java.jar.在附件中已上傳了相應Jar包。
2、VO(Value Objects)值對象:與數據庫表一一對應的Java類。含有與數據庫表字段一一對應的屬性,相應屬性的getter和setter方法。甚至還有一些驗證方法。VO提供了一個面向對象的方法來操作數據庫。以後我們的DAO接口就是通過調用VO來進行數據庫操作的。
例:對應於數據庫表T_User:三個字段,id、username、password。相應的VO類
User.java
- package db;
- public class User {
- //用戶id
- private int userid;
- //用戶姓名
- private String username;
- //用戶密碼
- private String password;
- //獲得用戶id
- public int getUserid(){
- return userid;
- }
- //設置用戶id
- public void setUserid(int userid){
- this.userid = userid;
- }
- //獲得用戶名
- public String getUsername() {
- return username;
- }
- //設置用戶名
- public void setUsername(String username) {
- this.username = username;
- }
- //獲得用戶密碼
- public String getPassword() {
- return password;
- }
- //設置用戶密碼
- public void setPassword(String password) {
- this.password = password;
- }
- }
3、DAO接口:定義了所有的用戶的操作,如添加記錄、刪除記錄和查詢記錄等。這不是一個具體的實現類,而是一個接口,僅僅定義了相應的操作(方法),這是給後來的具體實現提供一種靈活性和易維護性。具體的實現需要具體實現類實現這個接口的方法來實現。
例:對上面的T_User表進行CRUD操作。
UserDAO.java
- package db ;
- import java.util.* ;
- // 定義數據庫操作方法
- public interface UserDAO{
- // 增加操作
- public void insert(User user) throws Exception ;
- // 修改操作
- public void update(User user) throws Exception ;
- // 刪除操作
- public void delete(int userid) throws Exception ;
- // 按ID查詢操作
- public User queryById(int userid) throws Exception ;
- // 查詢全部
- public List queryAll() throws Exception ;
- }
4、DAO實現類:這裏纔是具體的操作的實現。需要實現DAO接口以及相應的方法。
同樣,一個DAO接口可以由多個實現。例如,上例中的可以有Mysql數據庫來實現,也可以使用oracle數據庫來實現。
同理,也可以是對同一數據庫的不同實現。
例:DAO的Mysql實現。
UserDAOImpl.java
- package db;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.util.ArrayList;
- import java.util.List;
- import com.javaweb.ch08.Person;
- public class UserDAOImpl implements UserDAO {
- //添加操作
- public void insert(User user) throws Exception {
- String sql = "INSERT INTO user(username,password) VALUES(?,?)" ;
- PreparedStatement pstmt = null ;
- DataBaseConnection dbc = null ;
- // 下面是針對數據庫的具體操作
- try{
- // 連接數據庫
- dbc = new DataBaseConnection() ;
- pstmt = dbc.getConnection().prepareStatement(sql) ;
- pstmt.setString(1, user.getUsername());
- pstmt.setString(2, user.getPassword());
- // 進行數據庫更新操作
- pstmt.executeUpdate() ;
- pstmt.close() ;
- }catch (Exception e){
- throw new Exception("操作出現異常") ;
- }
- finally{
- // 關閉數據庫連接
- dbc.close() ;
- }
- }
- //修改操作
- public void update(User user) throws Exception {
- String sql = "UPDATE user SET username=?,password=? WHERE userid=?" ;
- PreparedStatement pstmt = null ;
- DataBaseConnection dbc = null ;
- // 下面是針對數據庫的具體操作
- try{
- // 連接數據庫
- dbc = new DataBaseConnection() ;
- pstmt = dbc.getConnection().prepareStatement(sql) ;
- pstmt.setString(1, user.getUsername());
- pstmt.setString(2, user.getPassword());
- pstmt.setInt(3,user.getUserid());
- // 進行數據庫更新操作
- pstmt.executeUpdate() ;
- pstmt.close() ;
- }
- catch (Exception e){
- throw new Exception("操作出現異常") ;
- }
- finally{
- // 關閉數據庫連接
- dbc.close() ;
- }
- }
- //刪除操作
- public void delete(int userid) throws Exception {
- String sql = "DELETE FROM user WHERE userid=?" ;
- PreparedStatement pstmt = null ;
- DataBaseConnection dbc = null ;
- // 下面是針對數據庫的具體操作
- try{
- // 連接數據庫
- dbc = new DataBaseConnection() ;
- pstmt = dbc.getConnection().prepareStatement(sql) ;
- pstmt.setInt(1,userid) ;
- // 進行數據庫更新操作
- pstmt.executeUpdate() ;
- pstmt.close() ;
- }catch (Exception e){
- throw new Exception("操作出現異常") ;
- }
- finally{
- // 關閉數據庫連接
- dbc.close() ;
- }
- }
- //按ID查詢
- public User queryById(int userid) throws Exception {
- User user = null ;
- String sql = "SELECT * FROM user WHERE userid=?" ;
- PreparedStatement pstmt = null ;
- DataBaseConnection dbc = null ;
- // 下面是針對數據庫的具體操作
- try{
- // 連接數據庫
- dbc = new DataBaseConnection() ;
- pstmt = dbc.getConnection().prepareStatement(sql) ;
- pstmt.setInt(1, userid);
- // 進行數據庫查詢操作
- ResultSet rs = pstmt.executeQuery() ;
- if(rs.next())
- {
- // 查詢出內容,之後將查詢出的內容賦值給user對象
- user = new User() ;
- user.setUserid(rs.getInt(1));
- user.setUsername(rs.getString(2));
- user.setPassword(rs.getString(3));
- }
- rs.close() ;
- pstmt.close() ;
- }catch (Exception e){
- throw new Exception("操作出現異常") ;
- }
- finally{
- // 關閉數據庫連接
- dbc.close() ;
- }
- return user ;
- }
- public List<User> queryAll() throws Exception {
- List<User> all = new ArrayList<User>() ;
- String sql = "SELECT * FROM user " ;
- PreparedStatement pstmt = null ;
- DataBaseConnection dbc = null ;
- // 下面是針對數據庫的具體操作
- try{
- // 連接數據庫
- dbc = new DataBaseConnection() ;
- pstmt = dbc.getConnection().prepareStatement(sql) ;
- // 進行數據庫查詢操作
- ResultSet rs = pstmt.executeQuery() ;
- while(rs.next()){
- // 查詢出內容,之後將查詢出的內容賦值給user對象
- User user = new User() ;
- user.setUserid(rs.getInt(1));
- user.setUsername(rs.getString(2));
- user.setPassword(rs.getString(3));
- // 將查詢出來的數據加入到List對象之中
- all.add(user) ;
- }
- rs.close() ;
- pstmt.close() ;
- }
- catch (Exception e){
- throw new Exception("操作出現異常") ;
- }
- finally{
- // 關閉數據庫連接
- dbc.close() ;
- }
- return all ;
- }
- }
5、DAO工廠類:在沒有DAO工廠類的情況下,必須通過創建DAO實現類的實例才能完成數據庫的操作。這時要求必須知道具體的實現子類,對於後期的修改十分不便。如後期需要創建一個該DAO接口的Oracle實現類。這時就必須修改所有使用DAO實現類的代碼。如果使用DAO工廠類的一個靜態方法(不需要創建對象即可調用)來獲取DAO實現類實例,這時替換DAO實現類,只需修改DAO工廠類中的方法代碼,而不需要修改所有的調用DAO實現的代碼。
DAO工廠類是一個單例模式,這樣避免的數據庫的不一致。
例:通過DAO工廠類來獲取具體的DAO實現類。
DAOFactory.java
- package db;
- public class DAOFactory{
- public static UserDAO getUserDAOInstance(){
- return new UserDAOImpl() ;
- }
- }
這裏若改變爲Oracle實現類UserDAOOracleImpl來實現DAO,只需在DAOFactory中修改
- package db;
- public class DAOFactory{
- public static UserDAO getUserDAOInstance(){
- <span style="background-color: #ff0000;">return new UserDAOOracleImpl()</span> ;
- }
- }
有了上面五個部分,就可以通過DAO工廠類獲取DAO實現類實例。通過調用DAO實現類實例中的方法就可以完成相應的數據庫的CRUD操作。
三、表示層調用通過DAO工廠類獲取DAO實現類實例的方法完成相應的操作。
1、添加記錄:AddUserDemo.jsp
- <%@ page language="java" contentType="text/html;charset=gb2312"%>
- <%@ page import="db.*"%>
- <html>
- <head>
- <title>添加用戶記錄</title>
- </head>
- <body>
- <%
- //通過DAO工廠獲得DAO實現類實例
- UserDAO userDAO = DAOFactory.getUserDAOInstance();
- //設置需要添加的用戶
- User user = new User();
- user.setUsername("dao");
- user.setPassword("123");
- userDAO.insert(user);
- %>
- </body>
- </html>
2、更新記錄:UpdateUserDemo.jsp
- <%@ page language="java" contentType="text/html;charset=gb2312"%>
- <%@ page import="db.*"%>
- <html>
- <head>
- <title>更新用戶記錄</title>
- </head>
- <body>
- <%
- //通過DAO工廠獲得DAO實現類實例
- UserDAO userDAO = DAOFactory.getUserDAOInstance();
- //設置需要更新的用戶
- User user = new User();
- user.setUserid(10);
- user.setUsername("dao");
- user.setPassword("123456");
- //執行更新操作
- userDAO.update(user);
- %>
- </body>
- </html>
3、刪除記錄:DeleteUserDemo.jsp
- <%@ page language="java" contentType="text/html;charset=gb2312"%>
- <%@ page import="db.*"%>
- <html>
- <head>
- <title>刪除用戶記錄</title>
- </head>
- <body>
- <%
- //通過DAO工廠獲得DAO實現類實例
- UserDAO userDAO = DAOFactory.getUserDAOInstance();
- //執行刪除操作
- userDAO.delete(10);
- %>
- </body>
- </html>
4、按ID查詢記錄:QueryByIdDemo.jsp
- <%@ page language="java" contentType="text/html;charset=gb2312"%>
- <%@ page import="db.*"%>
- <html>
- <head>
- <title>按ID查詢記錄</title>
- </head>
- <body>
- <%
- //通過DAO工廠獲得DAO實現類實例
- UserDAO userDAO = DAOFactory.getUserDAOInstance();
- //指定按ID查詢
- User user = userDAO.queryById(2);
- out.println("用戶名:" + user.getUsername() + "<br>");
- out.println("密碼:" + user.getPassword());
- %>
- </body>
- </html>
5、查詢所有記錄:QueryAllUserDemo.jsp
- <%@ page language="java" contentType="text/html;charset=gb2312"%>
- <%@ page import="db.*"%>
- <%@ page import="java.util.*"%>
- <html>
- <head>
- <title>查詢所有記錄</title>
- </head>
- <body>
- <%
- //通過DAO工廠獲得DAO實現類實例
- UserDAO userDAO = DAOFactory.getUserDAOInstance();
- //查詢所有用戶
- List<User> all = userDAO.queryAll();
- Iterator<User> iter = all.iterator();
- //遍歷輸出所有用戶信息
- while(iter.hasNext()) {
- User user = iter.next();
- out.println("用戶名:" + user.getUsername());
- out.println(",密碼:" + user.getPassword() + "<br>");
- }
- %>
- </body>
- </html>