web.xml
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:beans.xml</param-value>
</context-param>
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<filter>
<filter-name>SpringCharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>SpringCharacterEncodingFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
springmvc
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
">
<context:component-scan base-package="com.rl.ecps.controller"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/shop/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
访问首页:
@Controller
@RequestMapping("/item")
public class EbItemController {
@RequestMapping("toIndex.do")
public String toIndex() {
return "index";
}
}
由于下面使用了iframe,于是就出现了404错误了。 src是不能直接获取WEB-INF的JSP的。
<iframe id="itemListIframe" src="phoneClassification.jsp" frameBorder=0 scrolling=no width="100%" height="200%" ></iframe>
于是乎,我们把地址修改成访问controller,controller做跳转就行了。
<iframe id="itemListIframe" src="${path}/item/phoneClassification.do" frameBorder=0 scrolling=no width="100%" height="200%" ></iframe>
@RequestMapping("phoneClassification.do")
public String phoneClassification() {
return "phoneClassification";
}
设置完之后我们就可以能看到页面了。
我们要做的就是, 通过前台给出的参数,我们后台筛选出数据在前台展示。
首先,我们来分析一下可以筛选的参数把:
从参数上我们可以分为几类:
首先,我们把所有品牌先查询和对应的参数先查询出来吧。
@RequestMapping("toIndex.do")
public String toIndex(Model model) {
List<EbBrand> ebBrands = brandService.selectBrand();
List<EbFeature> isSelect = featureService.selectIsSelect();
model.addAttribute("ebBrands", ebBrands);
model.addAttribute("isSelect", isSelect);
return "index";
}
在页面上做展示
<c:forEach items="${isSelect}" var="feature">
<li style="display:none"><b>${feature.featureName}:</b>
<p>
<a href="javascript:void(0);" title="不限" class="here">不限</a>
<c:forEach items="${feature.selectValues}" var="val">
<a href="javascript:void(0);" >${val}</a>
</c:forEach>
</p>
</li>
</c:forEach>
/**
* 接收条件,查询出符合条件的商品
* @param brandId 品牌id
* @param price 价钱
* @param param 被选中的参数
* @return
*/
@RequestMapping("listItem.do")
public String listItem(Long brandId, String price, String param) {
return "phoneClassification";
}
参数我们已经知道了,那我们怎么写这个SQL语句呢??
我的分析是这样子的:
/**
根据价钱,品牌,被选中属性查询符合条件的商品
涉及到的表:
1.商品
2.商品
3.参数值
4.价钱
*/
SELECT *
FROM EB_BRAND brand, EB_ITEM item, EB_PARA_VALUE para, EB_SKU sku
WHERE brand.BRAND_ID = item.BRAND_ID AND
para.ITEM_ID = item.ITEM_ID AND
sku.ITEM_ID = item.ITEM_ID AND
brand.BRAND_ID = 1002 AND
sku.SKU_PRICE BETWEEN 1 AND 800000 AND
para.PARA_VALUE = 'Android4.0';
在价钱中是一个范围,因此我们用between and 语法,而我们的参数传递过来可能是与很多的,因此只要我们使用动态SQL循环就行了。
因此,我们的mapper中的SQL是这样子的。
<select id="listItem" parameterType="map" resultMap="listItemRM">
SELECT item.*, sku.SKU_PRICE
FROM EB_BRAND brand, EB_ITEM item, EB_PARA_VALUE para, EB_SKU sku
<where>
brand.BRAND_ID = item.BRAND_ID
para.ITEM_ID = item.ITEM_ID AND
sku.ITEM_ID = item.ITEM_ID AND
<if test="brandId!=null">
brand.BRAND_ID = #{brandId} AND
</if>
<if test="minPrice!=null">
sku.SKU_PRICE BETWEEN #{minPrice} AND #{maxPrice} AND
</if>
<if test="paraList!=null">
<foreach collection="paraList" item="val" >
para.PARA_VALUE = #{val} AND
</foreach>
</if>
</where>
</select>
由于我们的展示数据还需要价钱,返回的basemap不够用。我们就新创建了一个Map
<resultMap type="com.rl.ecps.model.EbItem" id="listItemRM" extends="BaseResultMap">
<result column="sku_price" property="skuPrice"/>
</resultMap>
在实体中给予对应的属性
private BigDecimal skuPrice;
public BigDecimal getSkuPrice() {
return skuPrice;
}
public void setSkuPrice(BigDecimal skuPrice) {
this.skuPrice = skuPrice;
}
dao实现
public List<EbItem> listItem(Map<String, Object> map) {
return this.getSqlSession().selectList(nameSpace + "listItem", map);
}
service实现
public List<EbItem> listItem(Long brandId, String price, String param) {
Map<String, Object> map = new HashedMap();
map.put("brandId", brandId);
//将价钱进行分割成两部分
if (StringUtils.isNotBlank(price)) {
String[] strings = price.split(",");
map.put("minPrice", strings[0]);
map.put("maxPrice", strings[1]);
}
//分割并装载到map中
List<String> list = new ArrayList<String>();
if (StringUtils.isNotBlank(param)) {
String[] paras = param.split(",");
for (String para : paras) {
list.add(para);
}
map.put("paraList", list);
}
return itemDao.listItem(map);
}
基于这么一个需求, 当我们点击一个条件的时候,我们要把当前所有获取的条件都获取出来。然后提交给服务器端就行了!
在点击选中事件上,我们获取数据
//使用变量状态我们的数据
var price = "";
var brandId = "";
var paraStr = "";
$(".filter li a").each(function () {
//拿到选中的超链接
var clazz = $(this).attr("class");
if (clazz == "here") {
//得到他们的类型【在html中我们自定义了3个类型】
var myType = $(this).attr("myType");
//根据不同的类型,对其进行不同的操作
if (myType == "brand") {
brandId = $(this).attr("myBrandValue")
} else if (myType == "price") {
price = $(this).attr("myPriceValue");
} else if (myType == "para" && $(this).attr("myParaValue") != null) {
var val = $(this).attr("myParaValue");
paraStr = paraStr + val+",";
}
}
});
alert(price + "---" + brandId + "---" + paraStr);
修改iframe的请求路径,把我们的参数带过去
var iframePath = "${path}/item/listItem.do?price="+price+"&brandId="+brandId+"¶Str="+paraStr;
$("#itemListIframe").attr("src", iframePath);
/**
* 接收条件,查询出符合条件的商品
*
* @param brandId 品牌id
* @param price 价钱
* @param paraStr 被选中的参数
* @return
*/
@RequestMapping("/listItem.do")
public String listItem(Long brandId, String price, String paraStr, Model model) {
// TODO 基本效果出来了,但条件查询还有问题。
List<EbItem> items = itemService.listItem(brandId, price, paraStr);
model.addAttribute("items", items);
return "phoneClassification";
}
我们在查询的时候,发现很多相同价钱的手机都展示出来的。讲道理我们只要展示最低价钱那款就行了
想要展示最低价那款,还是要去修改SQL语句。需要用到分组函数了。
首先我有这么一个商品
它有两个最小销售单元,一般我们在页面上显示最便宜的那个就行了。
我们的SQL语句可以写成这样:
SELECT min(sku.SKU_PRICE) SKU_PRICE ,item.*
FROM EB_ITEM item, EB_PARA_VALUE para, EB_SKU sku
WHERE para.ITEM_ID = item.ITEM_ID
AND sku.ITEM_ID = item.ITEM_ID
AND item.BRAND_ID = 3069
AND sku.SKU_PRICE BETWEEN 1 AND 1000000
AND para.PARA_VALUE = 'Android'
AND item.ITEM_ID=3080
GROUP BY item.ITEM_ID,
item.ITEM_NAME,
item.ITEM_NO,
item.BRAND_ID,
item.CAT_ID,
item.TAG_IMG_ID,
item.TAG_IMG,
item.IS_NEW,
item.IS_GOOD,
item.IS_HOT,
item.PROMOTION,
item.AUDIT_STATUS,
item.SHOW_STATUS,
item.IMGS,
item.KEYWORDS,
item.PAGE_DESC,
item.ITEM_RECYCLE,
item.ON_SALE_TIME,
item.CHECK_TIME,
item.UPDATE_TIME,
item.UPDATE_USER_ID,
item.CREATE_TIME,
item.CHECKER_USER_ID,
item.FULL_PATH_DEPLOY,
item.FULL_PATH_DEPLOY_OFFER,
item.ORIGINAL_ITEM_ID,
item.LAST_STATUS,
item.MERCHANT_ID,
item.ITEM_SORT,
item.SALES,
item.CREATE_USER_ID,
item.SIM_LEVEL,
item.GIFT_DESC,
item.GIFT_IMG,
item.GIFT_SHOW_TYPE,
item.IMG_SIZE1
order by item.item_id desc
修改一下Mapper中的SQL语句:
<select id="listItem" parameterType="map" resultMap="listItemRM">
SELECT item.*, min(sku.SKU_PRICE) sku_price
FROM EB_ITEM item, EB_PARA_VALUE para, EB_SKU sku
<where>
para.ITEM_ID = item.ITEM_ID AND
sku.ITEM_ID = item.ITEM_ID
<if test="brandId!=null">
AND item.BRAND_ID = #{brandId}
</if>
<if test="minPrice!=null">
AND sku.SKU_PRICE BETWEEN #{minPrice} AND #{maxPrice}
</if>
<if test="paraList!=null">
<foreach collection="paraList" item="val">
AND para.PARA_VALUE = #{val}
</foreach>
</if>
</where>
GROUP BY item.ITEM_ID,
item.ITEM_NAME,
item.ITEM_NO,
item.BRAND_ID,
item.CAT_ID,
item.TAG_IMG_ID,
item.TAG_IMG,
item.IS_NEW,
item.IS_GOOD,
item.IS_HOT,
item.PROMOTION,
item.AUDIT_STATUS,
item.SHOW_STATUS,
item.IMGS,
item.KEYWORDS,
item.PAGE_DESC,
item.ITEM_RECYCLE,
item.ON_SALE_TIME,
item.CHECK_TIME,
item.UPDATE_TIME,
item.UPDATE_USER_ID,
item.CREATE_TIME,
item.CHECKER_USER_ID,
item.FULL_PATH_DEPLOY,
item.FULL_PATH_DEPLOY_OFFER,
item.ORIGINAL_ITEM_ID,
item.LAST_STATUS,
item.MERCHANT_ID,
item.ITEM_SORT,
item.SALES,
item.CREATE_USER_ID,
item.SIM_LEVEL,
item.GIFT_DESC,
item.GIFT_IMG,
item.GIFT_SHOW_TYPE,
item.IMG_SIZE1
order by item.item_id desc
</select>
再次查看的时候,只出现一台了。
标准答案的SQL是使用exists关键字来进行查询的:在单表查询的情况下,看有没有符合条件的数据,如果符合,那么exists为ture
<select id="listItem" parameterType="map" resultMap="listItemRM">
select min(es.sku_price) sku_price, ei.*
from eb_item ei, eb_sku es
<where>
ei.item_id = es.item_id
<if test="minPrice != null">
and es.sku_price between #{minPrice} and #{maxPrice}
</if>
<if test="brandId != null">
and ei.brand_id = #{brandId}
</if>
<if test="paraList != null">
<foreach collection="paraList" item="paraValue">
and exists (select *
from eb_para_value t
where ei.item_id = t.item_id
and t.para_value = #{paraValue})
</foreach>
</if>
</where>
group by ei.ITEM_ID,
ei.ITEM_NAME,
ei.ITEM_NO,
ei.BRAND_ID,
ei.CAT_ID,
ei.TAG_IMG_ID,
ei.TAG_IMG,
ei.IS_NEW,
ei.IS_GOOD,
ei.IS_HOT,
ei.PROMOTION,
ei.AUDIT_STATUS,
ei.SHOW_STATUS,
ei.IMGS,
ei.KEYWORDS,
ei.PAGE_DESC,
ei.ITEM_RECYCLE,
ei.ON_SALE_TIME,
ei.CHECK_TIME,
ei.UPDATE_TIME,
ei.UPDATE_USER_ID,
ei.CREATE_TIME,
ei.CHECKER_USER_ID,
ei.FULL_PATH_DEPLOY,
ei.FULL_PATH_DEPLOY_OFFER,
ei.ORIGINAL_ITEM_ID,
ei.LAST_STATUS,
ei.MERCHANT_ID,
ei.ITEM_SORT,
ei.SALES,
ei.CREATE_USER_ID,
ei.SIM_LEVEL,
ei.GIFT_DESC,
ei.GIFT_IMG,
ei.GIFT_SHOW_TYPE,
ei.IMG_SIZE1
order by ei.item_id desc
</select>
对于这三类,我们很容易就能够把他们显示出来。 最主要的问题是获取他们这些数据、然后根据这些数据进行查询
对于标准答案,是将被选中的参数使用exist关键字来对其进行过滤。一个条件对应一个exist。至于他俩有什么区别我倒不知道了,知道了再回来补吧。
由于我们有3个参数、Dao层使用map集合来接收。