【SSH网上商城项目实战19】订单信息的级联入库以及页面的缓存问题

购物车这一块还剩最后两个问题,就是订单信息的级联入库和页面缓存,这里的信息是指购物车和购物项,即我们将购物车的信息存入数据库的同时,也存入每个购物项的信息,而且外键都关联好,这涉及到了Hibernate中的级联入库问题;页面缓存问题指的是当用户确认了订单后,如果点后退,又会回到订单确认页面,刚刚的订单确认页面又出来了,而且session还在,信息还是刚刚的信息,这明显不是我们想要的结果,我们会在后面一一分析。这一节主要来讨论订单信息的级联入库以及页面的缓存问题。

1. 订单信息的级联入库
        Hibernate中两张关联表的级联入库,需要配置一下,这里主要介绍注解的配置方式,订单的POJO是Forder,购物项的POJO是Sorder,Forder与Sorder是一对多的关系,首先我们设置一下它们的注解配置,如下:

 1 @Entity
 2 public class Forder implements java.io.Serializable {
 3     
 4     //省略无关代码……
 5  
 6     private List<Sorder> sorders = new ArrayList<Sorder>();
 7  
 8     @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "forder")
 9     public List<Sorder> getSorders() {
10         return this.sorders;
11     }
12  
13     public void setSorders(List<Sorder> sorders) {
14         this.sorders = sorders;
15     }
16 }
17  
18 @Entity
19 public class Sorder implements java.io.Serializable {
20  
21     //省略无关代码……
22  
23     private Forder forder;
24  
25     @ManyToOne(fetch = FetchType.LAZY)
26     @JoinColumn(name = "fid")
27     public Forder getForder() {
28         return this.forder;
29     }
30  
31     public void setForder(Forder forder) {
32         this.forder = forder;
33     }
34 }

这样配置后,当我们save订单项时,也会save购物项,而且自动关联外键。但是前提是,我们要将它们之间的关系设置好,即forder中要setSorders(),sorder中要setForder(),以及其他相关联的外键对应的实体中的属性。

 

        之前我们将购物项加入购物车的时候已经将执行了forder.setSorder(sorder)了,现在我们需要在sorder中加入forder,所以我们在原来的代码上添加一下,如下:

 1 //这是17节中的代码,我们在中间插上一句
 2 @Service("sorderService")
 3 public class SorderServiceImpl extends BaseServiceImpl<Sorder> implements
 4         SorderService {
 5  
 6     @Override
 7     public Forder addSorder(Forder forder, Product product) {
 8         boolean isHave = false; //用来标记有没有重复购物项
 9         //拿到当前的购物项
10         Sorder sorder = productToSorder(product);
11         //判断当前购物项是否重复,如果重复,则添加数量即可
12         for(Sorder old : forder.getSorders()) {
13             if(old.getProduct().getId().equals(sorder.getProduct().getId())) {
14                 //购物项有重复,添加数量即可
15                 old.setNumber(old.getNumber() + sorder.getNumber());
16                 isHave = true;
17                 break;
18             }
19         }
20         //当前购物项在购物车中不存在,新添加即可
21         if(!isHave) {
22                         //我们在这里插入一句:
23             //在向购物中添加购物项之前,先建立购物项与购物车的关联,但是此时forder.id为null,
24             //但是在入库的时候是先入库购物车,再入库购物项,那时候就有主键了
25             sorder.setForder(forder);
26             forder.getSorders().add(sorder);
27         }
28         
29         return forder;
30     }
31  
32     @Override
33     public Sorder productToSorder(Product product) {
34         Sorder sorder = new Sorder();
35         sorder.setName(product.getName());
36         sorder.setNumber(1);
37         sorder.setPrice(product.getPrice());
38         sorder.setProduct(product);
39         return sorder;
40     }
41 }

        好了,我们看一下订单确认时跳转到了哪个Action:

 

        所以我们去完成forderAction中的逻辑:

 

 1 @Controller("forderAction")
 2 @Scope("prototype")
 3 public class ForderAction extends BaseAction<Forder> {
 4     
 5     @Override
 6     public Forder getModel() {
 7         model = (Forder) session.get("forder");
 8         return model;
 9     }
10  
11     //实现购物车(订单)与购物项(订单项)级联入库功能
12     public String save() {
13 //        // 把session中的购物项交给当前的model对象
14 //        Forder forder = (Forder) session.get("forder");
15 //        //model.setSorders(forder.getSorders());
16 //        forder.setAddress(model.getAddress());
17 //        forder.setName(model.getName());
18 //        forder.setPhone(model.getPhone());
19 //        forder.setRemark(model.getRemark());
20 //        forder.setUser((User)session.get("user"));
21 //        forder.setStatus(new Status(1));
22 //        forder.setPost(model.getPost());
23 //        //级联入库(需要在xml或者POJO的注解中配置),需要sorder关联forder
24 //        //在SorderServiceImpl类中追加sorder.setForder(forder);
25 //        forderService.save(forder);
26         
27         model.setUser((User)session.get("user"));
28         model.setStatus(new Status(1));
29         forderService.save(model);
30         
31         return "bank";
32     }
33 }

从上面的代码中可以看出,有两种方法:第一种不覆写getModel方法(我注释掉的部分),这个方法比较笨,由于ForderAction继承了BaseAction,而BaseAction实现了ModelDriven接口,所以传过来的数据会封装到model中,model是BaseAction中的一个属性,然后我们需要将model中的信息全部传到session中的forder中,然后forder中数据有了才能与Sorder一起级联入库,不过这种方法有点笨……所以我们采用第二种方法,重写getModel方法,直接将forder赋给model即可,然后我们只要将model中级联的项添加一下即可,即上面非注释的代码。这样用户点击订单确认后,信息入库,跳转到支付页面(支付页面接下来要做,目前先随便跳转到一个jsp即可)。

2. 页面缓存问题
        现在订单信息的级联入库解决了,但是如果用户点击确认订单后,再后退,我们发现还是原来的订单确认页面,而且信息还是刚刚的信息,session也没关,也就是说相当于我又要确认订单信息,这明显是不妥的,也就是说,当用户点击确认订单后,我们不能让页面缓存,这样的话,当用户点击后退,就会显示页面已经失效了,我们让它跳到首页即可。

        我们知道,在前台jsp页面可以设置让浏览器不缓存数据,所以我们可以在前台confirm.jsp页面进行如下设置:

但是问题没那么简单,仅仅这样做是不行的,这样做的话,用户点击后退是会出现页面已过期的提示,但是当用户刷新一下又不行了,又会显示缓存加载原来的数据。所以我们明白了一点,由于session还没关闭,session中有订单的信息forder,用户刷新一下肯定会继续拿到这个forder,就会显示原来的订单信息,所以仅仅在前台这样设置根本无法解决问题,我们在后台也要做相关处理才行。

        既然知道问题所在了,我们可以这样做:因为当用户点击确认订单后,会交给ForderAction,然后ForderAction处理完后会跳转到支付页面,我们可以在ForderAction中做些手脚:我们将session中原来的forder给清掉,那就不OK了么?这是可行的,但是考虑到后面支付的时候还是需要订单的相关信息,所以我们可以将session中原来的forder保存到另一个地方,然后将原来的forder清空,所以我们在上面的ForderAction中最后加上两行代码,如下:

 

 1 @Controller("forderAction")
 2 @Scope("prototype")
 3 public class ForderAction extends BaseAction<Forder> {
 4     
 5     @Override
 6     public Forder getModel() {
 7         model = (Forder) session.get("forder");
 8         return model;
 9     }
10  
11     //实现购物车(订单)与购物项(订单项)级联入库功能
12     public String save() {
13 //        // 把session中的购物项交给当前的model对象
14 //        Forder forder = (Forder) session.get("forder");
15 //        //model.setSorders(forder.getSorders());
16 //        forder.setAddress(model.getAddress());
17 //        forder.setName(model.getName());
18 //        forder.setPhone(model.getPhone());
19 //        forder.setRemark(model.getRemark());
20 //        forder.setUser((User)session.get("user"));
21 //        forder.setStatus(new Status(1));
22 //        forder.setPost(model.getPost());
23 //        //级联入库(需要在xml或者POJO的注解中配置),需要sorder关联forder
24 //        //在SorderServiceImpl类中追加sorder.setForder(forder);
25 //        forderService.save(forder);
26         
27         model.setUser((User)session.get("user"));
28         model.setStatus(new Status(1));
29         forderService.save(model);
30         
31         //此时购物车已经入库,那么原来session中的购物车就应该清空
32         session.put("oldForder", session.get("forder"));//先将原来的购物车信息保存下来,因为后面付款的时候还需要相关信息
33         session.put("forder", new Forder());//new一个新的空购物车(相当于清空了购物车),还可以方便用户再买~
34         return "bank";
35     }
36 }

        然后还没完,我们在前台确认订单页面也得加上下面的代码:

 

现在的逻辑就清楚了,首先到订单确认页面,forder是有数据的,所以不为空,这个判断无效的,当用户点击确认订单后,在ForderAction中我们将forder换成了一个空的Forder对象,也就是说原来的数据都没了(我们保存在session中另一个键值对中,供后面支付用),这样当用户点后退又回到刚刚订单确认页面时,那个判断就生效了,就会跳转到首页去,到这里,整个逻辑就完整了,页面缓存问题解决好了。
 

转载于:https://www.cnblogs.com/sharpest/p/9916404.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/276952.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

exfat分配单元大小选多少_安防监控摄像机视角大小和镜头毫米数的基础知识!...

关于选择监控镜头毫米数的问题&#xff0c;虽然只有新手才有此困惑&#xff0c;但是我们还是要认真地说一说。监控视角&#xff0c;就是指监控照射的镜头所能覆盖到的范围&#xff0c;就是监控画面所能看到的角度统称叫监控视角。我们正常选购监控的时候&#xff0c;除了可以选…

彩信编辑器之预览功能

html代码 <table width"200"height"250"border"0"cellpadding"0"cellspacing"0"bgcolor"#666666"><tr><td align"center"valign"middle"><marquee id"MMScreen&qu…

java 几个实用的小工具

1、除法运算 编程的人都知道&#xff0c;java中的“/”、“%”运算&#xff0c;其中前者为取整&#xff0c;后者取余数。那么有没有快捷的运算方法取正常的运算结果呢&#xff1f; 查了资料&#xff0c;发现很简单。代码如下&#xff1a; public static String txfloat(int a,i…

处理模板页菜单高亮

//处理模板页菜单高亮var urlstatus false;$("#indexMenu a").each(function () {if ((location.href /).indexOf($(this).attr(href)) > -1 && $(this).attr(href) ! ) {$(this).parent().addClass(active);urlstatus true;} else {$(this).parent().…

动画演示 Delphi 2007 IDE 功能[3] - 修改属性

动画剧本:添加控件后用 F11 激活 Object Inspector 窗口;可用 ↑ ↓ 选择属性;用 Tab 切换属性名和属性值;用 Tab 切换到属性名后, 键入属性名的部分字母, 可迅速定位;用 Tab 切换到属性值后, 也可以键入字母选择, 而后回车确认.Ctrl↓ 可以选择其他控件;整个过程可以做到无鼠标…

kali怎么成为管理员_网站死链是什么、是怎么引起的以及死链对SEO优化的影响?...

网站死链是我们在做SEO时必不可少的一个错误&#xff0c;对于从事SEO行业的人员来说&#xff0c;网站死链最熟悉不过了&#xff0c;但是对于那些刚入SEO行业的新手来说&#xff0c;还是不太熟悉。今天我们就给大家讲一下什么是网站死链&#xff1f;网站死链是怎么引起的&#x…

Map-Reduce入门

1、Map-Reduce的逻辑过程 假设我们需要处理一批有关天气的数据&#xff0c;其格式如下&#xff1a; 按照ASCII码存储&#xff0c;每行一条记录每一行字符从0开始计数&#xff0c;第15个到第18个字符为年第25个到第29个字符为温度&#xff0c;其中第25位是符号/-006701199099999…

Java之泛型T T与T的用法

<T> T表示返回值是一个泛型&#xff0c;传递啥&#xff0c;就返回啥类型的数据&#xff0c;而单独的T就是表示限制你传递的参数类型&#xff0c;这个案例中&#xff0c;通过一个泛型的返回方式&#xff0c;获取每一个集合中的第一个数据&#xff0c; 通过返回值<T>…

UrlReWriter 使用经验小结

UrlRewriter 是微软封装好了的一个URL重写组件。使用它可以让我节约很多自已开发的时间。 好了&#xff0c;开始讲述我的应用经验&#xff0c;这只是很菜鸟的经验&#xff0c;高手就不用看了。 第一步&#xff0c;请从此下载此组件。解压&#xff0c;把UrlRewriter.dll copy到你…

clickhouse大数据分析技术与实战_从销售到经营——大客户销售策略与实战技术...

对于首席客户代表而言&#xff0c;要走出困局&#xff0c;所需要大客户销售策略性的训练&#xff0c;而不是像基层客户经理的销售技巧训练一样&#xff1b;新业务的学习固然重要&#xff0c;但更重要的是转化成实战绩效。从组织变革角度&#xff0c;每次成功的业务转型背后都意…

Hadoop_NameNode_代码分析_目录树(2)

&#xff08;1&#xff09;NameNode的内存中保存了庞大的目录树结构&#xff0c;这个结构用来保存文件目录结构和文件Block之间的映射&#xff0c;这种结构关系会固化在磁盘上&#xff0c;但是对树的改动频繁发生&#xff0c;什么时候将树写入磁盘呢&#xff1f;把每次操作应用…

详解 Visual C# 数据库编程

详解 Visual C# 数据库编程 ******2007-11-05 14:34关于数据库编程&#xff0c;微软提供了一个统一的数据对象访问模型&#xff0c;在Visual Studio6.0中称为ADO&#xff0c;在.NET中则统一为ADO.NET,掌握ADO.NET就等于掌握了数据库编程的核心。 针对数据库编程始终是程序设计语…

swift - 根试图控制器的手势返回冲突 - push 新的tabbar控制器手势冲突

1. 禁用手势 和开启手势extension JYRTSShopListController: UIGestureRecognizerDelegate {/// 禁止使用手势返回func forbidhenSideBack() {self.isCanSideBack falseif (self.navigationController?.responds(to:#selector(getter: self.navigationController?.interacti…

Acer 4750 安装黑苹果_黑苹果系统安装通用教程图文版

在开始之前&#xff0c;不管你要安装的是台式组装机&#xff0c;台式品牌机&#xff0c;一体机&#xff0c;还是笔记本&#xff0c;都要大概了解一下硬件信息。因为黑苹果的安装确实比安装Windows的系统要复杂的多。不管是前期准备工作&#xff0c;安装&#xff0c;还是安装之后…

IIS7中使用集成模式时出现HttpException

症状:在iis7在使用集成模式的Pool可能出现HttpException,而程序在经典模式下能正常运行. 解决方法:http://mvolo.com/blogs/serverside/archive/2007/11/10/Integrated-mode-Request-is-not-available-in-this-context-in-Application_5F00_Start.aspx 转载于:https://www.cnbl…

教你学会七种维护服务器安全最佳技巧

导读&#xff1a; 你的计算机上是否存在有至关重要的数据,并且不希望它们落入恶人之手呢?当然,它们完全有这种可能 。而且,近些年来,服务器遭受的风险也比以前更大了.越来越多的病毒,心怀不轨的黑客,以及那些商业间谍都将服务器作为了自己的目标.很显然,服务器的安全问题是不容…

mysql 快速生成百万条测试数据

转自&#xff1a;http://www.cnblogs.com/jiangxiaobo/p/6101072.html 1、生成思路 利用mysql内存表插入速度快的特点&#xff0c;先利用函数和存储过程在内存表中生成数据&#xff0c;然后再从内存表插入普通表中2、创建内存表及普通表 CREATE TABLE vote_record_memory (id I…

自动化专业学python有用吗-马哥教育官网-专业Linux培训班,Python培训机构

今天小编要来说一下Python自动化的学习思路&#xff0c; 对于刚刚进入的测试行业的人来说&#xff0c;未来该怎么样朝着自动化方向发展&#xff0c;即使接触到了自动化测试&#xff0c;又该从何下手去学呢&#xff1f; 简单的说&#xff0c; 做测试做的好&#xff0c;会了接口&…

java JVM

每一个Java虚拟机都由一个类加载器子系统&#xff08;class loader subsystem&#xff09;&#xff0c;负责加载程序中的类型&#xff08;类和接口&#xff09;&#xff0c;并赋予唯一的名字。每一个Java虚拟机都有一个执行引擎&#xff08;execution engine&#xff09;负责执…

马化腾联手10余位科学家发起科学探索奖,腾讯基金投入10亿元启动资金

11月9日消息&#xff0c;据腾讯科技报道&#xff0c;腾讯基金会于腾讯公司成立20周年之际宣布&#xff0c;腾讯公司董事会主席兼首席执行官&#xff0c;腾讯基金会发起人马化腾&#xff0c;与北京大学教授饶毅&#xff0c;携手杨振宁、毛淑德、何华武、邬贺铨、李培根、陈十一、…