Java Web基础入门第八十八讲 在线网上书店(三)——编写dao层
发布日期:2021-06-30 18:04:24 浏览次数:2 分类:技术文章

本文共 18444 字,大约阅读时间需要 61 分钟。

编写dao层

编写CategoryDao

我们首先开发出分类管理模块中的dao层,在cn.liayun.dao包下创建一个CategoryDao接口,接口的具体代码如下:

package cn.liayun.dao;import java.util.List;import cn.liayun.domain.Category;public interface CategoryDao {
void add(Category c); Category find(String id); List
getAll();}

接下来,我们就要编写该接口的具体实现类了,在cn.liayun.dao.impl包下创建CategoryDao接口的实现类——CategoryDaoImpl.java。

package cn.liayun.dao.impl;import java.sql.Connection;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 cn.liayun.dao.CategoryDao;import cn.liayun.domain.Category;import cn.liayun.utils.JdbcUtils;public class CategoryDaoImpl implements CategoryDao {
@Override public void add(Category c) {
try {
Connection conn = JdbcUtils.getConnection();//必定获取到的是当前线程上开启事务的连接 QueryRunner runner = new QueryRunner(); String sql = "insert into category(id,name,description) values(?,?,?)"; Object[] params = {
c.getId(), c.getName(), c.getDescription()}; runner.update(conn, sql, params); } catch (Exception e) {
throw new RuntimeException(e); } } @Override public Category find(String id) {
try {
Connection conn = JdbcUtils.getConnection();//必定获取到的是当前线程上开启事务的连接 QueryRunner runner = new QueryRunner(); String sql = "select * from category where id=?"; return runner.query(conn, sql, id, new BeanHandler
(Category.class)); } catch (Exception e) {
throw new RuntimeException(e); } } @Override public List
getAll() {
try {
Connection conn = JdbcUtils.getConnection();//必定获取到的是当前线程上开启事务的连接 QueryRunner runner = new QueryRunner(); String sql = "select * from category"; return runner.query(conn, sql, new BeanListHandler
(Category.class)); } catch (Exception e) {
throw new RuntimeException(e); } } }

该类真的算是比较简单了,也好写。

编写BookDao

用户进入前台首页的时候,就能看到图书的信息,这些图书的信息是从数据库里面查询出来的,一个在线网上书店的图书可能成千上百,所以,在查询图书的时候,一定得要分页,除此之外,如果上层带了查询条件过来,那么就需要获得该查询条件下的分页数据。

这样,我们还得创建出实现分页显示的三个对象。首先在cn.liayun.domain包下创建QueryInfo类,用于封装用户的请求参数。该类的具体代码如下:

package cn.liayun.domain;//封装查询信息public class QueryInfo {
private int currentpage = 1; private int pagesize = 4; private int startindex; private String queryname;//带查询条件过来,查看某个分类下面的分页数据,例如category_id private String queryvalue;//查询条件的值,查看3号分类下面的分页数据,例如category_id=3 private String where;//使用上面两个带过来的东西组装成一个查询条件,例如where = "where category_id = ?" public int getCurrentpage() {
return currentpage; } public void setCurrentpage(int currentpage) {
this.currentpage = currentpage; } public int getPagesize() {
return pagesize; } public void setPagesize(int pagesize) {
this.pagesize = pagesize; } public int getStartindex() {
this.startindex = (this.currentpage - 1) * this.pagesize; return startindex; } public String getQueryname() {
return queryname; } public void setQueryname(String queryname) {
this.queryname = queryname; } public String getQueryvalue() {
return queryvalue; } public void setQueryvalue(String queryvalue) {
this.queryvalue = queryvalue; } public String getWhere() {
if (this.queryname == null || this.queryname.trim().equals("")) {
return ""; } else {
//this.where = "where category_id=?" this.where = "where " + this.queryname + "=?"; } return where; } }

然后在cn.liayun.domain包下创建QueryResult类,用于封装查询结果。该类的具体代码如下:

package cn.liayun.domain;import java.util.List;public class QueryResult {
//普通JavaBean private List
list; private int totalrecord; public List
getList() {
return list; } public void setList(List
list) {
this.list = list; } public int getTotalrecord() {
return totalrecord; } public void setTotalrecord(int totalrecord) {
this.totalrecord = totalrecord; }}

最后,在cn.liayun.domain包下创建PageBean类。该类用于将QueryResult对象中封装的查询结果,生成显示分页数据的PageBean对象。

package cn.liayun.domain;import java.util.List;public class PageBean {
private List
list; private int totalrecord; private int pagesize; private int totalpage; private int currentpage; private int previouspage; private int nextpage; private int[] pagebar; public List
getList() {
return list; } public void setList(List
list) {
this.list = list; } public int getTotalrecord() {
return totalrecord; } public void setTotalrecord(int totalrecord) {
this.totalrecord = totalrecord; } public int getPagesize() {
return pagesize; } public void setPagesize(int pagesize) {
this.pagesize = pagesize; } public int getTotalpage() {
if (this.totalrecord % this.pagesize == 0) {
this.totalpage = this.totalrecord / this.pagesize; } else {
this.totalpage = this.totalrecord / this.pagesize + 1; } return totalpage; } public int getCurrentpage() {
return currentpage; } public void setCurrentpage(int currentpage) {
this.currentpage = currentpage; } public int getPreviouspage() {
if ((this.currentpage - 1) > 1) {
this.previouspage = this.currentpage - 1; } else {
this.previouspage = 1; } return previouspage; } public int getNextpage() {
if ((this.currentpage + 1) > this.totalpage) {
this.nextpage = this.totalpage; } else {
this.nextpage = this.currentpage + 1; } return nextpage; } public int[] getPagebar() {
int startpage;//页码条的起始页 int endpage;//页码条的结束页 if (this.totalpage <= 10) {
startpage = 1; endpage = this.totalpage; } else {
startpage = this.currentpage - 4; endpage = this.currentpage + 5; if (startpage < 1) {
startpage = 1; endpage = 10; } if (endpage > this.totalpage) {
endpage = this.totalpage; startpage = this.totalpage - 9; } } this.pagebar = new int[endpage - startpage + 1]; int index = 0; for (int i = startpage; i <= endpage; i++) {
this.pagebar[index++] = i; } return pagebar; } }

接下来,我们开始编写出图书管理模块中的dao层。在cn.liayun.dao包下创建一个BookDao接口,接口的具体代码如下:

package cn.liayun.dao;import java.util.List;import cn.liayun.domain.Book;import cn.liayun.domain.QueryResult;public interface BookDao {
void add(Book b); Book find(String id); //查找图书的分页数据(图书一般来说有很多,所以要分页。除此之外,如果上层带了查询条件过来,那么就需要获得该查询条件下的分页数据) QueryResult pageQuery(int startindex, int pagesize, String where, Object param); public List
getAll();}

接下来,我们就要编写该接口的具体实现类了,在cn.liayun.dao.impl包下创建BookDao接口的实现类——BookDaoImpl.java。

package cn.liayun.dao.impl;import java.sql.Connection;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 cn.liayun.dao.BookDao;import cn.liayun.domain.Book;import cn.liayun.domain.QueryResult;import cn.liayun.utils.JdbcUtils;public class BookDaoImpl implements BookDao {
@Override public void add(Book b) {
try {
Connection conn = JdbcUtils.getConnection(); QueryRunner runner = new QueryRunner(); String sql = "insert into book(id,name,price,author,image,description,category_id) values(?,?,?,?,?,?,?)"; Object[] params = {
b.getId(), b.getName(), b.getPrice(), b.getAuthor(), b.getImage(), b.getDescription(), b.getCategory().getId()}; runner.update(conn, sql, params); } catch (Exception e) {
throw new RuntimeException(e); } } @Override public Book find(String id) {
try {
Connection conn = JdbcUtils.getConnection(); QueryRunner runner = new QueryRunner(); String sql = "select * from book where id=?"; return runner.query(conn, sql, id, new BeanHandler
(Book.class)); } catch (Exception e) {
throw new RuntimeException(e); } } //书在找的时候,一定要分页 /* * 用户带where条件过来,则该方法返回分类下面的分页数据; * 如果没有带where条件过来,则该方法返回所有书的分页数据 * * where条件的书写格式:String where = "where category_id = ?" */ private List
getPageData(int startindex, int pagesize, String where, Object param) {
try {
Connection conn = JdbcUtils.getConnection(); QueryRunner runner = new QueryRunner(); if (where == null || where.trim().equals("")) {
//返回所有书的分页数据 String sql = "select * from book limit ?,?"; Object[] params = {
startindex, pagesize}; return runner.query(conn, sql, params, new BeanListHandler
(Book.class)); } else {
//如果上层带了查询条件过来,那么就需要获得该查询条件下的分页数据 String sql = "select * from book " + where + " limit ?,?"; Object[] params = {
param, startindex, pagesize}; return runner.query(conn, sql, params, new BeanListHandler
(Book.class)); } } catch (Exception e) {
throw new RuntimeException(e); } } //分页的时候,获得总记录数 private int getPageTotalRecord(String where, Object param) {
try {
Connection conn = JdbcUtils.getConnection(); QueryRunner runner = new QueryRunner(); if (where == null || where.trim().equals("")) {
String sql = "select count(*) from book"; return runner.query(conn, sql, new ScalarHandler
()).intValue(); } else {
String sql = "select count(*) from book " + where; return runner.query(conn, sql, param, new ScalarHandler
()).intValue(); } } catch (Exception e) { throw new RuntimeException(e); } } @Override public QueryResult pageQuery(int startindex, int pagesize, String where, Object param) { List
list = getPageData(startindex, pagesize, where, param); int totalrecord = getPageTotalRecord(where, param); QueryResult result = new QueryResult(); result.setList(list); result.setTotalrecord(totalrecord); return result; } public List
getAll() { try { Connection conn = JdbcUtils.getConnection(); QueryRunner runner = new QueryRunner(); String sql = "select * from book"; return runner.query(conn, sql, new BeanListHandler
(Book.class)); } catch (Exception e) { throw new RuntimeException(e); } }}

编写OrderDao

该项目设计中最难的地方就是订单管理模块这里了。在cn.liayun.dao包下创建一个OrderDao接口,接口的具体代码如下:

package cn.liayun.dao;import java.util.List;import cn.liayun.domain.Order;public interface OrderDao {
void add(Order o); /* * 最麻烦的一个方法 * 这个方法要把Order对象的基本信息找回来,还要把用户的信息找回来,还要把多个订单项的信息找回来。 * 那么就要查找4张表。 * */ Order find(String id); /* * 查看已经发货或没发货的订单信息 * * status为true,表示已发货 * status为false,表示未发货 */ List
getAll(boolean status); //更新订单状态 public void update(String id, boolean status);}

接下来,我们就要编写该接口的具体实现类了,在cn.liayun.dao.impl包下创建OrderDao接口的实现类——OrderDaoImpl.java。

package cn.liayun.dao.impl;import java.sql.Connection;import java.util.List;import java.util.Set;import org.apache.commons.dbutils.QueryRunner;import org.apache.commons.dbutils.handlers.BeanHandler;import org.apache.commons.dbutils.handlers.BeanListHandler;import cn.liayun.dao.OrderDao;import cn.liayun.domain.Book;import cn.liayun.domain.Order;import cn.liayun.domain.OrderItem;import cn.liayun.domain.User;import cn.liayun.utils.JdbcUtils;//难点public class OrderDaoImpl implements OrderDao {
@Override public void add(Order o) {
try {
Connection conn = JdbcUtils.getConnection(); QueryRunner runner = new QueryRunner(); //保存订单的基本信息 String sql = "insert into orders(id,ordertime,status,price,user_id) values(?,?,?,?,?)"; Object[] params = {
o.getId(), o.getOrdertime(), o.isStatus(), o.getPrice(), o.getUser().getId()}; runner.update(conn, sql, params); //再保存多个订单项的基本信息 Set
set = o.getOrderitems(); for (OrderItem item : set) {
sql = "insert into orderitem(id,quantity,price,book_id,order_id) values(?,?,?,?,?)"; params = new Object[]{
item.getId(), item.getQuantity(), item.getPrice(), item.getBook().getId(), o.getId()}; runner.update(conn, sql, params); } } catch (Exception e) {
throw new RuntimeException(e); } } /* * 最麻烦的一个方法 * 这个方法要把Order对象的基本信息找回来,还要把用户的信息找回来,还要把多个订单项的信息找回来。 * 那么就要查找4张表。 * */ @Override public Order find(String id) {
try {
Connection conn = JdbcUtils.getConnection(); QueryRunner runner = new QueryRunner(); //找出订单的基本信息 String sql = "select * from orders where id=?"; Order order = runner.query(conn, sql, new BeanHandler
(Order.class), id); //找出订单中的每一个订单项 sql = "select * from orderitem where order_id=?"; List
list = runner.query(conn, sql, new BeanListHandler
(OrderItem.class), id); //找出每一个订单项代表的每本书(涉及到多表查询) for (OrderItem item : list) {
sql = "select b.* from orderitem oi,book b where oi.id=? and b.id=oi.book_id"; Book book = runner.query(conn, sql, new BeanHandler
(Book.class), item.getId()); item.setBook(book); } order.getOrderitems().addAll(list); //找出下订单的人(涉及到多表查询) sql = "select u.* from orders o,user u where o.id=? and u.id=o.user_id"; User user = runner.query(conn, sql, new BeanHandler
(User.class), id); order.setUser(user); return order; } catch (Exception e) { throw new RuntimeException(e); } } /* * 查看已经发货或没发货的订单信息 * * status为true,表示已发货 * status为false,表示未发货 */ @Override public List
getAll(boolean status) { try { Connection conn = JdbcUtils.getConnection(); QueryRunner runner = new QueryRunner(); String sql = "select * from orders where status=?"; List
list = runner.query(conn, sql, new BeanListHandler
(Order.class), status); //找出每一个订单的下单人 for (Order o : list) { sql = "select u.* from orders o,user u where o.id=? and u.id=o.user_id"; User user = runner.query(conn, sql, new BeanHandler
(User.class), o.getId()); o.setUser(user); } return list; } catch (Exception e) { throw new RuntimeException(e); } } //更新订单状态 public void update(String id, boolean status) { try { Connection conn = JdbcUtils.getConnection(); QueryRunner runner = new QueryRunner(); String sql = "update orders set status=? where id=?"; Object[] parmas = { status, id}; runner.update(conn, sql, parmas); } catch (Exception e) { throw new RuntimeException(e); } }}

该类中除了更新订单状态的update方法比较简单之外,其余的方法都挺麻烦的,尤其是find方法,这个方法要把Order对象的基本信息找回来,还要把用户的信息找回来,还要把多个订单项的信息找回来,不可避免就要查找4张表。

其次,add方法也很麻烦,它是将所有数据都封装到Order对象上,然后取出数据,把数据插入到数据表中。其实,我们的Order和OrderItem的操作可以分开。OrderItem也可以另外编写一个dao,那么我们在插入完Order对象之后,得到Order对象返回的主键,再调用OrderItemDaoImpl的方法来插入OrderItem的数据,这样我觉得会让代码更清晰一些。在OrderItemDaoImpl中接收的是一个List<OrderItem>,因为我们一个订单会对应多个订单项。

编写UserDao

最后,我们来编写用户管理模块中的dao层。在cn.liayun.dao包下创建一个UserDao接口,接口的具体代码如下:

package cn.liayun.dao;import cn.liayun.domain.User;public interface UserDao {
void add(User user); User find(String id); User find(String username, String password);}

接下来,我们就要编写该接口的具体实现类了,在cn.liayun.dao.impl包下创建UserDao接口的实现类——UserDaoImpl.java。

package cn.liayun.dao.impl;import java.sql.Connection;import org.apache.commons.dbutils.QueryRunner;import org.apache.commons.dbutils.handlers.BeanHandler;import cn.liayun.dao.UserDao;import cn.liayun.domain.User;import cn.liayun.utils.JdbcUtils;public class UserDaoImpl implements UserDao {
@Override public void add(User user) {
try {
Connection conn = JdbcUtils.getConnection(); QueryRunner runner = new QueryRunner(); String sql = "insert into user(id,username,password,phone,cellphone,email,address) values(?,?,?,?,?,?,?)"; Object[] params = {
user.getId(), user.getUsername(), user.getPassword(), user.getPhone(), user.getCellphone(), user.getEmail(), user.getAddress()}; runner.update(conn, sql, params); } catch (Exception e) {
throw new RuntimeException(e); } } @Override public User find(String id) {
try {
Connection conn = JdbcUtils.getConnection(); QueryRunner runner = new QueryRunner(); String sql = "select * from user where id=?"; return runner.query(conn, sql, id, new BeanHandler
(User.class)); } catch (Exception e) {
throw new RuntimeException(e); } } @Override public User find(String username, String password) {
try {
Connection conn = JdbcUtils.getConnection(); QueryRunner runner = new QueryRunner(); String sql = "select * from user where username=? and password=?"; return runner.query(conn, sql, new Object[]{
username, password}, new BeanHandler
(User.class)); } catch (Exception e) {
throw new RuntimeException(e); } }}

该类也算是比较简单的了,也好写。

测试dao层

开发完数据访问层,一定要对程序已编写好的部分代码进行测试,做一步,测试一步,以免整个程序完成后由于页面太多或者是代码量太大给查找错误造成更大的负担!

由于数据库表中都没有数据,所以,为了方便下面进行测试,可以使用如下sql语句向数据库表中插入一些假数据。

insert into category(id,name,description) values('1','技术书籍','技术书籍');insert into category(id,name,description) values('2','武侠小说','武侠小说');insert into book(id,name,price,author,image,description,category_id) values('1','Java Web开发','100','老张','1.jpg','Java Web开发','1');insert into book(id,name,price,author,image,description,category_id) values('2','JDBC开发','10','老张','2.jpg','JDBC开发','1');insert into book(id,name,price,author,image,description,category_id) values('3','JavaScript开发','1','老张','3.jpg','JavaScript开发','1');insert into book(id,name,price,author,image,description,category_id) values('4','Spring源码解析','18','李阿昀','4.jpg','Spring源码解析','1');insert into user(id,username,password,phone,cellphone,email,address) values('1','liayun','123','15071339999','13773458989','liayun@163.com','广州黄埔');insert into orders(id,ordertime,status,price,user_id) values('1','2019-04-30 23:34:32','0','89','1');insert into orderitem(id,quantity,price,book_id,order_id) values('1','89','12','1','1');insert into orderitem(id,quantity,price,book_id,order_id) values('2','3','45','2','1');

现在,在juint.test包下创建出一个BookDaoTest类,该类的具体代码如下:

package junit.test;import org.junit.Test;import cn.liayun.dao.BookDao;import cn.liayun.dao.impl.BookDaoImpl;import cn.liayun.domain.Book;import cn.liayun.domain.Category;import cn.liayun.utils.JdbcUtils;public class BookDaoTest {
@Test public void testQuery() {
BookDao dao = new BookDaoImpl(); dao.pageQuery(0, 2, "", 1);//作断点调试 } @Test public void testAddBook() {
Book book = new Book(); book.setAuthor("无名氏"); book.setDescription("什么鬼啊!"); book.setId("5"); book.setImage("5.jpg"); book.setName("醉拳甘乃迪"); book.setPrice(99); book.setCategory(new Category()); BookDao dao = new BookDaoImpl(); dao.add(book); JdbcUtils.commitTransaction();//自己做测试时,一定要记得提交事务 }}

接着在juint.test包下创建了一个OrderDaoTest类,该类的具体代码如下:

package junit.test;import org.junit.Test;import cn.liayun.dao.OrderDao;import cn.liayun.dao.impl.OrderDaoImpl;public class OrderDaoTest {
@Test public void testFind() {
OrderDao dao = new OrderDaoImpl(); dao.find("1");//作断点调试 } }

从上面可以看到,我们只对图书管理模块和订单管理模块中的dao层代码进行了测试,如果大家有时间的话,最好对每一个模块dao层中的每一个方法进行测试,确保编写的dao层准确无误!

转载地址:https://liayun.blog.csdn.net/article/details/91168005 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Java Web基础入门第八十九讲 在线网上书店(四)——编写service层
下一篇:Java Web基础入门第八十七讲 在线网上书店(二)——设计实体及其相对应的数据库表

发表评论

最新留言

关注你微信了!
[***.104.42.241]2024年04月17日 14时19分52秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

MMOCR——config文件 2019-04-30
NCCL 2019-04-30
pip install git+ 2019-04-30
UGC 用户产生内容 2019-04-30
ranger 2019-04-30
slurm 2019-04-30
xfce4 2019-04-30
xrdp 2019-04-30
Raft算法 2019-04-30
Python计算文本BLEU分数 2019-04-30
swap内存(linux) 2019-04-30
人脸au 2019-04-30
torch.distributed 分布式 2019-04-30
OpenMP编程模型(OMP) 2019-04-30
混合精度训练(FP16 & FP32) 2019-04-30
PyPy 2019-04-30
打印CSDN文章 2019-04-30
MATLAB与CUDA 2019-04-30
Linux png转jpg (convert命令) 2019-04-30
NAS (Network Attached Storage 网络附属存储) 2019-04-30