A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

江某人:
使用MVC设计模式JSP + Servlet + JavaBean + JDBC实现商品信息的CRUD的操作
创建工程导入jar包
msysql驱动
c3p0的包
dbutils的包
beanUtils的包:两个.
JSTL的包:两个

查询
在首页上点击【查询所有商品】链接:
提交到Servlet中:
    调用业务层-->调用DAO:
    将商品列表保存到request域中:
    转发到商品列表页面:
在商品列表的页面中显示商品:

添加:
在首页点击添加链接:跳转到添加页面.
在添加页面中输入信息:点击提交提交到Servlet
在Servlet中:
     接收数据:
     封装数据:
     调用业务层:
     页面跳转


重复提交的问题:
    添加完商品之后,转发到一个页面,刷新该页面.
     网速很慢,点击提交的按钮,其实已经在提交了但是网速慢,不停的点击提交.
  解决重复提交的根本解决办法:令牌机制(一次性).
     生成随机的令牌保存在session中.
     在表单的提交的时候,将随机的令牌放入到表单的隐藏字段中.
     在Servlet中获得session中和表单中的令牌是否一致.
     如果一致执行插入操作,不一致跳转到其他页面.将令牌销毁.
        类似于验证码实现 多加了个UUID

修改:
在列表页面上点击修改链接:
提交到Servlet:根据id查询该商品.将商品的信息显示到修改页面:
在修改的页面上修改数据,点击提交按钮:
提交到Servlet:完成商品信息的修改:

删除:
在列表页面上点击删除链接:
提交到Servlet:
调用业务层完成删除的操作:

分页分页功能的实现:
物理分页:一次只查10条记录,点击下一页,再去查询后10条.使用SQL语句进行控制的分页.
     缺点:经常需要和数据库交互.
     优点:数据量特别大,不会导致内存的溢出.
逻辑分页:一次性将所有数据全都查询出来,根据需要进行截取.List集合进行控制. subList();
    缺点:数据量如果特别大,容易导致内存溢出.
    优点:与数据库交互次数少.

MYSQL进行分页: 使用limit关键字.       
   select * from xxx where .. Group by ... Having ... Order by ...Limit a,b;--a:从哪开始.b:查询记录个数
                根据页数计算 limit后面的两个参数
                        currPage  begin   pageSize
                           1            0              10
                           2            10              10
                           3            20               10
                        begin = (currPage-1) * pageSize
                参数的传递:
                        前台---后台:currPage
                        后台---前台:currPage,totalPage(总页数),totalCount(总记录数),pageSize,List集合
回复 使用道具 举报
陈强
商品的CRUD&分页显示的一天
首先第一部分都是之前的知识的一个回顾,两个点需要注意一下
-1\解决商品重复添加的问题使用到了令牌机制,就是表单传出来的一个字符串和存在session中的一个字符串进行比较,不相同则无法添加,并且使用完后要将当前的session中的令牌清除
-2\批量删除中使用事务管理,避免删除过程中出现漏网之鱼
这一部分都是旧的知识,回顾了一下,发现在JS的知识有点忘了
然后是关于分页显示的部分,
分为物理分页和逻辑分页,区别在于每次读取的数量的多少,我们基本上使用的是物理分页,就是每次读取指定数量的信息
-这边使用到一个关键字limit,带两个参数,第一个参数A表示从什么位置开始查,第二个参数B是指查询的记录数,然后A\B与页数的关系就是A=( 页数 – 1 ) * B
-后台传到前台需要传递5个的参数,这里会将这些数据进行封装成pageBean.
由于这一部分的代码还未实现,其中的重点及注意事项还未总结....

回复 使用道具 举报
王刘锁
2018-6-12,补6-11日:
代码量太大,到晚上12点才勉强敲完代码,实在没精力写总结,拿到今天来补,昨天学习的是CRUD对数据库表中数据的增删改查操作,虽然是以前做过的,但是如今写起来还是吃力,那就来记录一下写代码遇到的问题和需要注意的地方:直接进入主题好了,先来添加商品的:点击添加按钮跳转到添加商品页面,输入商品信息后点击提交,把数据提交到servlet中,然后就是对数据库的查询
操作(很简单也写过很多次了.),需要注意的是给单选按钮或下来列表设置value=0/1好来接收数据,最重要的是注意重复提交问题,这里学习了新的东西来解决转发的地址栏不改变引起的刷新页面重复提交和其它一些重复提交问题--令牌机制!,就是Java有一个UUID的工具类来生成随机的字符串,那我们也需要在添加商品的时候给商品随机生成一个id,还要设置date-new date(),在查询的时候可以根据日期来排序,令牌机制就是在添加页面jsp中先生成一个随机字符串UUID.randomUUID().toString(),然后存在session域中-因为这个id是私有的,再在jsp中存一份隐藏的<input type="hidden" name="token" value="${token }">,然后就可以在添加商品的servlet中先获取session域中存的令牌和表单提交的令牌,取出后remove掉session中的令牌,下面先比较连个令牌是否一样,不一样说明页面没有刷新但是重复点了提交按钮,这就是重复提交了,那我们就不要再执行下面的添加商品代码了,添加的就是这么一点要注意的,下面说删除的,删除一条就是在删除按钮点击后触发onclick事件,执行window.location.href=""页面跳转功能,提交该商品的pid到后台进行操作,要注意的是删除多条记录时的事务管理,首先也是传pid到后台,点击按钮触发onclick事件执行代码document.getElementById("form1").submit()提交表单,但是在servlet中获取的pid的数组,然后在service中先获取连接,然后开启事务,遍历数组得到每一个pid根据每一个id去dao层操作数据库,好像没什么要注意的了,然后说修改吧,修改和添加页面相似,不同的是修改页面需要把商品原本的信息显示出来,这就需要我们点击修改按钮先把该商品id提交到后台去查询出该商品的信息,保存到request域中再转发到修改页面,在页面jsp中获取域中商品,得到每一个商品属性显示在表单中,这里对于单选按钮和下拉列表的数据需要做一个<c:if>的判断,前面我们给按钮设置的value值对应的数据内容就可以用的到了,然后是修改后提交的update数据库操作,接下来就是查询了,这个没什么注意的,就是查询后得到结果集,在jsp中遍历结果集得到每一个商品,再得到商品属性显示在页面就可以了,我们要学习的有模糊查询和分页查询,模糊查询就是输入关键字,根据关键字去数据库中查询数据,查询到也是一个结果集,要注意到是模糊查询的关键字是like-pname like ? 然后执行的时候参数就是%输入的关键字%这样可以查询到所有名字中有关键字的记录,也不难哈,
最终的重点来了,分页查询,思想搞懂了代码就很简单了,首先准备工作,创建一个类来封装一些需要在页面显示的数据PageBean,属性有currPage-当前页数,totalCount-总记录数,totalPage-总页数,pageSize-每页记录数,还有一个list<product>集合来存每一页的商品,然后首页点击分页查询要从第一页显示所以就传一个currPage=1到后台,然后去数据库中查,分页查询的关键字根据数据库不同也不相同,我们用的MySQL是limit关键字,String sql = "select * from product order by pdate desc limit ?,?";这里第一个?是从哪一条记录开始,第二个?是查多少条,从那一条记录开始可以用当前页减一乘以每页显示的条数来获取,begin=(currPage-1)*pageSize;dao层我呢只需要在service调用的时候传过去计算后的begin和pageSize就可以了重要的是service层中我们要new一个pagebean来封装数据,总页数可以用总记录数除以每页条数来获取,如果有余数就加一页,totalPage=totalCount/pageSize/(+1);再把查到的一定数量(pageSize)的结果集也封装到pagebean中,在servlet中吧pagebean存到request域中转发到分页查询显示页面,遍历结果集显示商品属性,为了效果可以在最后加一行来显示首页,下一页上一页尾页等,那首页就是连接路径跳转到分页查询servlet中提交的参数是currPage=1,那么尾页就是currPage=totalpage,上一页下一页就是当前页加一或减一,currPage+/-1;效果更好的可以显示每一页的数字(1,2,3,..);只需要加一个循环<c:forEach var="i" begin="1" end="${pageBean.totalPage }">循环的次数就是总页数.也可以在循环中判断,如果查看的是当前页就不可以再点这个数字,因为每点一次就刷新了一次页面,那点一次就会循环一次,在循环中判断把当前页显示成纯数字没有连接就可以实现了..另外在记一下以前学的全选全不选的实现,在引入jquery后用jquery来实现更简洁
$(function() {
        $("#checkAll").click(function() {
        $("input[name='check']").prop("checked", this.checked);
        });
        });当全选按钮点击触发事件执行代码获取所有name=check的input标签并用prop方法把这些标签的checked属性赋值为这个全选按钮的checked属性值this.checked;
回复 使用道具 举报
许剑鸿    webDay20


没有学习新内容  通过案例  商城商品的CRUD以及分页展示商品列表的学习增强了JDBC的技术及对MVC设计模式更深入了解

不知道总结啥 之前都写总结过  今天的任务是疯狂敲代码
回复 使用道具 举报
林文辉

增删改查及分页案例:
1.分页主要使用关键字 limit
2.使用令牌机制和重定向来解决重复提交的问题

/** 分页功能模块
         * @param request
         * @param response
         * @return
         */
        public String findByCid(HttpServletRequest request,HttpServletResponse response) {
                try {
                         
                        String cid=request.getParameter("cid");
                        Integer currPage = Integer.parseInt(request.getParameter("currPage"));
                        ProductService productService = (ProductService) BeanFactory.getBean("ProductService");
                        PageBean<Product> pageBean=productService.findPageByCid(cid,currPage);
                        request.setAttribute("pageBean", pageBean);
                        return "/jsp/product_list.jsp";
                } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                        throw new RuntimeException();
                }
               
        }

查找所有
public String findAll(HttpServletRequest request,HttpServletResponse response) {
                try {
                        Integer page = Integer.parseInt(request.getParameter("page"));
                        Integer rows = Integer.parseInt(request.getParameter("rows"));
                        PageBean pageBean = new PageBean();
                        pageBean.setPageSize(rows);
                        pageBean.setCurrPage(page);
                        ProductService productService = (ProductService) BeanFactory.getBean("ProductService");
                        JSONArray array = new JSONArray();
                        JSONObject result = new JSONObject();
                        array=JsonUtil.formToJSONArray(productService.findAll(pageBean));
                        int total =productService.findCountByPage();
                        result.put("rows", array);
                        result.put("total", total);
                        ResponseUtil.write(response, result);
                }catch(Exception e) {
                        e.printStackTrace();
                }
                return null;
        }

由于修改和添加的功能相似,放在同一个方法中
try {
                        Product product = new Product();
                        //创建磁盘工厂
                        DiskFileItemFactory disFileItemFactory = new DiskFileItemFactory();
                        disFileItemFactory.setSizeThreshold(5*1024*1024);
                       
                        //核心解析类
                        ServletFileUpload fileUpload = new ServletFileUpload(disFileItemFactory);
                        fileUpload.setHeaderEncoding("UTF-8");
                       
                        List<FileItem> list = fileUpload.parseRequest(request);
                        Map<String,String> map = new HashMap<String,String>();
                        String fileName = null;
                        for (FileItem fileItem : list) {
                                if(fileItem.isFormField()) {
                                        //普通项
                                        String name = fileItem.getFieldName();
                                        String value = fileItem.getString("UTF-8");
                                        map.put(name, value);
                                }else {
                                        //文件项
                                        fileName = fileItem.getName();
                                        InputStream is = fileItem.getInputStream();
                                        String path = this.getServletContext().getRealPath("products/1");
                                        OutputStream os = new FileOutputStream(path+"/"+fileName);
                                        int len = 0;
                                        byte[] bytes = new byte[1024];
                                        while((len=is.read(bytes))!=-1) {
                                                os.write(bytes, 0, len);
                                        }
                                        is.close();
                                        os.close();
                                }
                        }
                        //封装数据
                        BeanUtils.populate(product, map);
                        product.setPimage("products/1/"+fileName);
                        Category category = new Category();
                        category.setCid(map.get("cid"));
                        product.setCategory(category);
                        //存入数据库
                        ProductService productService = (ProductService) BeanFactory.getBean("ProductService");
                        Integer saveNums = null;
                        String data =map.get("data");
                        if("1".equals(data)) {
                                saveNums=productService.modifyProduct(product);
                        }else {
                        saveNums=productService.saveProduct(product);
                        }
                        JSONObject result =new  JSONObject();
                       
                        if(saveNums.intValue()>0) {
                                result.put("success", "true");
                        }else {
                                result.put("success", "true");
                                result.put("errorMsg", "保存失败");
                        }
                        ResponseUtil.write(response, result);
                       
                }catch(Exception e) {
                        e.printStackTrace();
                }

删除
public String delProduct(HttpServletRequest request,HttpServletResponse response) {
                Integer delNums=null;
                try {
                        String delIds = request.getParameter("delIds");
                        ProductService productService = (ProductService) BeanFactory.getBean("ProductService");
                        delNums= productService.deleteByPid(delIds);
                        JSONObject result = new JSONObject();
                        if(delNums.intValue()>0) {
                                result.put("success", "true");
                                result.put("delNums",delNums.intValue());
                        }else {
                                result.put("errorMsg", "删除失败");
                        }
                        ResponseUtil.write(response, result);
                } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }
                JSONObject result =new JSONObject();
                return null;
        }
回复 使用道具 举报
万冕

今天学的主要是加强之前学的内容,在加一些扩展

拓展了一个令牌机制,主要是解决重复提交重复插入的情况,是利用UUID生成一个随机的字符串,然后在赋值完后,将域里的
UUID移除,第二次刷新时两个UUID就会不同,从而做到了不会重复提交的情况

最主要的就是分页功能,分为两种

物理分页一次只查固定的条数,点下一页后再查固定的页数
缺点就是要经常和数据库进行连接
优点查找数量不大,不会造成内存溢出

逻辑分页是一次性将所有的内容都查询出来,再利用sql语句进行分页截取
缺点数量大容易造成内存溢出
优点与数据库联系少

limit关键字(从哪开始,显示的条数)
回复 使用道具 举报
谢洪彬:
CRUD(增删改查):
今天主要是应用了以前学习的知识进行对商品的页面进行增删该查的操作,以及分页的一个商品显示,虽说是以前学习过的,但是需要进行很多逻辑上的操作再加上很多页面上的跳转.
增:
SQL语句: insert into 表名 values(值1,值2,值3.....);
要点分析:
1.由于表单提交的参数过多,这是我们可以使用BeanUtils工具类进行数据的一键封装,条用populate(实体类对象,Map集合),进行封装.封装的要点是你表单的name属性名要和实体类的属性一致,这样才可以实现数据的一键封装.
2.在进行添加的过程中我们发现了可以重复提价的bug,比如添加完数据进行倒退,这时是访问我们缓存的历史.针对于这类情况我们可以使用令牌机制.
步奏分析:
2.1使用UUID获取随机字符并存入session域中
2.2 在表单中设置一个隐藏的<input>标签,并将值设置为session中UUID的值
2.3在servlet中进行两个值的判断
2.4在获取玩session中UUID的之后需要把该对象删除,保证令牌的唯一性.

单条删:  
SQL语句:delect form 表名 where 条件 ;
1.我们可以根据ID去删除对应的数据
多条记录删除:
1.如果是多条删除,也可以根据ID去删除,但是servlet得到的数据会是一个存有多个ID的集合.
2.在进行多条删除的时候我们就需要在service中开启事务,要么多条删除一起成功,要么一起失败,在service中就可以遍历得到的ID并一次调用方法对数据库进行操作.
改:
SQL语句: update 表名 set 值1,值2.....where 条件;
1.在进行修改之前我们要获取该条数据的全部值,并将对应的值放入修改表中作为默认值
2.在进行修改时因为也是多条数据的提交,我们也可以使用beanutils进行一键封装
条件查询:
SQL语句:select * from 表名 where 条件
1.我们需要获取文本框的值,根据这个值去dao曾进行模糊查询操作
2.关键字:
like 模糊查询  % 任意字符
这个时候我们需要注意%不能直接写到SQL语句中

分页查询:        还没敲完,待续.....
回复 使用道具 举报
王清松
今天所使用的所有技术都是以往学习的,所以主要是熟练操作,新知识仅有两点

1.令牌思想,防止信息的重复提交
2.sql语句中limit关键字的使用
回复 使用道具 举报
张述明
分页的显示(重点)

功能实现;
1.        物理分页: 一次只查10条,下一页在查10条   
缺:经常需要和数据交互
使用sql语句来控制分页

2.        逻辑分页: 一次查询所有数据,根据需要进行截取
缺点:数据量太大,容易内存溢出
List集合进行控制



不同的数据库对分页的语句也不一样

Mysql进行分页,使用limit关键字
Select*fromxxx where …group by..having…Order by…limit a ,b  
a是第几条开始  b:向下查询的记录数
参数的传递
前台—后台  传currpage  要跳转的页数 想访问哪一页
后台:传前台  当前页数currpage 总计录数 totalCount  总页数 每页显示条数  list<product>
Oracle进行分页,使用sql语句嵌套
Sql Server数据库进行分页,使用top关键字
:
主页-链接-serlvet?currpage=1;------sevlet(接收数据)   返回一个PageBean:就是背包
业务层: new PageBean()   设置pagebean参数  五个
回复 使用道具 举报
Do1 中级黑马 2018-6-16 15:15:18
30#
本帖最后由 Do1 于 2019-12-1 23:49 编辑



商品的增删改查和分页主要涉及到的是JDBC使用和JSTL  JSP语句的使用

分页主要是通过把页面数封装成一个类,然后存到session或者转发到域中,再用JSTL JSP调取数据,打印出来,超链接的路径指向的是想要访问的页面数然后去切换页面的Servlet类处理处理后转发再到页面中遍历出查询到的商品,这个页面数也就是JSTL循环打印出来的页面数,
回复 使用道具 举报
5119 中级黑马 2018-6-19 19:44:33
31#
游荣辉
总结       
        今天复习了一波MVC设计模式JSP + Servlet + JavaBean + JDBC和 CRUD 的操作.,和学习了分页查询

        查询的功能就不多说了,添加的功能加了一个令牌机制,就是使用了令牌禁止就可以防止你的多次提交,不管你是刷新页面还是返回再次添加,都只能添加一个.
        删除多条信息要把id封装成一个list集合返回给后台,遍历这个集合,依次删除就好了
        今天还学了一个新知识.分页,
                分页条: 【首页】【上一页】[1][2][3][4]【下一页】【尾页】(这个就是普通的分页条)
                分页有两种
                        物理分页:一次只查10条记录,点击下一页,再去查询后10条.使用SQL语句进行控制的分页.(现在基本都在用的)
                        逻辑分页:一次性将所有数据全都查询出来,根据需要进行截取.List集合进行控制. subList();
                像不同数据库对分页的语句都是不一样的
                        Mysql数据库就是使用limit关键字
                                样式:  前面就是我们普通的查询语句,只是最后的时候要加上limit关键字,他后面有两个参数,第一个参数是:从第几个开始,第二个参数是:想要查询的个数(就是想要一次看到几天数据)
                        可以是使用页数来计算limit的两个参数
                                第二个参数可以写死
                                第一个参数=(前台出来的页数-1)*第二个参数
                        参数的传递
                                前台--->后台:当前页数
                                后台--->前台:当前页数,总页数,总记录数,第二个参数,List集合.
                                        这样传递很麻烦,我们可以把他们封装到一个实体类中,在用这个实体类进行传递就好了
回复 使用道具 举报
12
您需要登录后才可以回帖 登录 | 加入黑马