day42-43 (8.30~31)两天购物商城的【商品模块收获总结】

8.30,31 两天做了 购物商城的商品模块。


细分为两个小模块。
8.30:商品的增删查改CRUD。
8.31:
商品批量删除。
商品分页查询。(重点)

商品模糊查询。


8.30:商品的增删查改CRUD。

8.30:商品的增删查改CRUD。
===收获:
①注意每跳转一个页面前,考虑下个页面是否需要传递数据过去。
需要传递数据:则先经过servlet处理,不能直接跳转页面;
不需要:则可以直接跳转。
②servlet service dao 三层间,使用接口关联。
从页面到servlet,servlet直接new XxxService();直接调 service.Xxx方法();
不存在的类和方法,根据错误提示创建,快速开发。
③外键cid,isHot,pDate(日期)三个字段 注意。
cid在Product实体类里要有 对应的依赖属性。
isHot 数据库是Boolean类型。对应实体类里 容易想到int的0和1;
	这里注意使用Integer未选择是否热门的商品就不会默认isHot=0(变为不热门)
pDate是 商品添加日期。
对应实体属性 有两种处理方式:
String:排序快,高效。===适合在数据量很大时使用。
Date:功能更强大。===例如可随意变更 日期格式,取毫秒值等。


8.31:
商品批量删除。
商品分页查询。(重点)
商品模糊查询。

===收获:

商品批量删除。

①商品批量删除:
----同时拿到 多个同名(name='pid')的复选框的id值:
JQuery:	
//==serialize()拿到所有表单项:【name和value的键值对】
var ids = $("input[type=checkbox]:checked").serialize();//pid=Xxx1&pid=Xxx2&pid=Xxx3...
location.href="${pageContext.request.contextPath}/delProducts?" + ids;

----servlet:delProducts 页面:
/*这里牢记:getParameterValues("pid")因为只能 接受多个同名表单项的值。
select的option没有name 属性,所以一定是CheckBox复选框。*/
String[] ids = request.getParameterValues("pid");

----批量删除:
/*
接着批量删除:servlet:service:dao,两种方式:
①:遍历数组ids,一条一条地删除。但 效率低下。
②:使用QueryRunner的batch(sql,Object[][] obj),批量删除。*/
②:代码:
public void delByPids(String[] pids) throws SQLException {
		//===QueryRunner qr = new QueryRunner();
		QueryRunner qr = new QueryRunner(C3p0Utils.getDataSource());
		String sql = "delete from product where pid=?";
		/*
		 * 二维数组结构
		 * 长度是要删除的 pid 的数量
		 * 每一个元素都是一个一维数组,一维数组的值 --- pid
		 */
		Object[][] params = new Object[pids.length][];
		for (int i = 0; i < params.length; i++) {
			/* params[i][0]=pids[i];//===self方式==NullPointerException==Why?
			 * 内层一维  数组params[i]没给定大小,也没静态初始化。
			 * 所以:可看作 只是声明 了数组名,没有new,没有 创建数组。
			 * 即:内层一维数组 Object[] params[i]=null;*/
			//
			params[i]=new Object[]{pids[i]};//==teacher==answer==ok
		}
		//==###=外围数组的长度决定了 sql 语句执行的次数,里面的一维数组的值用于补齐每次执行sql所需的参数===了解了。
		qr.batch(sql, params);
	}


商品分页查询。(重点)

②商品分页查询。
分页实现起来稍微麻烦点,页面需要的数据:
 productList(即pList),===不分页也需要,显示商品信息
当前页数pageNum,===分页需要
显示分页总页数pages。===分页需要	
(数据库总记录数目%pageSize==0?数据库总记录数目/pageSize : 数据库总记录数目/pageSize + 1)。

每页显示的商品数目:pageSize。===分页需要【可选】
这里没有单独抽出一个变量(或常量),写死在sql语句。
需要提取也很简单:只是查询时findByPage()方法要多传递一个pageSize参数。

分析完毕。

实现起来,也需要一步步来:
①先实现数据库分页查询:sql = select * from product limit start,pageSize;
还是使用QueryRunner的query(sql,ResultSetHandler b,Object[] params)
查询全部: params=null
List<Product> pList = qr.query(sql,new BeanListHandler<>(Product.class),null)
===页面显示和分页前一样,只是多添加了几个数据:
pList,pageNum,pages(总页数)三个数据,
都要请求转发到pList.jsp页面显示。页面EL表达式直接从request域对象里取值即可。

②使用面向对象思想:返回数据。
优化:pList,pageNum,pages(总页数)三个数据 都封装到pageBean对象里。
----在servlet,service,dao任意位置封装pageBean,效果一样。
只要可以返回给页面一个pageBean即可。
只是通常看作业务逻辑:在service里封装。
需要新建实体类PageBean:含有:pList,pageNum,pages三个属性。
====***作用:(在页面需要的数据个数和种类很多时,封装所有页面数据为PageBean,
方便了页面取值显示。)

③使用面向对象思想:处理类依赖关系。(重点)
前面的Pruduct类依赖Category,使用cid属性。改为Category cat属性。
====***为什么这样写?不仅仅是为了所谓的面相对象思想;
====***这样做的作用:
(【可以直接通过 实体product 拿到 有依赖关系的实体(这里是Category)的全部数据】)
====不这样,就只能拿到Category的cid。
====页面上显示商品信息的分类名称cname时,
使用cid依赖方式,无法直接获取cname,必须重新查询category表,麻烦。
使用Category对象依赖方式,可以直接通过getCategory()拿到Category的所有信息。

代码:
(为了实现:对象间的依赖。
必须
①同时查出 有依赖关系的多张表的信息。
===》多表查询sql+ QueryRunner的query(sql,new MapListHandler<>(Product.class),sql无参数)返回mapList。
【MapListHandler查询出:多表所有字段组成的map记录。===mapList】
②然后分别 封装每个实体对象,
===》遍历mapList:(Map map:mapList),BeanUtils.populate(bean对象,map)
这里两次执行populate,封装了product,category两个对象。
③set方法添加依赖关系。
product.setCategory(category)。

====这样【含有多张表全部完整信息的Bean(这里是Product)就封装完毕】。
)

注意:
******这里多表查询的sql写起来 比较简单。
外连接就OK:
SELECT * FROM category c LEFT OUTER JOIN product p ON p.cid=.cid;
//====后面就知道 还能用using:
SELECT * FROM category JOIN product USING (cid)


商品模糊查询。

③商品模糊查询 并对结果集分页。

能够写出sql语句:
SELECT * FROM (SELECT * FROM category JOIN product USING (cid) ) 
AS pp 
WHERE pp.pname LIKE "%电脑%"  LIMIT 0,7;
=======OK。其他和 前面“分页查询”:即“查询全部并分页”一样的。

注意:
******这里多表查询的sql写起来 有一定难度。
遇到:【外连接 left join重复字段】的问题。报错:有重复字段cid。
两种解决办法:
①两张表所有字段列出来,只列出来一个cid。====》字段太多时很麻烦。不推荐。
②使用专门处理这个问题的using关键字 来关联两张表。====》看sql代码

①两张表所有字段列出来,只列出来一个cid。====》代码
#====3 OK
SELECT * FROM 
(SELECT p.pid,p.pname,p.market_price,p.shop_price,p.pimage,p.pdesc,p.pdate,p.is_hot,p.pflag, 
c.cid,c.cname
 FROM product p LEFT OUTER JOIN category c ON p.cid=c.cid ) 
AS pp 
WHERE pp.pname LIKE "%电脑%"  LIMIT 0,2;

②使用专门处理这个问题的using关键字 来关联两张表。====》代码 

#======4:使用Using:OK
/*
有一种特殊情况,当两个要关联表的字段名是一样的,我们可以使用  USING ,可减少 SQL 语句的长度:
SELECT * FROM film JOIN film_actor USING (film_id) WHERE actor_id = 17 AND film.length > 120
这个时候括号就是必须的了。这种写法很好,输入更少的单词,查询的性能也非常棒,但还需要注意一些差异。
*/
#SELECT * FROM film JOIN film_actor USING (film_id)
SELECT * FROM category JOIN product USING (cid);
SELECT * FROM product JOIN category USING (cid);
SELECT * FROM (SELECT * FROM category JOIN product USING (cid) ) 
AS pp 
WHERE pp.pname LIKE "%电脑%"  LIMIT 0,7;



---------------代码:http://pan.baidu.com/s/1dFhEREL

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值