精华内容
下载资源
问答
  • DAO设计模式

    2012-04-11 19:31:23
    javaDAO设计模式,主要功能就是进行数据操作,在程序标准开发架构中属于数据层操作
  • DAO设计模式的介绍与实现

    千次阅读 多人点赞 2017-11-10 18:18:21
    看一下官方的介绍,DAO(Data Access Object,数据访问对象)的主要功能是数据操作,在程序的标准开发架构中属于数据层的操作。额,好像有点糊涂啊,用人类的语言解释一下也就是DAO是一种操作数据库的设计

    前言:哈哈,第一篇关于Java的博客了,暑假看了一些Java的设计模式,本来想着总结一下的,但是一耽误就到现在了,后面慢慢补上。今天我们来聊聊DAO

    1、DAO是个什么东西呢?

    看一下官方的介绍,DAO(Data Access Object,数据访问对象)的主要功能是数据操作,在程序的标准开发架构中属于数据层的操作。额,好像有点糊涂啊,用人类的语言解释一下也就是DAO是一种操作数据库的设计模式,也就是我们通过DAO这种设计模式,对于数据库的操作更加的方便管理,可扩展性更加的好。说到这里,可能也不是很明白,你把下面的代码都敲一遍,自然就明白了。

    2、DAO的组成

    上面说了DAO是什么东西,现在就来说说DAO的组成。有些地方说DAO是由五部分组成,有些地方说是由六部分组成。
    五部分的说法是

    数据库连接类: 连接数据库
    VO实体类: JavaBean,里面一堆的setter和getter
    DAO接口:  接口还能干啥,不就是让别人来实现吗,进行规范化管理。老板(接口)说了让你写报告,你要是不写就开除(报错)
    DAO实现类: 员工写报告的的具体过程(打开电脑,***,关闭电脑,汇报)
    DAO工厂类: 工厂不就是为了方便调用吗,要什么给什么。

    六部分的说法是

    数据库连接类: 连接数据库
    VO实体类: JavaBean,里面一堆的setter和getter
    DAO接口:  接口还能干啥,不就是让别人来实现吗,进行规范化管理。老板(接口)说了让你写报告,你要是不写就开除(报错)
    DAO实现真正类: 员工自己不写,嘿嘿,去找小明帮他写,所以小明成为了真正的实现类
    DAO的代理实现类: 员工这时候就是代理实现类
    DAO工厂类: 工厂不就是为了方便调用吗,要什么给什么。

    其实关于上面的两种组成部分,我还是比较赞同六部分组成的,因为这样更加的清晰化,数据和逻辑得到更进一步的分离,所以我下面就采用六部分来实现一个小例子。

    3、通过图书的增删改查来看看这个神秘的玩意儿

    1、创建数据库(自己使用的是MySQL),咱们就随便找几个字段意思一下,比较重点不在这里

    create table books(
        bookid int auto_increment primary key,
        bookName varchar(50) not null,
        bookNumber int not null default 0,
        pubdate datetime not null,
        UNIQUE INDEX unique_id(bookid)
    )

    2、编写数据库的连接类
    在编写数据库的连接类之前,我们可以想一想,我们这里采用的是MySQL数据库,如果其他地方使用Oracle或者SQL Server,那么我们的数据库连接类就需要进行修改,在Java中有一个设计模式的理念就是我们尽量不要进行代码的修改,通过增加代码来实现我们想要的功能(我忘记这个设计模式叫什么名字了,手动【尴尬】),因此我们通过让连接类实现一个接口的方式来连接数据库。我们建立一个DB包,在包中建立一个DatabaseConnection接口和一个MySQLConnection类
    DatabaseConnection的代码如下

    package DB;
    
    import java.sql.Connection;
    public interface DatabaseConnection {
        //  取得数据库的连接
        public Connection getConnection();
        //  关闭数据库的连接
        public void close();
    }



    MySQLConnection的代码如下

    package DB;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    
    public class MySQLConnection implements DatabaseConnection{
        //数据库连接驱动
        private static final String DBDRIVER = "com.mysql.jdbc.Driver";
        //数据库连接地址,我这里直接将数据库名字web放在后面了
        private static final String DBULR = "jdbc:mysql://localhost:3306/web";
        // 数据库用户名   
        private static final String USERNAME = "root";
        // 数据库密码    
        private static final String PASSWORD = "root";
        private Connection conn;
        // 取得数据库连接
        public Connection getConnection() throws Exception{
            try {
                // 加载驱动程序
                Class.forName(DBDRIVER);
                // 取得数据库连接,获得资源句柄
                this.conn = DriverManager.getConnection(DBULR,USERNAME,PASSWORD);
            }catch(Exception e) {
                throw e;
            }
            return this.conn;
        }
        // 关闭数据库连接  
        public void close() throws Exception{
            if(this.conn != null) {
                try{
                    this.conn.close();
                }catch(Exception e) {
                    throw e;
                }
            }
        }
    }

    3、数据库连接类写好了,咱们来写一下VO类吧,我们建一个VO的包,在里面建立一下Book类
    book类的代码如下

    package VO;
    
    import java.util.Date;
    
    public class Book {
        private int bookid;
        private String bookName;
        private int bookNumber;
        private Date pubdate;
        public int getBookid() {
            return bookid;
        }
        public void setBookid(int bookid) {
            this.bookid = bookid;
        }
        public String getBookName() {
            return bookName;
        }
        public void setBookName(String bookName) {
            this.bookName = bookName;
        }
        public int getBookNumber() {
            return bookNumber;
        }
        public void setBookNumber(int bookNumber) {
            this.bookNumber = bookNumber;
        }
        public Date getPubdate() {
            return pubdate;
        }
        public void setPubdate(Date pubdate) {
            this.pubdate = pubdate;
        }
    }

    4、接下来就是DAO接口类了,上面已经说过了,这就是老板安排的任务的汇总(进行数据库操作的所有方法)。因为我们要对图书进行增删改查,所以我们需要findById方法(查找),findAll(显示全部书籍),doUpdate(修改书籍),doDelete(删除书籍),doCreate(新增书籍)。我们建立一个DAO包,在这里面建立一个bookDAO的接口
    bookDAO的代码如下

    package DAO;
    
    import java.sql.SQLException;
    import java.util.List;
    
    import VO.Book;
    
    public interface BookDAO {
        //  查找某一本书籍
        public Book findById(int bookid) throws Exception;
        // 显示所有书籍
        public List<Book> findAll() throws Exception;
        // 修改书籍信息
        public boolean doUpdate(Book book) throws Exception;
        // 删除书籍信息
        public boolean doDelete(Book book) throws Exception;
        // 新增书籍信息
        public boolean doCreate(Book book) throws Exception;
    }
    

    5、接下来我们就是进行方法的具体实现,如果拆分成五部分的话,在这里就直接把方法实现了,但是因为我将其拆分成了六部分,所以我就先写真正的实现类,再写代理实现类。我们在DAO下面建立一个BookDAOImpl的类
    BookDAOImpl的代码如下(代码相对比较多,但是逻辑比较简单)

    package DAO;
    
    import java.sql.Connection;
    import java.sql.Date;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.List;
    import VO.Book;
    
    public class BookDAOImpl implements BookDAO {
        private Connection conn;
        // 这里采用PreparedStatement进行预处理,主要是为了方式SQL注入
        // 关于网络安全,可以看我GitHub上面的一个文章
        // https://github.com/deng1234/webSecurity
        private PreparedStatement pstmt;
        // 在代理实现类中进行对象实例化的时候获得连接数据库的资源句柄    
        public BookDAOImpl(Connection conn) {
            this.conn = conn;
        }
        @Override
        // 根据id查找   
        public Book findById(int bookid) throws SQLException{
            Book book = new Book();
            String sql = "SELECT bookid, bookName, bookNumber, pubdate FROM books WHERE bookid = ?";
            try {
                this.pstmt = this.conn.prepareStatement(sql);
                this.pstmt.setInt(1, bookid);
                ResultSet rs = (ResultSet) this.pstmt.executeQuery();
                if(rs.next()) {
                    book.setBookid(rs.getInt(1));
                    book.setBookName(rs.getString(2));
                    book.setBookNumber(rs.getInt(3));
                    book.setPubdate(rs.getDate(4));
                }
            } catch (SQLException e) {
                throw e;
            }
            this.pstmt.close();
            return book;
        }
    
        @Override
        // 列出所有书籍
        public List<Book> findAll() throws SQLException {
            List<Book> books = new ArrayList<Book>();
            Book book;
            String sql = "SELECT bookid, bookName, bookNumber, pubdate FROM books";
            try {
                this.pstmt = this.conn.prepareStatement(sql);
                ResultSet rs = (ResultSet) this.pstmt.executeQuery();
                while(rs.next()) {
                    book = new Book();
                    book.setBookid(rs.getInt(1));
                    book.setBookName(rs.getString(2));
                    book.setBookNumber(rs.getInt(3));
                    book.setPubdate(rs.getDate(4));
                    books.add(book);
                }
            } catch (SQLException e) {
                throw e;
            }
            this.pstmt.close();
            return books;
        }
    
        @Override
        // 修改书籍信息
        public boolean doUpdate(Book book) throws SQLException {
            boolean flag = false;
            String sql = "UPDATE books SET bookName = ?, bookNumber = ?, pubdate = ? WHERE bookid = ?";
            try {
                this.pstmt = this.conn.prepareStatement(sql);
                this.pstmt.setString(1, book.getBookName());
                this.pstmt.setInt(2, book.getBookNumber());
                this.pstmt.setDate(3, new java.sql.Date(book.getPubdate().getTime()));
                this.pstmt.setInt(4, book.getBookid());
                if(this.pstmt.executeUpdate() > 0) {
                    flag = true;
                }
            } catch (SQLException e) {
                throw e;
            }
            this.pstmt.close();
            return flag;
        }
    
        @Override
        // 删除书籍信息
        public boolean doDelete(Book book) throws SQLException {
            boolean flag = false;
            String sql = "DELETE FROM books WHERE bookid = ?";
            try {
                this.pstmt = this.conn.prepareStatement(sql);
                this.pstmt.setInt(1, book.getBookid());
                if(this.pstmt.executeUpdate() > 0) {
                    flag = true;
                }
            } catch (SQLException e) {
                throw e;
            }
            this.pstmt.close();
            return flag;
        }
    
        @Override
        // 新增书籍
        public boolean doCreate(Book book) throws SQLException {
            boolean flag = false;
            String sql = "INSERT INTO books (bookName, bookNumber, pubdate) "
                    + "values(?, ?, ?)";
            try {
                this.pstmt = this.conn.prepareStatement(sql);
                this.pstmt.setString(1, book.getBookName());
                this.pstmt.setInt(2, book.getBookNumber());
                this.pstmt.setDate(3, new java.sql.Date(book.getPubdate().getTime()));
                if(this.pstmt.executeUpdate() > 0) {
                    flag = true;
                }
            } catch (SQLException e) {
                throw e;
            }
            this.pstmt.close();
            return flag;
        }
    
    }

    6、咱们接下来就写DAO的代理实现类,在DAO的包下面建立一个BookDAOProxy类,因为不管是代理,还是真正去实现的,接口中(老板)的方法都是需要去做的,所以我们在这里面都需要实现BookDAO接口
    BookDAOProxy类的代码为

    package DAO;
    
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.List;
    
    import DB.MySQLConnection;
    import VO.Book;
    
    public class BookDAOProxy implements BookDAO{
        private MySQLConnection conn = null;
        private BookDAO dao;
        public BookDAOProxy() throws Exception {
            this.conn = new MySQLConnection();
            // 在这里对真正的DAO实现内进行实例化       
            this.dao = new BookDAOImpl(this.conn.getConnection());
        }
    
        @Override
        // 书籍查找
        public Book findById(int bookid) throws Exception {
            Book book = new Book();
            try {
                book = this.dao.findById(bookid);
            }catch(SQLException e) {
                throw e;
            }finally {
                // 关闭数据库
                this.conn.close();
            }
            return book;
        }
    
        @Override
        // 列出所有书籍
        public List<Book> findAll() throws Exception {
            List<Book> books = new ArrayList<Book>();
            try {
                books = this.dao.findAll();
            }catch(Exception e) {
                throw e;
            }finally {
                this.conn.close();
            }
            return books;
        }
    
        @Override
        public boolean doUpdate(Book book) throws Exception {
            boolean flag = false;
            try {
                if(this.dao.findById(book.getBookid()) != null) {
                    flag = this.dao.doUpdate(book);
                }
            }catch(Exception e) {
                throw e;
            }finally {
                this.conn.close();
            }
            return flag;
        }
    
        @Override
        public boolean doDelete(Book book) throws Exception {
            boolean flag = false;
            try {
                flag = this.dao.doDelete(book);
            }catch(Exception e) {
                throw e;
            }finally {
                this.conn.close();
            }
            return flag;
        }
    
        @Override
        public boolean doCreate(Book book) throws Exception {
            boolean flag = false;
            try {
                flag = this.dao.doCreate(book);
            }catch(Exception e) {
                throw e;
            }finally {
                this.conn.close();
            }
            return flag;
        }
    
    }
    
    

    7、挺住,我们马上就迎来最后一部分啦,建立一个工厂类。为什么进行工厂类呢,如果不进行工厂化处理的时候,我们调用方法需要对BookDAOProxy进行对象实例化,然后再调用其中的方法,不管在哪里调用,都需要进行对象实例化。如果有一天我们需要修改代理类,哈哈,你就需要去每一个地方修改(^__^),虽然修改的可能性不大哈。但是如果我们进行工厂类的封装,调用直接通过工厂类取得其实例化,并且如果要要换一个代理类,直接修改即可。我们建立一个FACTORY的包,然后在下面建立一个DAOFactoty的类
    DAOFactory的代码为

    package FACTORY;
    
    import DAO.BookDAO;
    import DAO.BookDAOProxy;
    
    public class DAOFactory {
        public static BookDAO getBookDAOInstance() throws Exception {
            return new BookDAOProxy();
        }
    }
    

    4、折腾了半天,我们总得测试一下,看看写的正确吧

    我们建立一个Test包,在里面建立一个doCreate的类测试数据插入,doUpdate测试数据修改,doDelete测试数据删除,findAll数据显示,finById数据查找 。
    数据插入方法测试的测试

    package Test;
    
    import FACTORY.DAOFactory;
    import VO.Book;
    
    public class doCreate {
        public static void main(String args[]) throws Exception {
            Book book = new Book();
            try {
                book.setBookName("Java特种兵");
                book.setBookNumber(1);
                book.setPubdate(new java.util.Date());
                boolean flag = DAOFactory.getBookDAOInstance().doCreate(book);
                System.out.println(flag);//true则是成功,false则是失败
            }catch(Exception e) {
                System.out.println(e);
            }
        }
    }
    



    数据查找方法测试代码

    package Test;
    
    import FACTORY.DAOFactory;
    import VO.Book;
    
    public class finById {
        public static void main(String args[]) throws Exception {
            Book book = new Book();
            try {
                book = DAOFactory.getBookDAOInstance().findById(1);
                System.out.println(book.getBookName()+"--"+book.getBookNumber()+"--"+book.getPubdate());
            }catch(Exception e) {
                System.out.println(e);
            }
        }
    }
    



    数据修改方法测试代码

    package Test;
    
    import FACTORY.DAOFactory;
    import VO.Book;
    
    public class doUpdate {
        public static void main(String args[]) throws Exception {
            Book book = new Book();
            try {
                book.setBookid(1);
                book.setBookName("Java特种兵");
                book.setBookNumber(3);
                book.setPubdate(new java.util.Date());
                boolean flag = DAOFactory.getBookDAOInstance().doUpdate(book);
                System.out.println(flag);
            }catch(Exception e) {
                System.out.println(e);
            }
        }
    }
    



    数据删除方法代码测试

    package Test;
    
    import FACTORY.DAOFactory;
    import VO.Book;
    
    public class doDelete {
        public static void main(String args[]) throws Exception {
            Book book = new Book();
            try {
                book.setBookid(1);
                boolean flag = DAOFactory.getBookDAOInstance().doDelete(book);
                System.out.println(flag);
            }catch(Exception e) {
                System.out.println(e);
            }
        }
    }
    



    显示所有数据方法代码测试

    package Test;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    import FACTORY.DAOFactory;
    import VO.Book;
    
    public class findAll {
        public static void main(String args[]) throws Exception {
            List<Book> books = new ArrayList<Book>();
            Book book = new Book();
            try {
                books = DAOFactory.getBookDAOInstance().findAll();
                Iterator<Book> iter = books.iterator();
                while(iter.hasNext()) {
                    book = iter.next();
                    System.out.println(book.getBookName()+"--"+book.getBookNumber()+"--"+book.getPubdate());
                }
            }catch(Exception e) {
                System.out.println(e);
            }
        }
    }
    

    详细代码可以在我的Github上面查看

    (完)

    展开全文
  • J2EE:DAO设计模式

    千次阅读 2014-08-09 15:33:32
    DAO设计模式 DAO设计模式: ... DAO设计模式是属于J2EE数据层的操作,使用DAO设计模式可以简化... 数据库连接类的主要功能是连接数据库并获得连接对象,以及关闭数据库。通过数据库连接类可以大大的简化开发,



    DAO设计模式:

    1、DAO简介:

          DAO设计模式是属于J2EE数据层的操作,使用DAO设计模式可以简化大量代码,增强程序的可移植性。

     

    一个典型的DAO模式的包括的组件:

    1)值对象(数据传输对象)--实体类entity

    2)DAO接口:把对数据库所有的操作定义成一个个抽象的方法;

    3)DAO接口具体实现类:针对不同的数据库、不同的技术来实现DAO接口定义的各种操作;

    4)DAO工厂:为了统一维护、管理DAO访问对象,采取Factory设计模式来建立工厂类


    2、DAO各部分详解:

    DAO设计模式包括以下5个主要部分:

    (1)、数据库连接类;

          数据库连接类的主要功能是连接数据库并获得连接对象,以及关闭数据库。通过数据库连接类可以大大的简化开发,在需要进行数据库连接时,只需常见该类的实例,并调用其中的方法就可以获得数据库连接对象和关闭数据库,不必再进行重复操作。例:


    1. Package com.javaweb.dao1  
    2.   
    3. Import java.sql.*;  
    4.   
    5. Public class DataBaseConnection{  
    6.   
    7.       Private final String DBDRIVER = “com.mysql.jdbc.Driver”;  
    8.   
    9.       Private final String DBURL = “jdbc:mysql://localhost:3306/javaweb”;  
    10.   
    11.       Private final String DBUSER = “root””;  
    12.   
    13.       Private final String DBPASSWORD = “585762”;  
    14.   
    15.       Private Connection conn = null;  
    16.   
    17.       Public DataBaseConnection(){  
    18.   
    19.              Try{  
    20.   
    21.                     Class.forName(DBDRIVER);  
    22.   
    23.                     This.conn =  
    24.   
    25.                                  DriverManager.getConnection(DBURL,DBUSER,DBPASSWORD);  
    26.   
    27.              }catch(Exception e){  
    28.   
    29.                     System.out.println(“加载数据库驱动失败!”);  
    30.   
    31.              }  
    32.   
    33.       }  
    34.   
    35.       Public Connection getConnection(){  
    36.   
    37.              Return conn;  
    38.   
    39.       }  
    40.   
    41.       Public void close(){  
    42.   
    43.              Try{  
    44.   
    45.                     Conn.close();  
    46.   
    47.              }catch(){  
    48.   
    49.                     System.out.println(“数据库连接关闭失败!”);  
    50.   
    51.              }  
    52.   
    53.       }  
    54.   
    55. }  

     

    (2)、VO类:

          VO类是一个包含属性和表中字段完全对应的类,并在该类中提供setter和getter方法来设置并获取该类中的属性。例:

    1. Package com.javaweb.dao1  
    2.   
    3. Public classs User{  
    4.   
    5.       Private int userid;  
    6.   
    7.       Private String username;  
    8.   
    9.       Private String password;  
    10.   
    11.       Public int getUserid(){  
    12.   
    13.             Return userid;  
    14.   
    15.       }  
    16.   
    17.       Public void setUserid(int userid){  
    18.   
    19.              Return userid;  
    20.   
    21.       }  
    22.   
    23.       Public String getUsername(){  
    24.   
    25.             Return username;  
    26.   
    27.       }  
    28.   
    29.       Public void setUsername(String username){  
    30.   
    31.              Return username;  
    32.   
    33.       }  
    34.   
    35.       Public String getUserpassword(){  
    36.   
    37.             Return userpassword;  
    38.   
    39.       }  
    40.   
    41.       Public void setUserid(String userpassword){  
    42.   
    43.              Return userpassword;  
    44.   
    45.       }  
    46.   
    47. }  

     

    (3)、DAO接口:

          DAO接口中定义了所有的用户操作,如添加记录、删除记录及查询记录等。不过因为是借口,所以仅仅是定义,需要子类实现。例:

    1. Package com.javaweb.dao1;  
    2.   
    3. Import java.util.*;  
    4.   
    5. Public class UserDAO{  
    6.        public void insert(User user)throw Exception;  
    7.   
    8.       Public void update(User user)throw Exception;  
    9.   
    10.       Public void delete(int userid)throw Exception;  
    11.   
    12.       Public User queryById(int userid)throw Exception;  
    13.   
    14.       Public List queryAll()throw Exception;  
    15.   
    16. }  

     

    (4)、DAO实现类:

          DAO实现类实现了DAO接口,并实现了接口中定义的所有方法。

    (5)、DAO工厂类:

          在没有DAO工厂类的情况下,必须通过创建DAO实现类的实例才能完成数据库操作。这时就必须知道具体的子类,对于后期的修改非常不方便。

          使用DAO工厂类,可以比较方便地对代码进行管理,而且可以很好地解决后期修改的问题,通过该DAO工厂类的一个静态方法来获取DAO实现类实例。这时如果要替换DAO实现类,只需要修改该Dao工厂类中的方法代码,而不必邀修改所有的操作数据库代码。例:

    1. Package com.javaweb.dao1;  
    2.   
    3. Public class DAOFactory{  
    4.   
    5.       Public static UserDAO getUserDAOInstance(){  
    6.   
    7.              Return new UserDAOImpl();  
    8.   
    9.       }  
    10.   
    11. }  
    12.    

    3、使用DAO完成数据库操作:

    (1)、添加记录:

    (2)、更新记录:

    (3)、删除记录:

    (4)、查询记录:


    展开全文
  • Java 分层设计(DAO设计模式

    万次阅读 多人点赞 2017-05-25 13:44:10
    此文章是本人学习mldn魔乐科技DAO设计模式教学视频后,总结下来,用于复习使用,在这里感谢mldn学习视频。 DAO设计模式? DAO全称是(Data Access Object,数据库访问对象),主要功能就是用于进行数据操作,在...

    此文章是本人学习mldn魔乐科技DAO设计模式教学视频后,总结下来,用于复习使用,在这里感谢mldn的学习视频。

    DAO设计模式?

    DAO全称是(Data Access Object,数据库访问对象),主要功能就是用于进行数据操作的,在程序的标准开发架构中属于数据层的操作。

    简要介绍一下企业分层架构:


    显示层:主要使用JSP/Servlet进行页面效果的显示

    业务层:(Business Object,数据对象)会将多个原子性的DAO操作进行组合,组合成一个完整的业务逻辑。

    数据层:(DAO,Data Access Object,数据库访问对象)提供多个原子性的DAO操作,例如:增、删、改、查,都是原子性操作。

    在整个业务中,最重要的是后台业务层。那什么是业务层?什么是数据层呢?

    下面用个例子展示:



    业务层是整个程序提供的操作功能,而一个业务层的操作要想完成需要多个数据层的操作一起共同完成。

    整个过程之中,发现数据层完成的只是一个个原子性的数据库开发。而在实际开发之中,每一个操作的业务往往需要牵扯到多个原子性的操作,也就是说所有的原子性的操作业务

    最终在业务层中完成。

    在实际的开发之中,业务的设计是非常复杂的,本次的操作知识简单的区分了业务层与数据层的基础关系,如果你的业务非常复杂(如银行项目),往往需要一个总业务层,而

    后会牵扯到若干个子业务层,每一个子业务层又去执行多个数据层。

    具体有多复杂呢?看看下面这个例图:



    对于数据层和业务层,可以概括成如下。

    数据层:又被称为数据访问层(Data Access Object,DAO),是专门进行数据库的原子性操作,也就是说在数据层中最需要控制的就是JDBC中的PreparedStatement接口的使用;

             业务层:又被称为业务中心,业务对象(Business Object,BO),但是现在又有一部分认为应该将其称为服务层(Service),业务层核心的目的是调用多个数据层的操作以完成整体的项目的业务设计,这个是整个项目的核心所在。

    实例分析:

    现在要求使用emp表(empno、ename、job、hiredate、sal、comm)实现如下的操作功能
    (客户所提供的所有的需求都叫做业务)
    -【业务层】实现雇员数据的添加,但是需要保证被添加的雇员编号不会重复;
    【数据层】判断要增加的雇员编号是否存在;
    【数据层】如果雇员编号不存在则进行数据的保存操作;
    -【业务层】实现雇员数据的修改操作;
    【数据层】执行数据的修改操作
    -【业务层】实现多个雇员数据的删除操作;
    【数据层】执行雇员的限定删除操作;
    -【业务层】可以根据雇员编号查找到一个雇员的信息;
    【数据层】根据雇员编号查询指定的雇员数据;
    -【业务层】可以查询所有雇员的信息;
    【数据层】查询全部雇员的数据;
    -【业务层】可以实现数据的分页显示(模糊查询),同时又可以返回所有的雇员数量。
    【数据层】雇员数据的分页查询;
    【数据层】使用COUNT()函数统计出所有的雇员数量。


    结论:用户所提出的所有的需求都应该划分为业务层,因为他指的是功能,而开发人员必须要根据业务层去进行数据层的设计。



    额外话题:从最早的DAO设计模式来讲实际上还会考虑到一个问题,多数据库的移植问题。
    此时就需要设置一个专门的表示连接标准的接口。


    考虑到显示的开发之中,所提供的第三方框架平台越来越完善,所以以上的复杂设计也就慢慢的被忽略了。


    定义DatabaseConnection类

    整个的操作过程之中,DatabaseConnection只是无条件的提供有数据库连接,而至于说有没有连接对象,它都不关心。
    范例:定义DatabaseConnection.java

    package cn.mldn.dbc;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    /*
     * 本类专门负责数据库的连接与关闭操作,在实例化本类对象时就意味着要进行数据库的开发
     * 所以在本类的构造方法里要进行数据库驱动加载与数据库连接取得
     * @author mldn
     * */
    public class DatabaseConnection {
    	private static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver" ;
    	private static final String DBURL = "jdbc:oracle:thin:@localhost:1521:ORCLBRUS" ;
    	private static final String DBUSER = "c##scott" ;
    	private static final String PASSWORD = "tiger" ;
    	private Connection conn = null;
    	/*
    	 * 在构造方法里为conn对象进行实例化,可以直接取得数据库的连接对象
    	 * 由于所有的操作都是基于数据库完成的,如果数据库取得不到连接,那么也就意味着所有的操作都可以停止了
    	 * 
    	 * */
    	public DatabaseConnection(){
    		try {
    			Class.forName(DBDRIVER) ;
    		} catch (ClassNotFoundException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		try {
    			this.conn = DriverManager.getConnection(DBURL,DBUSER,PASSWORD) ;
    		} catch (SQLException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		
    	}
    	/*
    	 * 取得一个数据库的连接对象
    	 * @return Connection实例化对象
    	 * */
    	public Connection getConnection(){
    		return this.conn ;
    	}
    	/*
    	 * 数据库的关闭
    	 * */
    	public void close(){
    		if(this.conn != null){
    			try {
    				this.conn.close();
    			} catch (SQLException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    	}
    
    }
    

    开发Value Object

    现在的程序严格来讲已经给出了四个层次。不同层次之间一定要进行数据的传递,但是既然要操作的是指定的数据表,所以数据的结构必须要与表的结构一一对应,那么自然就可以想到简单Java类(po、to、pojo、vo)。


    在实际的工作之中,针对于简单Java类的开发给出如下的要求:

    (1)      考虑到日后程序有可能出现的分布式应用问题,所以简单Java类必须要实现java.io.Serializable接口;

    (2)      简单java类的名称必须与表名称保存一直;

       例如:表名称student_info,类名称为:StudentInfo;

    (3)      类中的属性不允许使用基本数据类型,都必须使用基本数据类型的包装类;

       因为基本数据类型的数值型默认值是0,而如果是包装类默认值就是null;

    (4)      类中可以定义有多个构造方法,但是必须要保留一个无参构造方法;

    (5)      类中的属性必须使用private封装,封装后的属性必须提供有setter、getter方法;

    将所有的简单Java类保存在vo包中。

    范例:定义Emp.java

    package cn.mldn.vo;
    
    import java.io.Serializable;
    import java.util.Date;
    
    public class Emp implements Serializable {
    	private Integer empno ;
    	private String ename ;
    	private String job ;
    	private Date hiredate ;
    	private Double sal ;
    	private Double comm ;
    	public Integer getEmpno() {
    		return empno;
    	}
    	public void setEmpno(Integer empno) {
    		this.empno = empno;
    	}
    	public String getEname() {
    		return ename;
    	}
    	public void setEname(String ename) {
    		this.ename = ename;
    	}
    	public String getJob() {
    		return job;
    	}
    	public void setJob(String job) {
    		this.job = job;
    	}
    	public Date getHiredate() {
    		return hiredate;
    	}
    	public void setHiredate(Date hiredate) {
    		this.hiredate = hiredate;
    	}
    	public Double getSal() {
    		return sal;
    	}
    	public void setSal(Double sal) {
    		this.sal = sal;
    	}
    	public Double getComm() {
    		return comm;
    	}
    	public void setComm(Double comm) {
    		this.comm = comm;
    	}
    	
    }
    

    开发数据层

    数据层最终是交给业务层进行调用的,所以业务层必须知道数据层的执行标准,

    即:业务层需要明确的知道数据层的操作方法,但是不需要知道他的具体实现。每个层之间的相互访问,是需要有标准的存在,标准的存在就是接口的定义。

    (JDBC是一个标准)



    开发数据层操作标准(也就是接口)

    (不同层之间如果要进行访问,那么必须要提供有接口,以定义操作标准,那么对于数据层也是一样的,因为数据层最终是要交给业务层执行,所以需要先定义出数据层接口)
    对于数据层的接口给出如下的开发要求:
    数据层既然是进行数据操作的,那么就将其保存在dao包下;
    既然不同的数据表的操作有可能使用不同的数据层开发,那么就对于数据表进行命名。
    对emp表,那么数据层的接口就应该定义为IEmpDAO;

    定义IEmpDAO.java:

    package cn.mldn.dao;
    import java.util.*;
    import cn.mldn.vo.*;
    
    /*
     * 定义emp表的数据层的操作标准
     * */
    public interface IEmpDAO {
    	/*
    	 * 实现数据的增加操作
    	 * @param vo 包含了要增加数据的VO对象
    	 * @return 数据保存成功返回true,否则返回false
    	 * @throws Exception SQL执行异常
    	 * */
    	public boolean doCreate(Emp vo) throws Exception;
    
    	/*
    	 * 实现数据的修改操作
    	 * @param vo 包含了要修改数据的信息,一定要提供有ID内容
    	 * @return 数据保存成功返回true,否则返回false
    	 * @throws Exception SQL执行异常
    	 * */
    	public boolean doUpdate(Emp vo) throws Exception;
    
    	/*
    	 * 执行数据的批量删除操作,所有要删除的数据已Set集合的形式保存
    	 * 删除成功返回true(删除的数据个数与要删除的数据个数相同,例如要删除4个,可是要求的是删除5个,则返回false),否则返回false
    	 * @param ids 包含了所有要删除的数据ID,不包含有重复内容
    	 * @return 删除成功返回true(删除的数据个数与要删除的数据个数相同),否则返回false
    	 * @throws Exception SQL执行异常
    	 * */
    	public boolean doRemoveBatch(Set<Integer> ids) throws Exception;
    
    	/*
    	 * 根据雇员编号查询雇员信息
    	 * @param id 要查询的雇员编号
    	 * @return 如果雇员信息存在,则将数据以VO类对象的形式返回,如果雇员数据不存在,则返回null
    	 * @throws Exception SQL执行异常
    	 * */
    	public Emp findById(Integer id) throws Exception ;
    
    	/*
    	 * 查询指定数据表的全部记录,并且以集合的形式返回
    	 * @return 如果表中有数据,则所有的数据会封装为VO对象而后利用List集合返回,
    	 * 如果没有数据,那么集合的长度为0(size()== 0,不是null)
    	 * @throws Exception SQL执行异常
    	 * */
    	public List<Emp> findAll() throws Exception ;
    
    	/*
    	 * 分页进行数据的模糊查询,查询结果以集合的形式返回
    	 * @param currentPage 当前所在的页
    	 * @param lineSize 每页显示的数据行数
    	 * @param column 要进行模糊查询的数据列
    	 * @param keyWord 模糊查询的关键字
    	 * @return 如果表中有数据,则所有的数据会封装为VO对象而后利用List集合返回,
    	 * 如果没有数据,那么集合的长度为0(size()== 0,不是null)
    	 * @throws Exception SQL执行异常
    	 * */
    	public List<Emp> findAllSplit(Integer currentPage, Integer  lineSize, String column, String keyWord) throws Exception ;
    	
    	/*
    	 * 进行模糊查询数据量的统计,如果表中没有记录统计的结果就是0
    	 * @param column 要进行模糊查询的数据列
    	 * @param keyWord 模糊查询的关键字
    	 * @return 返回表中的数据量,如果没有数据返回0
    	 * @throws Exception
    	 * */
    	public Integer getAllCount(String column, String keyWord) throws Exception ;
    }

    对于整个数据层的开发严格来讲就只有两类功能:
    -数据更新:建议它的操作方法以doXxx()的形式命名。例如:doCreate()。
    -数据查询,对于查询分为两种形式:
    (1)查询表中数据:以fingXxx()形式命名。例如:findById()。
    (2)统计表中的数据:以getXxx()形式命名。例如:getName()。



    数据层实现类

    数据层需要被业务层调用,数据层需要进行数据库的执行(PreparedStatement),由于在开发之中一个业务层操作需要执行多个数据层的调用,所以数据库的打开与关闭操作应该由业务层控制会比较合适。
    所有的数据层实现类要求保存在dao.impl子包下。

    范例:EmpDAOImpl子类:

    package cn.mldn.dao.impl;
    
    import java.sql.*;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Set;
    
    
    import cn.mldn.dao.IEmpDAO;
    import cn.mldn.vo.Emp;
    /*
     * =======数据层实现类===========
     * 
     * */
    public class EmpDAOImpl implements IEmpDAO {
    	private Connection conn ;	//需要利用COnnection对象操作
    	private PreparedStatement pstmt ;
    	/*
    	 * 如果要想使用数据层进行原子性的功能操作实现,必须要提供有Connection接口对象
    	 * 另外,由于开发之中业务层要调用数据层,所以数据库的打开与关闭交由业务层处理
    	 * @param conn表示数据库连接对象
    	 * */
    	public EmpDAOImpl(Connection conn){
    		
    		this.conn = conn ;
    	}
    	@Override
    	public boolean doCreate(Emp vo) throws Exception {
    		String sql = "INSERT INTO emp(empno,ename,job,hiredate,sal,comm) VALUES (?,?,?,?,?,?)" ;
    		this.pstmt = this.conn.prepareStatement(sql);
    		this.pstmt.setInt(1, vo.getEmpno());
    		this.pstmt.setString(2, vo.getEname());
    		this.pstmt.setString(3, vo.getJob());
    		this.pstmt.setDate(4, new java.sql.Date(vo.getHiredate().getTime()));
    		this.pstmt.setDouble(5, vo.getSal());
    		this.pstmt.setDouble(6, vo.getComm());
    		return this.pstmt.executeUpdate() > 0 ;
    	}
    
    	@Override
    	public boolean doUpdate(Emp vo) throws Exception {
    		String sql = "UPDATE emp SET ename=?,job=?,hiredate=?,sal=?,comm=? WHERE empno=?" ;
    		this.pstmt = this.conn.prepareStatement(sql);
    		this.pstmt.setString(1, vo.getEname());
    		this.pstmt.setString(2, vo.getJob());
    		this.pstmt.setDate(3, new java.sql.Date(vo.getHiredate().getTime()));
    		this.pstmt.setDouble(4, vo.getSal());
    		this.pstmt.setDouble(5, vo.getComm());
    		this.pstmt.setInt(6, vo.getEmpno());
    		return this.pstmt.executeUpdate() > 0 ;
    
    	}
    	/*
    	 * =====================
    	 * 删除是最头疼的,
    	 * 
    	 * */
    	@Override
    	public boolean doRemoveBatch(Set<Integer> ids) throws Exception {
    		if(ids == null || ids.size() == 0){	//没有要删除的数据
    			return false ;
    		}
    		//字符串的拼凑使用StringBuffer
    		StringBuffer sql = new StringBuffer() ;
    		sql.append("DELETE FROM emp WHERE empno IN(") ;
    		Iterator<Integer> iter = ids.iterator() ;
    		while(iter.hasNext()){
    			//删除语句的格式是delete from emp where empno in ("","","",);
    			sql.append(iter.next()).append(",") ;
    		}
    		//删除最后一个逗号,并且添加)
    		sql.delete(sql.length()-1, sql.length()).append(")");
    		/* conn.prepareStatement()只接受String,所以让
    		 * StringBuffer转为String,需要用toString(),
    		 * 这是重点强调了的知识点
    		 * 
    		 * */
    		this.pstmt = this.conn.prepareStatement(sql.toString());
    		//pstmt.executeUpdate()返回结果为int
    		return this.pstmt.executeUpdate() == ids.size();
    	}
    
    	@Override
    	public Emp findById(Integer id) throws Exception {
    		Emp vo = null ;
    		String sql = "SELECT empno,ename,job,hiredate,sal,comm FROM emp WHERE empno=?" ;
    		this.pstmt = this.conn.prepareStatement(sql) ;
    		this.pstmt.setInt(1, id);
    		ResultSet rs = this.pstmt.executeQuery() ;
    		if(rs.next()) {
    			vo = new Emp() ;
    			vo.setEmpno(rs.getInt(1));
    			vo.setEname(rs.getString(2));
    			vo.setJob(rs.getString(3));
    			vo.setHiredate(rs.getDate(4));
    			vo.setSal(rs.getDouble(5));
    			vo.setComm(rs.getDouble(6));
    		}
    		return vo ;
    	}
    
    	@Override
    	public List<Emp> findAll() throws Exception {
    		List<Emp> all = new ArrayList<Emp>() ;
    		String sql = "SELETE empno,ename,job,hiredate,sal,comm FROM emp" ;
    		this.pstmt = this.conn.prepareStatement(sql) ;
    		ResultSet rs = this.pstmt.executeQuery() ;
    		while(rs.next()) {
    			Emp vo = new Emp() ;
    			vo.setEmpno(rs.getInt(1));
    			vo.setEname(rs.getString(2));
    			vo.setJob(rs.getString(3));
    			vo.setHiredate(rs.getDate(4));
    			vo.setSal(rs.getDouble(5));
    			vo.setComm(rs.getDouble(6));
    			all.add(vo) ;
    		}
    		return all;
    	}
    
    	/*
    	 * =======重点难点(需要拼凑sql语句)======
    	 * */
    	@Override
    	public List<Emp> findAllSplit(Integer currentPage, Integer lineSize, String column, String keyWord) throws Exception {
    		List<Emp> all = new ArrayList<Emp>() ;
    		String sql = "SELECT * FROM "
    				+ " (SELECT empno,ename,job,hiredate,sal,comm,ROWNUM rn"
    				+ " FROM emp"
    				+ " WHERE " + column + " LIKE ? AND ROWNUM<=?) temp "
    				+ " WHERE temp.rn>? " ;
    		this.pstmt = this.conn.prepareStatement(sql) ;
    		this.pstmt.setString(1, "%" + keyWord + "%");
    		this.pstmt.setInt(2, currentPage * lineSize);
    		this.pstmt.setInt(3, (currentPage - 1) * lineSize);
    		ResultSet rs = this.pstmt.executeQuery() ;
    		while(rs.next()) {
    			Emp vo = new Emp() ;
    			vo.setEmpno(rs.getInt(1));
    			vo.setEname(rs.getString(2));
    			vo.setJob(rs.getString(3));
    			vo.setHiredate(rs.getDate(4));
    			vo.setSal(rs.getDouble(5));
    			vo.setComm(rs.getDouble(6));
    			all.add(vo) ;
    		}
    		return all;
    	}
    
    	@Override
    	public Integer getAllCount(String column, String keyWord) throws Exception {
    		String sql = "SELECT COUNT(empno) FROM emp WHERE " + column + " LIKE ?" ;
    		this.pstmt = this.conn.prepareStatement(sql) ;
    		this.pstmt.setString(1, "%" + keyWord + "%");
    		ResultSet rs = this.pstmt.executeQuery() ;
    		if(rs.next()) {
    			return rs.getInt(1) ;
    		}
    		return null;
    	}
    
    }
    


    定义数据层工厂类--DAOFactory

      业务层要想进行数据层的调用,那么必须要取得IEmpDAO接口对象,但是不同层之间要想取得接口对象实例,需要使用工厂设计模式,这个工厂类将其保存在factory子包下。

    范例:定义工厂类

    package cn.mldn.factory;
    
    import java.sql.Connection;
    import cn.mldn.dao.IEmpDAO;
    import cn.mldn.dao.impl.*;
    
    /*
     * 数据层的实现类--工厂设计类
     * 
     * */
    public class DAOFactory {
    	public static IEmpDAO getIEmpDAOInstance(Connection conn){
    		return new EmpDAOImpl(conn) ;
    	}
    }
    


    使用工厂的特征就是外层不需要知道具体的子类。



    开发业务层
    业务层是真正留给外部调用的,可能是控制层,或者是直接调用,既然业务层也是由不同的层进行调用,所以业务层开发的首要任务就是定义业务层的操作标准。


    开发业务层标准—IEmpService

             业务层也可以称为Service层,既然描述的是emp表的操作,所以名称就定义为IEmpService,并且保存在Service的子包下,但是对于业务层的方法定义并没有明确的要求,只不过个人强烈建议还是写上有意义的统一名称;

    范例:定义IEmpService操作标准

    package cn.mldn.service;
    
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    import cn.mldn.vo.Emp ;
    
    /*
     * 定义emp表的业务层的执行标准
     * 
     * */
    /**
     * 定义emp表的业务层的执行标准,此类一定要负责数据库的打开与关闭操作
     * 此类可以通过DAOFactory类取得IEmpDAO接口对象
     * @author Bruis
     *
     */
    public interface IEmpService {
    	
    	/**
    	 * 实现雇员数据的增加操作,本次操作要调用IEmpDAO接口的如下方法
    	 * 需要调用IEmpDAO.findById()方法,判断要增加数据的id是否已经存在
    	 * 如果现在要增加的数据编号不存在则调用IEmpDAO.doCreate()方法,返回操作的结果
    	 * @param vo包含了要增加数据的VO对象
    	 * @return 如果增加数据的ID重复或者保存失败,返回false,否则返回true
    	 * @throws SQLException
    	 */
    	public boolean insert(Emp vo) throws Exception ;
    
    	/**
    	 * 实现雇员数据的修改操作,本次要调用IEmpDAO.doUpdate()方法,本次修改属于全部内容的修改
    	 * @param vo
    	 * @return
    	 * @throws SQLException
    	 */
    	public boolean update(Emp vo) throws Exception ;
    
    	/**
    	 * 执行雇员数据的删除操作,可以删除多个雇员信息,调用IEmpDAO.doRemoveBatch()方法
    	 * @param ids包含了全部要删除数据的集合,没有重复数据
    	 * @return
    	 * @throws SQLException
    	 */
    	public boolean delete(Set<Integer> ids) throws Exception ;
    
    	/**
    	 * 根据雇员编号查找雇员的完整信息,调用IEmpDAO.findById()犯法
    	 * @param ids
    	 * @return 如果找到了则雇员信息已VO对象返回,否则返回null
    	 * @throws SQLException
    	 */
    	public Emp get(Integer ids) throws Exception ;
    
    	/**
    	 * 查询全部雇员信息,调用IEmpDAO.findAll()方法
    	 * @return 查询结果以List集合的形式返回,如果没有数据则集合的长度为0
    	 * @throws SQLException
    	 */
    	public List<Emp> list() throws Exception ;
    
    	/**
    	 * 实现数据的模糊查询与数据统计,要调用IEmpDAO接口的两个方法
    	 * 调用IEmpDAO.findAllSplit()方法,查询出所有的表数据,返回的是List<Emp>
    	 * 调用IEmpDAO.getAllCount()方法,查询所有的数据量,返回的Integer
    	 * @param currentPage 当前所在页
    	 * @param lineSize 每页显示的记录数
    	 * @param column 模糊查询的数据列
    	 * @param keyWord 关键字
    	 * 
    	 * @return 由于需要返回多种数据类型,所以使用Map集合返回,由于类型不统一,所以所有value的类型设置为Object
    	 * 如果key = allEmps,value = IEmpDAO.findAllSplit()返回结果,List<Emp>
    	 * 如果key = empCount,value = IEmpDAO.getAllCount()返回结果,Integer
    	 * @throws Exception
    	 */
    	public Map<String,Object> list(int currentPage,int lineSize,String column,String keyWord) throws Exception ;
    }
    

    业务层实现类
    -业务层实现类的核心功能:
    (1)负责控制数据库的打开和关闭,当存在了业务层对象后其目的就是为了操作数据库,即:业务层对象实例化之后就必须准备好数据库连接:
    (2)根据DAOFactory调用getIEmpDAOInstance()方法而后取得IEmpDAO接口对象。业务层的实现类编程在dao.impl子包中。

    范例:定义EmpServiceImpl子类

    package cn.mldn.service.impl;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    import cn.mldn.dbc.DatabaseConnection;
    import cn.mldn.factory.DAOFactory;
    import cn.mldn.service.IEmpService;
    import cn.mldn.vo.Emp;
    
    /**
     * 业务层实现子类的编写
     * @author Bruis
     *
     */
    public class EmpServiceImpl implements IEmpService {
    	//在这个类的对象内部就提供有一个数据库连接类的实例化对象
    	private DatabaseConnection dbc = new DatabaseConnection() ;
    	@Override
    	public boolean insert(Emp vo) throws Exception {
    		try{
    			//要增加的雇员编号如果不存在,则findById返回的结果就是null,null表示可以进行新雇员的数据增加
    			if(DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).findById(vo.getEmpno()) == null){
    				return DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).doCreate(vo) ;
    			}
    			return false ;
    		} catch(Exception e) {
    			throw e ;
    		} finally {
    			this.dbc.close() ;
    		}
    	}
    
    	@Override
    	public boolean update(Emp vo) throws Exception {
    		try{
    			return DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).doUpdate(vo) ;
    		} catch(Exception e) {
    			throw e ;
    		} finally {
    			this.dbc.close() ;
    		}
    	}
    
    	@Override
    	public boolean delete(Set<Integer> ids) throws Exception {
    		try{
    			return DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).doRemoveBatch(ids) ;
    		} catch(Exception e) {
    			throw e ;
    		} finally {
    			this.dbc.close() ;
    		}
    	}
    
    	@Override
    	public Emp get(Integer ids) throws Exception {
    		try{
    			return DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).findById(ids) ;
    		} catch(Exception e) {
    			throw e ;
    		} finally {
    			this.dbc.close() ;
    		}
    	}
    
    	@Override
    	public List<Emp> list() throws Exception {
    		try{
    			return DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).findAll() ;
    		} catch(Exception e) {
    			throw e ;
    		} finally {
    			this.dbc.close() ;
    		}
    	}
    
    	@Override
    	public Map<String, Object> list(int currentPage, int lineSize, String column, String keyWord) throws Exception {
    		/*
    		 * 查看IEmpService的注释
    		 * @return 由于需要返回多种数据类型,所以使用Map集合返回,由于类型不统一,所以所有value的类型设置为Object
    		 * 如果key = allEmps,value = IEmpDAO.findAllSplit()返回结果,List<Emp>
    		 * 如果key = empCount,value = IEmpDAO.getAllCount()返回结果,Integer
    		 * */
    		try{
    			Map<String,Object> map = new HashMap<String,Object>() ;
    			map.put("allEmps",DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).findAllSplit(currentPage, lineSize, column, keyWord)) ;
    			map.put("empCount",DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).getAllCount(column, keyWord) ) ;
    			return map ;
    		} catch(Exception e) {
    			throw e ;
    		} finally {
    			this.dbc.close() ;
    		}
    	}
    
    }
    

    不同层之间的访问依靠的就是工厂类和接口进行操作。



    定义业务层的工厂类——ServiceFactory

    业务层最终依然需要被其他的层所使用,所以需要为其定义工厂类,该类也同

    样保存在factory子包下,如果从实际的开发来讲,业务层应该分成两种,

    (1) 前台业务逻辑:可以将其保存在service.front包中,工厂类:SercviceFrontFactory包

    (2) 后台业务逻辑:可以将其保存在service.back包中,工厂类:ServiceBackFactory

    范例:定义ServiceFactory

    /**
     * @param
     */
    package cn.mldn.factory;
    
    import cn.mldn.service.IEmpService;
    import cn.mldn.service.impl.EmpServiceImpl;
    
    /**
     * @author Administrator
     *
     */
    public class ServiceFactory {
    	public static IEmpService getIEmpServiceInstance(){
    		return new EmpServiceImpl() ;
    	}
    }


    在实际的编写之中,子类永远都是不可见的,同时在整个操作里面,控制层完全看不到任何的JDBC代码。


    然后下面看一下包的结构:(需要导入oracle的jar包-ojdbc6)



    下面就来进行测试,测试之前把oracle服务与监听给打开。

    测试类在cn.mldn.test包下

    package cn.mldn.test;
    
    import java.util.Date;
    
    import cn.mldn.factory.ServiceFactory;
    import cn.mldn.vo.Emp;
    
    public class TestEmpInsert {
    	public static void main(String[] args) {
    		Emp vo = new Emp() ;
    		vo.setEmpno(8889);
    		vo.setEname("陈冠佑");
    		vo.setJob("摄影师");
    		vo.setHiredate(new Date());
    		vo.setSal(10.0);
    		vo.setComm(0.5);
    		try {
    			System.out.println(ServiceFactory.getIEmpServiceInstance().insert(vo));
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    
    	}
    
    }
    

    运行TestEmpInsert类之前,看一看emp表的数据情况(位于c##scott用户中的emp表):



    运行了TestEmpInsert类之后,结果返回true,表面插入数据成功:


    此时,再看看emp表的情况:


    测试结束,成功插入数据。


    下面再来测试一下分页查询:

    运行TestEmpSplit.java

    package cn.mldn.test;
    
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    
    import cn.mldn.factory.ServiceFactory;
    import cn.mldn.vo.Emp;
    
    	
    public class TestEmpSplit {
    	//这是压制警告
    	@SuppressWarnings("unchecked")
    	public static void main(String[] args) {
    		try {
    			Map<String,Object> map = ServiceFactory.getIEmpServiceInstance().list(2,5,"ename","") ;
    			//取出分页过后的记录条数,需要向下转型为Integer
    			int count = (Integer)map.get("empCount") ;
    			System.out.println("数据库总的记录条数:" + count);
    			List<Emp> all = (List<Emp>) map.get("allEmps") ;
    			Iterator<Emp> iter = all.iterator() ;
    			while(iter.hasNext()) {
    				Emp vo = iter.next() ;
    				System.out.println(vo.getEname() + ", " + vo.getJob() );
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		
    	}
    
    }
    

    运行结果:


    测试成功。


    下面来操作Dept表——实现部门操作

    现在要求使用部门表(dept)表实现如下的操作功能
    (客户所提供的所有的需求都叫做业务)

    -【业务层】进行部门数据的添加;

    【数据层】判断要增加的部门编号是否存在,如果不存在则可以添加;

    【数据层】实现部门数据的保存;

    -【业务层】进行部门数据的修改;

    【数据层】执行部门数据的修改操作

    -【业务层】进行部门数据的删除;

    【数据层】执行部门数据删除;

    -【业务层】进行部门数据的全部查询;

    【数据层】查询全部;

    -【业务层】可以根据部门编号查询一个部门完整信息;

    【数据层】根据编号查询;

    一、定义Dept.java

    package cn.mldn.vo;
    
    import java.io.Serializable;
    
    @SuppressWarnings("serial")
    public class Dept implements Serializable {
    	private Integer deptno ;
    	private String dname ;
    	private String loc ;
    	public Integer getDeptno() {
    		return deptno;
    	}
    	public void setDeptno(Integer deptno) {
    		this.deptno = deptno;
    	}
    	public String getDname() {
    		return dname;
    	}
    	public void setDname(String dname) {
    		this.dname = dname;
    	}
    	public String getLoc() {
    		return loc;
    	}
    	public void setLoc(String loc) {
    		this.loc = loc;
    	}
    }
    

    几乎所有的数据表都应该具备有基础CRUD功能(增加、修改全部、删除数据、根据id显示、数据统计),那么这些功能的方法每个接口都要重复定义。

    在整个DAO接口定义的过程中,不同的表区别在于:VO类、主键类型。为了避免代码重复,定义一个公共的接口。那么为了解决重复问题,使用泛型实现接口的继承操作。


    二、定义接口IDAO

    package cn.mldn.dao;
    
    import java.util.List;
    import java.util.Set;
    
    import cn.mldn.vo.Emp;
    
    /**
     * 定义公共的DAO操作接口标准,基本的功能包括:增加、修改全部、删除数据、根据编号查询、查询全部、分页显示、数据统计
     * @author mldn
     *
     * @param <K> 表示要操作的主键类型,由子接口实现
     * @param <V> 表示要操作的VO类型,由子接口实现
     */
    @SuppressWarnings("unused")
    public interface IDAO<K,V> {
    	/*
    	 * 实现数据的增加操作
    	 * @param vo 包含了要增加数据的VO对象
    	 * @return 数据保存成功返回true,否则返回false
    	 * @throws Exception SQL执行异常
    	 * */
    	public boolean doCreate(V vo) throws Exception;
    
    	/*
    	 * 实现数据的修改操作
    	 * @param vo 包含了要修改数据的信息,一定要提供有ID内容
    	 * @return 数据保存成功返回true,否则返回false
    	 * @throws Exception SQL执行异常
    	 * */
    	public boolean doUpdate(V vo) throws Exception;
    
    	/*
    	 * 执行数据的批量删除操作,所有要删除的数据已Set集合的形式保存
    	 * 删除成功返回true(删除的数据个数与要删除的数据个数相同,例如要删除4个,可是要求的是删除5个,则返回false),否则返回false
    	 * @param ids 包含了所有要删除的数据ID,不包含有重复内容
    	 * @return 删除成功返回true(删除的数据个数与要删除的数据个数相同),否则返回false
    	 * @throws Exception SQL执行异常
    	 * */
    	public boolean doRemoveBatch(Set<K> ids) throws Exception;
    
    	/*
    	 * 根据雇员编号查询雇员信息
    	 * @param id 要查询的雇员编号
    	 * @return 如果雇员信息存在,则将数据以VO类对象的形式返回,如果雇员数据不存在,则返回null
    	 * @throws Exception SQL执行异常
    	 * */
    	public V findById(K id) throws Exception ;
    
    	/*
    	 * 查询指定数据表的全部记录,并且以集合的形式返回
    	 * @return 如果表中有数据,则所有的数据会封装为VO对象而后利用List集合返回,
    	 * 如果没有数据,那么集合的长度为0(size()== 0,不是null)
    	 * @throws Exception SQL执行异常
    	 * */
    	public List<V> findAll() throws Exception ;
    
    	/*
    	 * 分页进行数据的模糊查询,查询结果以集合的形式返回
    	 * @param currentPage 当前所在的页
    	 * @param lineSize 每页显示的数据行数
    	 * @param column 要进行模糊查询的数据列
    	 * @param keyWord 模糊查询的关键字
    	 * @return 如果表中有数据,则所有的数据会封装为VO对象而后利用List集合返回,
    	 * 如果没有数据,那么集合的长度为0(size()== 0,不是null)
    	 * @throws Exception SQL执行异常
    	 * */
    	public List<V> findAllSplit(Integer currentPage, Integer  lineSize, String column, String keyWord) throws Exception ;
    	
    	/*
    	 * 进行模糊查询数据量的统计,如果表中没有记录统计的结果就是0
    	 * @param column 要进行模糊查询的数据列
    	 * @param keyWord 模糊查询的关键字
    	 * @return 返回表中的数据量,如果没有数据返回0
    	 * @throws Exception
    	 * */
    	public Integer getAllCount(String column, String keyWord) throws Exception ;
    }
    

    三、定义IDeptDAO接口
    package cn.mldn.dao;
    
    import cn.mldn.vo.Dept;
    
    public interface IDeptDAO extends IDAO<Integer,Dept>{
    
    }
    


    四、重新定义IEmpDAO接口

    package cn.mldn.dao;
    import java.util.*;
    import cn.mldn.vo.*;
    
    /*
     * 定义emp表的数据层的操作标准
     * */
    public interface IEmpDAO extends IDAO<Integer,Emp>{
    }
    



    五、定义DeptDAOImpl子类

    package cn.mldn.dao.impl;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Set;
    
    import cn.mldn.dao.IDeptDAO;
    import cn.mldn.vo.Dept;
    
    public class DeptDAOImpl implements IDeptDAO {
    	private Connection conn ;
    	private PreparedStatement pstmt ;
    	public DeptDAOImpl(Connection conn){
    		this.conn = conn ;
    	}
    	@Override
    	public boolean doCreate(Dept vo) throws Exception {
    		String sql = "INSERT INTO dept(deptno,dname,loc) VALUES (?,?,?)" ;
    		this.pstmt = this.conn.prepareStatement(sql) ;
    		this.pstmt.setInt(1, vo.getDeptno());
    		this.pstmt.setString(2, vo.getDname());
    		this.pstmt.setString(3, vo.getLoc());
    		return this.pstmt.executeUpdate() > 0;
    	}
    
    	@Override
    	public boolean doUpdate(Dept vo) throws Exception {
    		String sql = "UPDATE dept SET dname=?,loc=? WHERE deptno=?" ;
    		this.pstmt = this.conn.prepareStatement(sql) ;
    		this.pstmt.setString(1, vo.getDname());
    		this.pstmt.setString(2, vo.getLoc());
    		this.pstmt.setInt(3, vo.getDeptno());
    		return this.pstmt.executeUpdate() > 0;
    	}
    
    	@Override
    	public boolean doRemoveBatch(Set<Integer> ids) throws Exception {
    		if(ids == null || ids.size() == 0){	//没有要删除的数据
    			return false ;
    		}
    		//字符串的拼凑使用StringBuffer
    		StringBuffer sql = new StringBuffer() ;
    		sql.append("DELETE FROM dept WHERE deptno IN(") ;
    		Iterator<Integer> iter = ids.iterator() ;
    		while(iter.hasNext()){
    			//删除语句的格式是delete from emp where empno in ("","","",);
    			sql.append(iter.next()).append(",") ;
    		}
    		//删除最后一个逗号,并且添加)
    		sql.delete(sql.length()-1, sql.length()).append(")");
    		/* conn.prepareStatement()只接受String,所以让
    		 * StringBuffer转为String,需要用toString(),
    		 * 这是重点强调了的知识点
    		 * 
    		 * */
    		this.pstmt = this.conn.prepareStatement(sql.toString());
    		//pstmt.executeUpdate()返回结果为int
    		return this.pstmt.executeUpdate() == ids.size();
    	}
    
    	@Override
    	public Dept findById(Integer id) throws Exception {
    		Dept vo = null ;
    		String sql = "SELECT deptno,dname,loc FROM dept WHERE deptno=?" ;
    		this.pstmt = this.conn.prepareStatement(sql) ;
    		this.pstmt.setInt(1, id);
    		ResultSet rs = this.pstmt.executeQuery() ;
    		if(rs.next()){
    			vo = new Dept() ;
    			vo.setDeptno(rs.getInt(1));
    			vo.setDname(rs.getString(2));
    			vo.setLoc(rs.getString(3));
    		}
    		return vo ;
    	}
    
    	@Override
    	public List<Dept> findAll() throws Exception {
    		List<Dept> all = new ArrayList<Dept>() ;
    		String sql = "SELECT deptno,dname,loc FROM dept" ;
    		this.pstmt = this.conn.prepareStatement(sql) ;
    		ResultSet rs = this.pstmt.executeQuery() ;
    		while(rs.next()){
    			Dept vo = new Dept() ;
    			vo.setDeptno(rs.getInt(1));
    			vo.setDname(rs.getString(2));
    			vo.setLoc(rs.getString(3));
    			all.add(vo);
    		}
    		return all;
    	}
    
    	@Override
    	public List<Dept> findAllSplit(Integer currentPage, Integer lineSize, String column, String keyWord)
    			throws Exception {
    		throw new Exception("此方法未使用") ;
    	}
    
    	@Override
    	public Integer getAllCount(String column, String keyWord) throws Exception {
    		throw new Exception("此方法未使用") ;
    	}
    
    }
    

    六、修改DAOFactory类,增加新的接口对象取得方法。

    package cn.mldn.factory;
    
    import java.sql.Connection;
    
    import cn.mldn.dao.IDeptDAO;
    import cn.mldn.dao.IEmpDAO;
    import cn.mldn.dao.impl.DeptDAOImpl;
    import cn.mldn.dao.impl.EmpDAOImpl;
    
    /*
     * 数据层的实现类--工厂设计类
     * 
     * */
    public class DAOFactory {
    	public static IEmpDAO getIEmpDAOInstance(Connection conn){
    		return new EmpDAOImpl(conn) ;
    	}
    	public static IDeptDAO getIDeptDAOInstance(Connection conn){
    		return new DeptDAOImpl(conn) ;
    	}
    }
    

    七、开发IDeptService接口

    package cn.mldn.service;
    
    import java.util.List;
    import java.util.Set;
    
    import cn.mldn.vo.Dept;
    
    public interface IDeptService {
    	public boolean insert(Dept vo) throws Exception ;
    	public boolean update(Dept vo) throws Exception ;
    	public boolean delete(Set<Integer> ids) throws Exception ;
    	public List<Dept> list() throws Exception ;
    	public Dept get(int id) throws Exception ;
    }
    

    八、实现DeptServiceImpl

    package cn.mldn.service.impl;
    
    import java.util.List;
    import java.util.Set;
    
    import cn.mldn.dbc.DatabaseConnection;
    import cn.mldn.factory.DAOFactory;
    import cn.mldn.service.IDeptService;
    import cn.mldn.vo.Dept;
    
    public class DeptServiceImpl implements IDeptService {
    	private DatabaseConnection dbc = new DatabaseConnection() ;
    
    	@Override
    	public boolean insert(Dept vo) throws Exception {
    		try{
    			if(DAOFactory.getIDeptDAOInstance(this.dbc.getConnection()).findById(vo.getDeptno()) == null){
    				return DAOFactory.getIDeptDAOInstance(this.dbc.getConnection()).doCreate(vo);
    			}
    			return false;
    		}catch(Exception e){
    			throw e ;
    		}finally{
    			this.dbc.close();
    		}
    	}
    
    	@Override
    	public boolean update(Dept vo) throws Exception {
    		try{
    			return DAOFactory.getIDeptDAOInstance(this.dbc.getConnection()).doUpdate(vo);
    		}catch(Exception e){
    			throw e ;
    		}finally{
    			this.dbc.close();
    		}
    	}
    
    	@Override
    	public boolean delete(Set<Integer> ids) throws Exception {
    		try{
    			return DAOFactory.getIDeptDAOInstance(this.dbc.getConnection()).doRemoveBatch(ids);
    		}catch(Exception e){
    			throw e ;
    		}finally{
    			this.dbc.close();
    		}
    	}
    
    	@Override
    	public List<Dept> list() throws Exception {
    		try{
    			return DAOFactory.getIDeptDAOInstance(this.dbc.getConnection()).findAll();
    		}catch(Exception e){
    			throw e ;
    		}finally{
    			this.dbc.close();
    		}
    	}
    
    	@Override
    	public Dept get(int id) throws Exception {
    		try{
    			return DAOFactory.getIDeptDAOInstance(this.dbc.getConnection()).findById(id);
    		}catch(Exception e){
    			throw e ;
    		}finally{
    			this.dbc.close();
    		}
    	}
    
    }
    

    九、修改服务层工厂类

    /**
     * @param
     */
    package cn.mldn.factory;
    
    import cn.mldn.service.IDeptService;
    import cn.mldn.service.IEmpService;
    import cn.mldn.service.impl.DeptServiceImpl;
    import cn.mldn.service.impl.EmpServiceImpl;
    
    /**
     * @author Administrator
     *
     */
    public class ServiceFactory {
    	public static IEmpService getIEmpServiceInstance(){
    		return new EmpServiceImpl() ;
    	}
    	public static IDeptService getIDeptServiceInstance(){
    		return new DeptServiceImpl();
    	}
    }
    

    这里的测试要用到Junit。接下来的文章会介绍到。


    展开全文
  • DAO设计模式简介

    2020-07-09 17:19:16
    DAO(Data Access Object,数据访问对象),主要的功能是用于进行数据操作,在程序标准开发框架中属于数据层操作。 数据开发结构: 资源层是数据库操作层,里面可以进行各种数据库存储,但是这些数据存储...
    展开全文
  • java-DAO设计模式

    2015-03-15 23:39:00
    1.DAO设计模式 DAO全称是Data Access Object,数据库访问对象,主要的功能就是用于进行数据操作,在程序标准开发架构中属于数据层操作2.企业分层架构  客户层(Client):因为现在都...
  • 文章目录DAO设计模式详细--实例开发1.0 程序分层思想3.0 项目准备3.1数据库连接类3.2 开发value-object3.3 开发数据层3.3.1 开发数据层操作标准3.4 数据层实现类3.4.1jdbc中如何实现动态分页**3.5定义DAO工厂类...
  • DAO设计模式-2

    2014-02-22 09:45:10
    DAO设计模式简介 DAO(Data Access Object,数据访问对象),主要的功能就是用于进行数据操作,在程序标准开发框架中属于数据层操作。 企业分层架构 1):客户层:因为现在都采用了B/S开发架构,所以一般...
  • DAO设计模式-1

    2014-02-21 22:12:16
    DAO设计模式简介 DAO(Data Access Object,数据访问对象),主要的功能就是用于进行数据操作,在程序标准开发框架中属于数据层操作。 企业分层架构 1):客户层:因为现在都采用了B/S开发架构,所以一般...
  • DAO是数据访问对象简称(Data Access Object),是数据访问层(也可以称为数据层)一种对象。可以将项目分层为显示层,控制层,业务层,数据访问层,数据库。通常来看,我们要做一个项目,比如说一个客户端,...

空空如也

空空如也

1 2 3 4 5 ... 14
收藏数 262
精华内容 104
关键字:

dao设计模式的主要功能