今天在操作订单的代码时,控制台总是报出反射方法内部出现问题,debug仔细查找后,确定问题出现在dao层:
下面是我写的具体的订单dao
- public class OrderDao {
- QueryRunner qr = new QueryRunner();
- //当点击意见购买时生成订单即往订单表中插入订单
- public void addOrder(Order order){
- //得到数据库连接
- Connection con = null;
- try {
- con = JdbcUtils.getConnection();
- String sql = "insert into orders values(?,?,?,?,?,?)";
- //将下单时间转换为SQLdate
- Timestamp ts = new Timestamp(order.getOrdertime().getTime());
- Object [] params = {order.getOid(),ts,order.getTotal(),
- order.getState(),order.getUser().getUid(),order.getAddress()};
- qr.update(con, sql, params);
} catch (SQLException e) {
- throw new RuntimeException(e);
- }finally{
- try{ if(con!=null){con.close();}}catch(SQLException e){throw new RuntimeException(e);}
- }
- }
- //向表单中添加表单项
- public void addOrderItem(List<OrderItem> orderitem){
- Connection con = null;
- try {
- con = JdbcUtils.getConnection();
- String sql = "insert into orderitem values(?,?,?,?,?)";
- Object [][] params = new Object[orderitem.size()][];
- for(int i=0;i<orderitem.size();i++){
- OrderItem item = orderitem.get(i);
- params[i] = new Object[]{item.getIid(),item.getCount(),
- item.getSubtotal(),item.getOrder().getOid(),
- item.getBook().getBid()};
- }
- qr.batch(con, sql, params);
- } catch (SQLException e) {
- throw new RuntimeException(e);
- }finally{
- try{ if(con!=null){con.close();}catch(SQLException e){throw new RuntimeException(e);}
- }
}
而在service层上面两个方法是包含在同一个事务中,如下所示:
- public void addOrder(Order order){
- OrderDao dao = new OrderDao();
- try {
- //开启事务
- JdbcUtils.beginTransaction();
- dao.addOrder(order);
- dao.addOrderItem(order.getOrderitemlist());
- JdbcUtils.commitTransaction();
- } catch (SQLException e) {
- System.out.println("asdf");
- try {
- //回滚事务
- JdbcUtils.rollBack();
- } catch (SQLException e1) {
- throw new RuntimeException(e);
- }
- throw new RuntimeException(e);
- }
- }
如上的红色部分是问题的关键,由于在service层中它两所处在同一个事务,所以其中一个一旦关闭连接,就因为无法正常运行另外一个方法而导致SQL异常,最后的解决办法是,我封装了一个JdbcUtils工具类,它有一个释放链接的方法,会先判断事务是否还在使用连接,如果使用就不关闭,如果不使用,就关闭连接。所以红色出现问题的地方应该改为JdbcUtils.releaseConnection(con);问题解决。
-----------------------------------------------------------------------------------------------------
问题二:在表单的servlet层发现当用户在选择同一本书时不会出现问题,而购买多种图书时,就会爆出SQL异常说是同一个key值不能插入多条数据。源码如下:
- public class OrderServlet extends BaseServlet {
- public String addOrder(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- //从购物车中获取订单
Cart cart = (Cart) request.getSession().getAttribute("cart");
- //封装订单
- Order order = new Order();
- order.setOid(CommonUtils.uuid());
- order.setOrdertime(new Date());
- order.setTotal(cart.getTotal());
- order.setState(1);
- order.setUser((User)request.getSession().getAttribute("user"));
- //封装订单项
- Collection<CartItem> col = cart.getCartItems();
- List<OrderItem> orderItemList = new ArrayList<OrderItem>();
- ///
- for(CartItem ci:col){
- OrderItem oi = new OrderItem();
- oi.setBook(ci.getBook());
- oi.setCount(ci.getCount());
- oi.setIid(CommonUtils.uuid());
- oi.setSubtotal(ci.getTotal());
- oi.setOrder(order);
- orderItemList.add(oi);
- }
- order.setOrderitemlist(orderItemList);
- //清空购物车
- cart.clear();
- //调用service方法
- orderService os = new orderService();
- os.addOrder(order);
- request.setAttribute("order", order);
- return "f:/item/jsps/order/desc.jsp";
- }
- }
debug之后发现,选择多种图书时,购物车中没有问题即session没有问题,而是在添加表单项时,原先的图书种类都变成了同一种,仔细研究才发现将
- OrderItem oi = new OrderItem();写在了红色的/出,这就导致每次循环产生的订单项都是同一个,因为这里只产生了一个订单对象,而且是购物车集合中的最后一个,因为每次加载后面的总是会覆盖前面的内容。