最近跟着视频做了一个购书网站的小项目,有必要总结一下。代码中用到c3p0和BeanUtils
1.购物车
首先得根据对购物车类进行封装。经过分析,将多种物品添加到购物车中后,购物车中就不止一个购物项了,而每个购物项又有图书的信息,所以在此对购物车提取出两个类;一个是Cart类,用来存放购物项,以便将购物项放置到session中,并对购物车进行操作,而CartItem类用来封装购物项的。
Cart.java代码如下:
package cn.my.bookstore.cart;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
/***
* 购物车类 添加到购物车,从购物车中移除,清空购物车
* @author wulaoern
*
*/
public class Cart {
//存放购物项用map的好处是,可以用bid当作键值,这样方便查找。
private Map<String ,CartItem> map=new LinkedHashMap<String, CartItem>();
private BigDecimal total=new BigDecimal(0); //总价
/**
* 添加购物车
* @param carItem
*/
public BigDecimal getTotal()
{
return total;
}
/**
* 获得购物项集合
* @return
*/
public Collection<CartItem> getCartItems()
{
return map.values();
}
public void add(CartItem cartItem)
{
/**
* 先找到该数是否存在,如果存在,更新数量,不存在,添加进去购物车,同时更新总价
*/
String bid=cartItem.getBook().getBid();
if (map.containsKey(bid)){
//如果购物车中包含该购物项,更新数量
//购物车中原来的购物项
CartItem _cartItem=map.get(bid);
//更新购物车中购物项的数量,不用担心小计,自动更新
_cartItem.setCount(_cartItem.getCount()+cartItem.getCount());
}
else
{
map.put(bid, cartItem);
}
//更新购物车总价
total=total.add(cartItem.getSubtotal());
}
/**
* 从购物车中移除购物项
* @param bid 书号
*/
public void remove(String bid)
{
/*
* 将购物项移除,更新总价
*/
CartItem cartItem=map.remove(bid);
total=total.subtract(cartItem.getSubtotal());
}
/***
* 清空购物车
*/
public void clear()
{
map.clear();
total=new BigDecimal(0);
}
}
CartItem.java代码如下:
package cn.my.bookstore.cart;
import java.math.BigDecimal;
import cn.my.bookstore.book.Book;
/***
* 购物项 由书,数量,小计算出来
* @author wulaoern
*
*/
public class CartItem {
private Book book;//图书类,在数据库中,
private int count; //数量
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public BigDecimal getSubtotal() {
return book.getPrice().multiply(new BigDecimal(count));
}
}
在CartItem中用到了一个Book类,在此把代码贴出来:
package cn.my.bookstore.book;
import java.math.BigDecimal;
import cn.my.bookstore.category.Category;
public class Book {
/*
* `bid` char(32) NOT NULL,
`bname` varchar(100) DEFAULT NULL,
`price` decimal(10,2) DEFAULT NULL,
`author` varchar(50) DEFAULT NULL,
`image` varchar(200) DEFAULT NULL,
`cid` char(32) DEFAULT NULL,
`isdel` tinyint(1) DEFAULT NULL,
*/
private String bid;
private String bname;
private BigDecimal price=new BigDecimal(0);
private String author;
private String image;
/*
* 因为分类与图书是一对多 数据库中存的是关系
* 所以需要在多的一方 图书方 创建一个字段与 分类一方 的主键对应.
* 现在Java语言 是面向对象的.所以说在Book类中存的是Category的对象. ORM
* O:Object R:Relation M:Mapping --- Hibernate
*/
private Category category;
private int isdel;
public String getBid() {
return bid;
}
public void setBid(String bid) {
this.bid = bid;
}
public String getBname() {
return bname;
}
public void setBname(String bname) {
this.bname = bname;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
public int getIsdel() {
return isdel;
}
public void setIsdel(int isdel) {
this.isdel = isdel;
}
}
购物车的封装类做好了,就该做购物车了,
添加到购物车
在网站前台,将图书bid和购买数量传到servlet中,servlet通过bid获得将该图书对象,之后将图书对象和购买数量封装到CartItem对象中。从session中获得cart,注意,此处应判断session中是否存在cart,之后调用cart类的add()方法进行将物品添加到购物车。
其他
而购车的购物项的删除与清空就根据cart类中提供的方法传递参数进行操作就可以了。
2.订单
订单需要根据数据库中的信息进行提取。根据分析,一个订单中不只一个订单项,同样有两个类order类和orderItem类。OrderItem类用来封装订单中的具体的订单项,也就是图书信息。而Order类用来存放OrderItem.
OrderItem.java如下:
package cn.my.bookstore.order;
import java.math.BigDecimal;
import cn.my.bookstore.book.Book;
/**
* 订单项类
* CREATE TABLE `orderitem` (
`itemid` char(32) NOT NULL,
`count` int(11) DEFAULT NULL,
`subtotal` decimal(10,2) DEFAULT NULL,
`bid` char(32) DEFAULT NULL,
`oid` char(32) DEFAULT NULL,
PRIMARY KEY (`itemid`),
KEY `bid` (`bid`),
KEY `oid` (`oid`),
CONSTRAINT `orderitem_ibfk_1` FOREIGN KEY (`bid`) REFERENCES `book` (`bid`),
CONSTRAINT `orderitem_ibfk_2` FOREIGN KEY (`oid`) REFERENCES `orders` (`oid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
* @author wulaoern
*
*/
public class OrderItem {
private String itemId;
private int count;
private BigDecimal subTotal=new BigDecimal(0); //小计,即钱
private Book book;
private Order order;
public String getItemId() {
return itemId;
}
public void setItemId(String itemId) {
this.itemId = itemId;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public BigDecimal getSubTotal() {
return subTotal;
}
public void setSubTotal(BigDecimal subTotal) {
this.subTotal = subTotal;
}
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
}
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
}
Order.java如下
package cn.my.bookstore.order;
import java.math.BigDecimal;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import cn.my.bookstore.cart.CartItem;
import cn.my.bookstore.user.User;
/**
* 订单类
* CREATE TABLE `orders` (
`oid` char(32) NOT NULL,
`total` decimal(10,2) DEFAULT NULL,
`ordertime` timestamp,
`state` int(11) DEFAULT NULL,
`address` varchar(100) DEFAULT NULL,
`uid` char(32) DEFAULT NULL,
PRIMARY KEY (`oid`),
KEY `uid` (`uid`),
CONSTRAINT `orders_ibfk_1` FOREIGN KEY (`uid`) REFERENCES `user` (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
* @author wulaoern
*
*/
public class Order {
private String oid;
private BigDecimal total=new BigDecimal(0);
private Date orderTime;
private String address;
private User user;
private int state;
//因为需要通过订单号差查询订单项,而一个订单包括很多订单项,所以将订单项也进行封装
private Set<OrderItem> orderItems=new LinkedHashSet<OrderItem>();
public void addOrdertItem(OrderItem orderItem)
{
orderItems.add(orderItem);
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public String getOid() {
return oid;
}
public void setOid(String oid) {
this.oid = oid;
}
public BigDecimal getTotal() {
return total;
}
public void setTotal(BigDecimal total) {
this.total = total;
}
public Date getOrderTime() {
return orderTime;
}
public void setOrderTime(Date orderTime) {
this.orderTime = orderTime;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Set<OrderItem> getOrderItems() {
return orderItems;
}
public void setOrderItems(Set<OrderItem> orderItems) {
this.orderItems = orderItems;
}
}
下订单
这里做的下订单是一次性将购物车中的所有购物项下订单。
在点击下订单时候,在servlet中对数据进行封装,注意cart和user都是从session中获得的,这里也可以理解为将cartItem转到orderItem中
/*******************封装订单**********************/
Order order=new Order();
order.setOid(CommonsUUID.getUUID()); //这个方法是获取随机字符串作为id
order.setTotal(cart.getTotal());
order.setUser(user);
order.setState(1);//1代表未付款
/*******************封装订单项**************/
//因为一个订单中不止一个订单项,订单项从购物车中得到,之后将每一个订单项封装
for (CartItem cartItem : cart.getCartItems()) {
OrderItem orderItem=new OrderItem();
orderItem.setBook(cartItem.getBook());
orderItem.setCount(cartItem.getCount());
orderItem.setItemId(CommonsUUID.getUUID());
orderItem.setSubTotal(cartItem.getSubtotal());
order.addOrdertItem(orderItem);
}
经过这样一搞,order对象就满载订单项了,可以向下一层进行操作了。
在dao中,需要对两个表进行插入操作了,orders表和orderitem表。
public void addOrder(Order order) throws SQLException {
QueryRunner qr=new QueryRunner(JdbcUtils.getDataSource());
String sql="insert into orders values (?,?,null,?,?,?)";
Object[] param={order.getOid(),order.getTotal(),order.getState(),
order.getAddress(),order.getUser().getUid()};
qr.update(sql,param);
for (OrderItem orderItem : order.getOrderItems()) {
String sql2="insert into orderitem values (?,?,?,?,?)";
Object[] param2={orderItem.getItemId(),orderItem.getCount(),orderItem.getSubTotal(),
orderItem.getBook().getBid(),order.getOid()};
qr.update(sql2, param2);
}
这样一来,两个表中就有了订单数据了。
但是在下订单之后需要立马显示该次订单信息。所以还得到数据库中查找该订单信息,这个订单还是热的,比较容易查找,通过订单号oid就可以轻松找到详细信息。
public Order findOrderByOid(String oid) throws SQLException, IllegalAccessException, InvocationTargetException {
QueryRunner qr=new QueryRunner(JdbcUtils.getDataSource());
String sql="select * from orders where oid=?";
//按照订单号查询了订单信息,并进行封装,还缺少订单项,但是并不完整,还需要继续封装
Order order=qr.query(sql, new BeanHandler<Order>(Order.class),oid);
//order中还得继续封装orderItem而每一个订单有至少一个订单项,订单项中也还得封装图书,按照功能需求来讲,
//下完订单后,得将本次订单的所有订单项详情显示
String sql2="select * from orderitem o,book b where o.bid=b.bid and oid=?";
//将所有的数据存到了一个list中,而list中存放的是订单项的map信息
List<Map<String, Object>> mapList=qr.query(sql2, new MapListHandler(),oid);
//循环进行封装
for (Map<String, Object> map : mapList) {
//先封装书
Book book=new Book();
BeanUtils.populate(book, map);
//封装订单项
OrderItem orderItem=new OrderItem();
BeanUtils.populate(orderItem, map);
orderItem.setBook(book);
//继续封装order
order.addOrdertItem(orderItem);
}
return order;
}
这样一来就又获得了order对象,随便对他进行操作吧。
查看我的订单
其实查看我的订单只需要用户id uid就可以。之后根据数据库中表之间的连接将数据获取出来
public List<Order> findMyOrders(String uid) throws Exception {
List <Order> orders=new ArrayList<Order>();
QueryRunner qr=new QueryRunner(JdbcUtils.getDataSource());
//先根据用户ID查询出用户的订单信息,每个用户不只一个订单
String sql="select * from orders where uid=?";
List<Map<String, Object>> maplist= qr.query(sql, new MapListHandler(),uid);
for (Map<String, Object> map : maplist) {
//获取oid,根据oid查 询订单项目
String oid=(String) map.get("oid");
//调用方法对order的
Order order=findOrderByOid(oid);
//将查找的数据进行封装
BeanUtils.populate(order, map);
orders.add(order); //这个用的是上一个方法
}
return orders;
}
这样一个个的订单就被装到orders中了,对他随便操作吧。
结算
结算的话,可以调用各银行的接口,或者调用一些**宝提供的接口完成付账,再付账后,将数据库中的响应信息更新即可。