zoukankan      html  css  js  c++  java
  • (一)DAO设计及BaseDAO和BookDAO的实现

    1.总体架构

    MVC 设计模式:
    Model:POJO(Plain Old Java Object)
    Controller:Servlet
    View:JSP + EL + JSTL

    2.技术选型

    数据库:MySQL
    数据源:C3P0
    JDBC 工具:DBUtils
    事务解决方案:Filter + ThreadLocal
    Ajax 解决方案:jQuery + JavaScript + JSON + google-gson
    层之间解耦方案:工厂设计模式

     3.数据表设计

    相关表的创建

    DROP TABLE IF EXISTS `account`;
    
    CREATE TABLE `account` (
      `accountid` INT(11) NOT NULL AUTO_INCREMENT,
      `balance` FLOAT DEFAULT NULL,
      PRIMARY KEY  (`accountid`)
    )
    INSERT  INTO `account`(`accountid`,`balance`) VALUES (1,9740);
    
    DROP TABLE IF EXISTS `mybooks`;
    CREATE TABLE `mybooks` (
      `Id` INT(11) NOT NULL AUTO_INCREMENT,
      `Author` VARCHAR(30) NOT NULL,
      `Title` VARCHAR(30) NOT NULL,
      `Price` FLOAT NOT NULL,
      `Publishingdate` DATE NOT NULL,
      `Salesamount` INT(11) NOT NULL,
      `Storenumber` INT(11) NOT NULL,
      `Remark` TEXT NOT NULL,
      PRIMARY KEY  (`Id`)
    ) 
    INSERT  INTO `mybooks`(`Id`,`Author`,`Title`,`Price`,`Publishingdate`,`Salesamount`,`Storenumber`,`Remark`) 
    VALUES (1,'Tom','Java 编程思想',50,'2009-06-22',17,83,'Good Java Book'),
    (2,'Jerry','Oracle DBA 教材',60,'2009-06-22',12,88,'Good Oracle Book'),
    (3,'Bob','Ruby',50,'2009-06-22',12,88,'Good 0'),
    (4,'Mike','Javascript',51,'2009-06-22',0,100,'Good 1'),
    (5,'Rose','Ajax',52,'2009-06-22',0,100,'Good 2'),
    (6,'Backham','Struts',53,'2009-06-22',0,100,'Good 3'),
    (7,'Zidon','Hibernate',54,'2009-06-22',2,12,'Good 4'),
    (8,'Ronaerdo','Spring',55,'2009-06-22',2,13,'Good 5'),
    (9,'Clinsman','Cvs',56,'2009-06-22',0,16,'Good 6'),
    (10,'Kaka','Seo',57,'2009-06-22',0,17,'Good 7'),
    (11,'Lauer','Lucence',58,'2009-06-22',0,18,'Good 8'),
    (12,'Kasi','Guice',59,'2009-06-22',0,19,'Good 9'),
    (13,'Prierlo','Mysql',60,'2009-06-22',6,14,'Good 10'),
    (14,'Haohaidong','DB2',61,'2009-06-22',9,12,'Good 11'),
    (15,'Feige','Sybase',62,'2009-06-22',8,14,'Good 12'),
    (16,'Tuoleisi','DBDesign',63,'2009-06-22',0,23,'Good 13'),
    (17,'Jielade','Eclipse',64,'2009-06-22',0,24,'Good 14'),
    (18,'Teli','Netbeans',65,'2009-06-22',0,25,'Good 15'),
    (19,'Lapade','C#',66,'2009-06-22',0,26,'Good 16'),
    (20,'Runi','JDBC',67,'2009-06-22',0,27,'Good 17'),
    (21,'JoeKeer','Php',68,'2009-06-22',0,28,'Good 18'),
    (22,'Jordan','MysqlFront',69,'2009-06-22',5,24,'Good 19'),
    (23,'Yaoming','NoteBook',70,'2009-06-22',5,25,'Good 20'),
    (24,'Yi','C',71,'2009-06-22',5,26,'Good 21'),
    (25,'Sun','Css',72,'2009-06-22',0,32,'Good 22'),
    (26,'Xuliang','JQuery',73,'2009-06-22',0,33,'Good 23'),
    (27,'Meixi','Ext',74,'2009-06-22',0,34,'Good 24'),
    (28,'Apple','iphone',75,'2009-06-22',0,35,'Good 25'),
    (29,'Aigo','dc',76,'2009-06-22',0,36,'Good 26'),
    (30,'Sony','psp',77,'2009-06-22',0,100,'Good 27'),
    (31,'IRiver','mp3',78,'2009-06-22',0,100,'Good 28'),
    (32,'Sansing','TV',79,'2009-06-22',0,100,'Good 29');
    
    DROP TABLE IF EXISTS `trade`;
    CREATE TABLE `trade` (
      `tradeid` INT(11) NOT NULL AUTO_INCREMENT,
      `userid` INT(11) NOT NULL,
      `tradetime` DATETIME NOT NULL,
      PRIMARY KEY  (`tradeid`),
      KEY `user_id_fk` (`userid`),
      CONSTRAINT `user_id_fk` FOREIGN KEY (`userid`) REFERENCES `userinfo` (`userid`)
    )
    INSERT  INTO `trade`(`tradeid`,`userid`,`tradetime`) VALUES (12,1,'2012-11-01 00:00:00'),(13,1,'2012-11-01 00:00:00'),
    (14,1,'2012-11-01 00:00:00')
    ,(15,1,'2012-12-20 00:00:00'),
    (16,1,'2012-12-20 00:00:00');
    
    DROP TABLE IF EXISTS `tradeitem`;
    CREATE TABLE `tradeitem` (
      `itemid` INT(11) NOT NULL AUTO_INCREMENT,
      `bookid` INT(11) DEFAULT NULL,
      `quantity` INT(11) DEFAULT NULL,
      `tradeid` INT(11) DEFAULT NULL,
      PRIMARY KEY  (`itemid`),
      KEY `book_id_fk` (`bookid`),
      KEY `trade_id_fk` (`tradeid`),
      CONSTRAINT `book_id_fk` FOREIGN KEY (`bookid`) REFERENCES `mybooks` (`Id`),
      CONSTRAINT `trade_id_fk` FOREIGN KEY (`tradeid`) REFERENCES `trade` (`tradeid`)
    )
    INSERT  INTO `tradeitem`(`itemid`,`bookid`,`quantity`,`tradeid`) VALUES (22,1,10,12),
    (23,2,10,12),(24,3,10,12),(25,1,1,13),(26,13,2,13),(27,14,3,13),(28,15,4,13),(29,1,1,14),
    (30,13,2,14),(31,14,3,14),(32,15,4,14),(33,22,5,14),(34,23,5,14),(35,24,5,14),(36,2,1,15),
    (37,1,2,15),(38,3,1,15),(39,2,1,16),(40,1,3,16),(41,3,1,16);
    
    DROP TABLE IF EXISTS `userinfo`;
    CREATE TABLE `userinfo` (
      `userid` INT(11) NOT NULL AUTO_INCREMENT,
      `username` VARCHAR(50) DEFAULT NULL,
      `accountid` INT(11) DEFAULT NULL,
      PRIMARY KEY  (`userid`),
      KEY `account_id_fk` (`accountid`),
      CONSTRAINT `account_id_fk` FOREIGN KEY (`accountid`) REFERENCES `account` (`accountid`)
    )
    INSERT  INTO `userinfo`(`userid`,`username`,`accountid`) VALUES (1,'Tom',1),(2,'AAA',1),(3,'BB',1),(4,'CC',1),(5,'DD',1),(6,'EE',1);

    4.搭建环境

    加入 C3P0 数据源

         --加入 jar 包
         --加入配置文件
         --编辑配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <c3p0-config>
    
        <named-config name="javawebapp">
            <!--提供获取连接的四个基本信息 -->
            <!--连接本地主机的话: jbdc:mysql://localhost:3306/test 可写成jbdc:mysql:///test -->
            <property name="driverClass">com.mysql.jdbc.Driver</property>
            <property name="jdbcUrl">jdbc:mysql://localhost:3306/bookstore</property>
            <property name="user">root</property>
            <property name="password">123456</property>
    
    
            <!-- 对数据库连接池管理的基本信息 -->
            <!-- 当数据库连接池中的连接数不够时,c3p0一次向数据库服务器申请的连接数 -->
            <property name="acquireIncrement">5</property>
            <!-- 初始化时的连接数 -->
            <property name="initialPoolSize">10</property>
            <!-- 维护的最少连接数 -->
            <property name="minPoolSize">10</property>
            <!-- 维护的最多的连接数 -->
            <property name="maxPoolSize">100</property>
            <!-- 最多维护的Satement的个数 -->
            <property name="maxStatements">50</property>
            <!-- 每个连接最多使用Statement的个数 -->
            <property name="maxStatementsPerConnection">2</property>
    
        </named-config>
    </c3p0-config>
        

    加入 dbutils 工具类
    加入 JSTL
    其它:使用随时加入

    5.Dao 层设计

     目录结构

    Dao.java

    package com.aff.bookstore.dao;
    
    import java.util.List;
    
    /**
     * Dao 接口, 定义 Dao 的基本操作, 由 BaseDao 提供实现. 
     * @param <T>: Dao 实际操作的泛型类型
     */
    public interface Dao<T> {
        
        /**
         * 执行 INSERT 操作, 返回插入后的记录的 ID
         * @param sql: 待执行的 SQL 语句
         * @param args: 填充占位符的可变参数
         * @return: 插入新记录的 id
         */
        long insert(String sql, Object ... args);
        
        /**
         * 执行 UPDATE 操作, 包括 INSERT(但没有返回值), UPDATE, DELETE
         * @param sql: 待执行的 SQL 语句
         * @param args: 填充占位符的可变参数
         */
        void update(String sql, Object ... args);
        
        /**
         * 执行单条记录的查询操作, 返回与记录对应的类的一个对象
         * @param sql: 待执行的 SQL 语句
         * @param args: 填充占位符的可变参数
         * @return: 与记录对应的类的一个对象
         */
        T query(String sql, Object ... args);
        
        /**
         * 执行多条记录的查询操作, 返回与记录对应的类的一个 List
         * @param sql: 待执行的 SQL 语句
         * @param args: 填充占位符的可变参数
         * @return: 与记录对应的类的一个 List
         */
        List<T> queryForList(String sql, Object ... args);
        
        /**
         * 执行一个属性或值的查询操作, 例如查询某一条记录的一个字段, 或查询某个统计信息, 返回要查询的值
         * @param sql: 待执行的 SQL 语句
         * @param args: 填充占位符的可变参数
         * @return: 执行一个属性或值的查询操作, 例如查询某一条记录的一个字段, 或查询某个统计信息, 返回要查询的值
         */
        <V> V getSingleVal(String sql, Object ... args);
        
        /**
         * 执行批量更新操作
         * @param sql: 待执行的 SQL 语句
         * @param args: 填充占位符的可变参数
         */
        void batch(String sql, Object[]... params);
    }

    BookDAO.java

    package com.aff.bookstore.dao;
    
    import java.util.Collection;
    import java.util.List;
    
    import com.aff.bookstore.domain.Book;
    import com.aff.bookstore.domain.ShoppingCartItem;
    import com.aff.bookstore.web.CriteriaBook;
    import com.aff.bookstore.web.Page;
    
    public interface BookDAO {
    
        /**
         * 根据 id 获取指定 Book 对象
         * @param id
         * @return
         */
        public abstract Book getBook(int id);
    
        /**
         * 根据传入的 CriteriaBook 对象返回对应的 Page 对象
         * @param cb
         * @return
         */
        public abstract Page<Book> getPage(CriteriaBook cb);
    
        /**
         * 根据传入的 CriteriaBook 对象返回其对应的记录数
         * @param cb
         * @return
         */
        public abstract long getTotalBookNumber(CriteriaBook cb);
    
        /**
         * 根据传入的 CriteriaBook 和 pageSize 返回当前页对应的 List 
         * @param cb
         * @param pageNo
         * @param pageSize
         * @return
         */
        public abstract List<Book> getPageList(CriteriaBook cb,int pageSize);
    
        /**
         * 返回指定 id 的 book 的 storeNumber 字段的值
         * @param id
         * @return
         */
        public abstract int getStoreNumber(Integer id);
    
        /**
         * 根据传入的 ShoppingCartItem 的集合, 
         * 批量更新 books 数据表的 storenumber 和 salesnumber 字段的值
         * @param items
         */
        public abstract void batchUpdateStoreNumberAndSalesAmount(
                Collection<ShoppingCartItem> items);
    
    }

    BaseDAO.java

    package com.aff.bookstore.dao.impl;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.Statement;
    import java.util.List;
    
    import org.apache.commons.dbutils.QueryRunner;
    import org.apache.commons.dbutils.handlers.BeanHandler;
    import org.apache.commons.dbutils.handlers.BeanListHandler;
    import org.apache.commons.dbutils.handlers.ScalarHandler;
    
    import com.aff.bookstore.dao.Dao;
    import com.aff.bookstore.db.JDBCUtils;
    import com.aff.bookstore.utils.ReflectionUtils;
    
    public class BaseDAO<T> implements Dao<T> {
        private QueryRunner queryRunner = new QueryRunner();
        private Class<T> clazz;
    
        public BaseDAO() {
            clazz = ReflectionUtils.getSuperGenericType(getClass());
    
        }
    
        @Override
        public long insert(String sql, Object... args) {
            // 我们需要返回它的主键id值
            // update 中的insert 操作没有返回值
            // quertRunner也没有返回值
            // 此时需要使用原生的jdbc写
            long id = 0;
            Connection connection = null;
            PreparedStatement preparedStatement = null;
            ResultSet resultSet = null;
    
            try {
                connection = JDBCUtils.getConnection();
                preparedStatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
    
                if (args != null) {
                    for (int i = 0; i < args.length; i++) {
                        preparedStatement.setObject(i + 1, args[i]);
                    }
                }
                preparedStatement.executeUpdate();
    
                // 获取生成的主键值
                resultSet = preparedStatement.getGeneratedKeys();
                if (resultSet.next()) {
                    id = resultSet.getLong(1);// 第一列主键值 id
                }
    
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                JDBCUtils.release(resultSet, preparedStatement);
                JDBCUtils.release(connection);
            }
            return id;
        }
    
        @Override
        public void update(String sql, Object... args) {
            Connection connection = null;
    
            try {
                connection = JDBCUtils.getConnection();
                queryRunner.update(connection, sql,args);
    
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                JDBCUtils.release(connection);
            }
        }
    
        @Override
        public T query(String sql, Object... args) {
            Connection connection = null;
    
            try {
                connection = JDBCUtils.getConnection();
                return queryRunner.query(connection, sql, new BeanHandler<>(clazz), args);
    
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                JDBCUtils.release(connection);
            }
            return null;
        }
    
        @Override
        public List<T> queryForList(String sql, Object... args) {
            Connection connection = null;
    
            try {
                connection = JDBCUtils.getConnection();
                return queryRunner.query(connection, sql, new BeanListHandler<>(clazz), args);
    
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                JDBCUtils.release(connection);
            }
            return null;
        }
    
        @Override
        public <V> V getSingleVal(String sql, Object... args) {
            Connection connection = null;
    
            try {
                connection = JDBCUtils.getConnection();
                return (V) queryRunner.query(connection, sql, new ScalarHandler(), args);
    
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                JDBCUtils.release(connection);
            }
            return null;
        }
    
        @Override
        public void batch(String sql, Object[]... params) {
            Connection connection = null;
    
            try {
                connection = JDBCUtils.getConnection();
                queryRunner.batch(connection, sql, params);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                JDBCUtils.release(connection);
            }
        }
    }

    BookDaoImpl.java

    package com.aff.bookstore.dao.impl;
    
    import java.util.Collection;
    import java.util.List;
    
    import com.aff.bookstore.dao.BookDAO;
    import com.aff.bookstore.domain.Book;
    import com.aff.bookstore.domain.ShoppingCartItem;
    import com.aff.bookstore.web.CriteriaBook;
    import com.aff.bookstore.web.Page;
    
    public class BookDaoImpl extends BaseDAO<Book> implements BookDAO {
    
        @Override
        public Book getBook(int id) {
            String sql = "select id,    author, title, price ,publishingDate,salesAmount,storeNumber,remark from mybooks where id = ? ";
            return query(sql, id);
        }
    
        @Override
        public Page<Book> getPage(CriteriaBook cb) {
            Page page = new Page<>(cb.getPageNo());
            page.setTotalItemNumber(getTotalBookNumber(cb));
            // 检验 pageNo的合法性
            cb.setPageNo(page.getPageNo());
    
            page.setList(getPageList(cb, 3));
            return page;
        }
    
        // 获取在这个价格区间的有多少条数目
        @Override
        public long getTotalBookNumber(CriteriaBook cb) {
            String sql = "select count(id) from mybooks where price >=? and price <= ? ";
            return getSingleVal(sql, cb.getMinPrice(), cb.getMaxPrice());
        }
    
        @Override
        public List<Book> getPageList(CriteriaBook cb, int pageSize) {
            // 起始从0 开始的,所以 (cb.getPageNo()- 1) *pageSize,pageSize
            String sql = "select id,    author, title, price ,publishingDate,salesAmount,storeNumber,remark  from mybooks where price >=? and price <= ?  limit ?,?";
            return queryForList(sql, cb.getMinPrice(), cb.getMaxPrice(), (cb.getPageNo() - 1) * pageSize, pageSize);
        }
    
        @Override
        public int getStoreNumber(Integer id) {
            String sql = "select storeNumber from mybooks where id = ?";
            return getSingleVal(sql, id);
        }
    
        @Override
        public void batchUpdateStoreNumberAndSalesAmount(Collection<ShoppingCartItem> items) {
    
        }
    }
    All that work will definitely pay off
  • 相关阅读:
    Longest Subsequence CodeForces
    Alyona and towers CodeForces
    Electric Charges CodeForces
    Array GCD CodeForces
    笔记(模拟)
    城堡 (spfa+cheng)
    YOU ARE MY SUNSHINE
    AC日记——潜伏者 洛谷 P1071 (模拟)
    AC日记——神奇的幻方 洛谷 P2615(大模拟)
    AC日记——机器翻译 洛谷 P1540
  • 原文地址:https://www.cnblogs.com/afangfang/p/12907961.html
Copyright © 2011-2022 走看看