(一)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) { }
}
(一)DAO设计及BaseDAO和BookDAO的实现的更多相关文章
- SpringJdbc持久层封装,Spring jdbcTemplate封装,springJdbc泛型Dao,Spring baseDao封装
SpringJdbc持久层封装,Spring jdbcTemplate封装,springJdbc泛型Dao,Spring baseDao封装 >>>>>>>& ...
- JPA的泛型DAO设计及使用
使用如Hibernate或者JPA作为持久化的解决方案时,设计一个泛型的DAO抽象父类可以方便各个实体的通用CRUD操作.由于此时大部分实体DAO的CRUD操作基本一样,采用泛型设计解决这个问题,带来 ...
- Dao层抽取BaseDao公共方法
设计IBseDao接口,定义公共的CRUD方法. // IBaseDao 接口,定义公共的CRUD方法 public interface IBaseDao<T> { public void ...
- 针对Student表的DAO设计实例
完整代码以及junit,mysql--connector包下载地址 : https://github.com/CasterWx/MyStudentDao 表信息: 代码: dao包----impl包- ...
- Java秒杀简单设计二:数据库表和Dao层设计
Java秒杀简单设计二:数据库表Dao层设计 上一篇中搭建springboot项目环境和设计数据库表 https://www.cnblogs.com/taiguyiba/p/9791431.html ...
- JDBC中DAO+service设计思想
一.DAO设计思想 a) Data access Object(数据访问对象):前人总结出的一种固定模式的设计思想. 高可读性. 高复用性. 高扩展性. b) JDBC代码实现的增删改查操作是有复用需 ...
- OA项目笔记-从建立接口 dao impl action jsp等框架实现crud
1,设计 BaseDao 与 BaseDaoImpl 1,设计接口 BaseDao 1,每个实体都应有一个对应的Dao接口,封装了对这个实体的数据库操作.例 实体 Dao接口 实现类 ======== ...
- Dao模型设计(基于Dao与Hebernate框架)
以前没有Dao设计模型之前,一般都是这样的流程: ①先设计实体对象 学生对象: package com.itheima.domain; import java.io.Serializable; imp ...
- 从0开始学习ssh之basedao
用于所有dao里边会有许多相同的方法,例如save,update等等.应此设计一个basedao,所有dao都继承它.这样可以省去许多工作量. basedao如下 package cn.itcast. ...
随机推荐
- Java——多线程锁的那些事
引入 Java提供了种类丰富的锁,每种锁因其特性的不同,在适当的场景下能够展现出非常高的效率. 下面先带大家来总体预览一下锁的分类图 1.乐观锁 VS 悲观锁 乐观锁与悲观锁是一种广义上的概念,体现了 ...
- opencv基于PCA降维算法的人脸识别
opencv基于PCA降维算法的人脸识别(att_faces) 一.数据提取与处理 # 导入所需模块 import matplotlib.pyplot as plt import numpy as n ...
- D. Beautiful Array DP
https://codeforces.com/contest/1155/problem/D 这个题目还是不会写,挺难的,最后还是lj大佬教我的. 这个题目就是要分成三段来考虑, 第一段就是不进行乘,就 ...
- c语言中的malloc函数
少壮不努力,大一的时候c语言学得不扎实,最近学数据结构的时候看到c语言中malloc函数都不知道了,这里记录一下,避免以后再忘. malloc的全称是memory allocation,中文叫动态内存 ...
- 3、Hive-sql优化,数据倾斜处理
一.Hive-sql优化 #增加reducer任务数量(拉取数量分流) ; #在同一个sql中的不同的job是否可以同时运行,默认为false set hive.exec.parallel=true; ...
- 真正免费,不限页数的PDF转Word工具
真正免费,不限页数的PDF转Word工具 我们知道PDF转Word工具非常多,但大部分都有各种限制,限大小,限页数,加水印等等. 这其中绝大部分其实并不能做到格式完全一样,遇到图片更是直接傻了. 我们 ...
- [ACdream 1212 New Year Bonus Grant]贪心
题意:员工之间形成一棵树,上级可以给下级发奖金,任何一个人最多可以给一个下级发,并且发了奖金后就不能接受奖金.求总共最多可以产生多少的奖金流动 思路:每次选择没有下级并且有上级的员工a,令它的上级为b ...
- [hdu5358]分类统计,利用单调性优化
题意:直接来链接吧http://acm.hdu.edu.cn/showproblem.php?pid=5358 思路:注意S(i,j)具有区间连续性且单调,而⌊log2x⌋具有区间不变性,于是考虑枚举 ...
- 在ef core中使用postgres数据库的全文检索功能实战之中文支持
前言 有关通用的postgres数据库全文检索在ef core中的使用方法,参见我的上一篇文章. 本文实践了zhparser中文插件进行全文检索. 准备工作 安装插件,最方便的方法是直接使用安装好插件 ...
- Rasa init报错:AttributeError: type object 'Callable' has no attribute '_abc_registry'
错误:Rasa init --no-prompt 报错 原因:Python升级到3.7后会遇到该问题 解决:pip uninstall typing