day20MyBatis高级查询与分页详解Word下载.docx
- 文档编号:17861663
- 上传时间:2022-12-11
- 格式:DOCX
- 页数:23
- 大小:1.31MB
day20MyBatis高级查询与分页详解Word下载.docx
《day20MyBatis高级查询与分页详解Word下载.docx》由会员分享,可在线阅读,更多相关《day20MyBatis高级查询与分页详解Word下载.docx(23页珍藏版)》请在冰豆网上搜索。
用户选择了,这个字段就不为空,当这个字段不为空的时候,我们就在where后的查询加上这个条件过滤
2.2使用代码完成高级查询
在完成高级查询之前,我们要准备一个Query对象。
为什么要准备这个Query对象呢?
1查询的条件是有很多的,如果我们不封装成对象,传多个参数的话很麻烦,也不利于以后的修改与扩展
2调用MyBatis中配置的sql的时候,只能传一个参数,那咱们只有把所有参数都封装到一个对象中,然后把这个对象传递过去
Query对象就是咱们的查询对象,创建Query对象是有一定的规范的:
它应该在一个query包中,这个包与domain同级,名称为XxxQuery---Xxx表示实体的名称
如:
StudentQuery/ProductQuery
在Query中我们准备好相应的查询条件字段与属性(Query就是一个JavaBean)
根据上面的分析,咱们为Product准备相应的Query对象:
publicclassProductQuery{
privateStringname;
//商品名称
privateBigDecimalmaxPrice;
//最高价格
privateBigDecimalminPrice;
//最低价格
//提供相应的getter与setter方法
//提供一个方法来返回拼接的Sql语句
publicStringgetWhereSql(){
...
}
}
然后咱们在dao层准备一个高级查询的方法直接传入ProductQuery,如下:
List<
Product>
queryAll(ProductQueryquery);
我们接着完成这个queryAll的功能,包含xml中也搞定相应的代码。
但是在使用的时候咱们会遇到问题,而解决的方案居然是把#号改成$。
讲到这里,我们得先来研究一下#与$的区别。
再来完成其它的功能。
讲完#现$的区别后,咱们就来完成相应的代码。
也就是拼接字符串的方案(课堂中完成):
第一种:
使用where1=1(影响查询的效率)
Stringsql="
where1=1"
;
if(productName!
=null&
&
!
"
.equals(productName)){
sql+="
andproductNamelike'
%"
+productName+"
%'
if(maxSalePrice!
=null){
andsalePrice<
="
+maxSalePrice;
if(minSalePrice!
andsalePrice>
+minSalePrice;
returnsql;
第二种方式:
用一个集合来保存,第一个用where,其它的用and
好处:
解决了1=1的问题,代码稍显复杂
List<
String>
sqlList=newArrayList<
();
sqlList.add("
productNamelike'
);
salePrice<
+maxSalePrice);
salePrice>
+minSalePrice);
for(inti=0;
i<
sqlList.size();
i++){
if(i==0){
sql+="
where"
}else{
and"
}
sql+=sqlList.get(i);
第三种方式:
使用JDK自带的功能来替换第一个字符串
/**
*在这里拼接我们的条件字符串
*我们想达成的目标:
如果没有条件,就没有where以及的后面的代码
*如果有条件,第一个条件前面是where,后面的条件才是and
*我们可以加一个功能,把sql字符串中的第一个and修改成where
*@return
*/
sql=sql.replaceFirst("
and"
"
where"
2.3#与$的区别
在拼接字符串之前,咱们先说一个在MyBatis的映射文件,一个占位使用#与$的区别,我们了解了这个后,才能去完成字符串的拼接。
select*fromproduct${whereSql}
select*fromproductwhereproductNamelike'
%小米%'
$:
直接从javaBean中拿属性值,可以用于拼接SQL字符串(不安全)
$:
只能从对象中拿到数据
select*fromproduct#{whereSql}-报错
select*fromproduct?
#:
只是代表?
占位符(安全),设置值时值和设置的数据库字段名有关,和#{xxx}里面的xxx无关。
2.4使用MyBatis完成高级查询
刚才咱们已经讲解了在Java代码中拼接字符串的方案。
有的复杂,有的简单。
这确实也是一种解决方案。
不过MyBatis也为我们提供了一种完成高级查询的解决方案,而且这个方式用起来还非常简单(那就开始吧)。
在MyBatis中,它提供了一个where标签,然后在它里面加上if标签,所有的条件咱们都加上and,由于在where中,它会把第一个and替换成where。
从而自动帮我们完成高级查询的字符串拼接。
代码如下:
2.5Web中完成高级查询
1完成页面上的查询条件
先看我们要做的效果:
当我们点提交的时候就应该根据过滤条件得到相应的产品
那么我们页面上就需要一个form表单:
写页面时要使用placeholder,必须是的结构
<
formaction="
/product"
method="
post"
>
<
inputtype="
text"
name="
productName"
value="
${query.productName}"
placeholder="
商品名称"
/>
number"
minSalePrice"
${query.minSalePrice}"
最低价格"
maxSalePrice"
${query.maxSalePrice}"
最高价格"
submit"
..我要的.."
/form>
2完成servlet中的代码
2.1得到form表单中的数据,将它封装到ProductQuery里面
2.2通过Query里面的查询数据到dao层去拿到过滤后的所有产品
三分页功能
分页是我们开发中很常见的功能。
试想一下,如果一张表有20万条数据,我们一次读取出来,对整个程序的性能是非常大的负担,而且也要影响到查询的速度。
对用户来说,一下看到这么多数据估计也是醉了。
因此:
分页功能必不可少!
3.1真分页与假分页
分页有两种:
真分页与假分页。
这个只是我们对两种分页方式的取名而已,两种分页方式没有孰优孰劣。
他们只是方式与特性不同,于是选择上有不同,咱们B/S结构的软件可能更多的会使用真分页来完成功能。
下面,我们就对真分页与假分页进行介绍
假分页(前端分页)
比如说现有数据库有300条数据。
它先把300要数据全部读取到我们的内存里面。
Select*fromproduct;
->
300条
1--30
如果我每页30条,那么我们都从内存里面(List)里面来读取
好处:
翻页快,功能实现简单,不匀速(第一次非常慢,后面快)
劣势:
占用内存大
c/s
真分页(后端分页)
如果我每页30条,那么每次到数据库里去读取当前的30条数据
select*fromproductLIMIT0,29
select*fromproductLIMIT30,59
select*fromproductLIMIT60,89
占用内存小
翻页慢
它查询数据是匀速的
3.2分页的设计原理
分页前咱们要研究的几个问题:
查询的数据一共多少条?
通过Sql直接查询
每页要显示多少条数据?
自己决定的(或者客户前台选择)
我们如何计算一共多少页?
需要知道共多少条?
每页多少条?
共多少条/每页多少条(可以除尽)
共多少条/每页多少条+1(不可以除尽的情况)
怎么拿到某一页的所有数据?
SELECT*FROMproductLIMIT(当前页数-1)*每一页的条数
从哪一条数据开始不是由客户来直接输入的。
而是由他传过来的当前页面算出来的。
计算的公式:
(当前页数-1)*每一页的条数
解决了上面四个问题,咱们就可以完成后台的分页功能!
3.3后台完成分页功能
第一步:
在xml中添加分页的sql
第二步:
在query对象中加上分页的查询条件
注:
对咱们来说,分页的的条件也是属性查询的过滤条件。
-----------------------------
第三步:
直接在dao层里面实现分页查询
3.4Web中完成分页功能
在写代码之前,咱们先说一下。
完成分页功能,我们需要在前端做一个什么样的展示。
3.4.1分页功能的分析
研究一些数据:
①.每页多少条数据②.一共多少条数据③.当前第几页④首页⑤上一页
⑥下一页⑦尾页我们要考虑的是,这些数据应该是从何而来的
分析与计算过程:
1totalCount:
一共多少条数据从数据库中直接查询
selectcount(*)fromproduct
2pageSize:
每页多少条数据:
由我们自己决定
3currentPage:
当前每几页:
由客户决定(客户在前台选择)
当客户点击上一页,下一页,首页,尾页就代表它在做选择
也就是不管他点的是哪一个:
------------------------------------------------------
下面的所有数据都可以通过上面的条件计算出来:
4totalPage一共多少页
分析:
总共50条数据,每页10条->
5页totalCount/pageSize
总共52条数据,每页10条->
6页totalCount/pageSize+1
也就是说:
不能除尽,就需要加1
totalCount%pageSize==0?
totalCount/pageSize:
totalCount/pageSize+1
5firstPage:
首页就是第一页
6lastPage:
最后一页就是一共多少页(等于totalPage)
7prevPage:
上一页(判断,如果是第1页,不会变化)
currentPage<
=1?
1:
currentPage-1
8nextPage:
下一页(判断,如果是最后一页,不会变化)
currentPage>
=totalPage?
currentPage:
currentPage+1
----------------------------------------------------
9List这个查询到的数据
3.4.2封装分页对象
当我们点分页的每一个分页元素(如上一页,下一页)的时候,都会修改我们的当前页。
而我们又怎么知道上一页要到第几页,而下一页又是到第几页呢?
难道每次到了这个页面我们再进行计算嘛?
当然不是,在这个地方,我们的最佳实践就是把我当前显示的分页信息与展示的所有数据封装成一个分页对象.对于我们之前所分析研究出来的分页字段与数据全部封装到这个对象中。
之后,咱们直接从后台返回这个分页对象,就可以拿到所有数据了。
注意:
前面咱们学了一个Query对象,是前台传给后台,用于做查询的。
现在这个叫做分页对象,是后台传给前台,是用于展示了。
这个点一定要清楚。
分页对象的基础字段
分页数据的计算(可以查看上页的分析部分理解)
3.4.3dao层的改动
思考:
咱们准备好的分页对象怎么用?
分页对象是需要我们在后台(dao层)组装好,然后返回到前台。
我们在dao层准备一个返回分页对象的方法即可:
注意了:
在分页对象中我们需要拿到一共多少条数据,因为需要加上这条SQL:
3.4.3Jsp的修改(根据PageList显示数据)
3.4.4Servlet层的修改
调用拿到PageList的方法,并根据情况在前台提供currentPage这个参数
四高级查询与分页的集成
完成分页后我们可以去看一下现在我们的功能,不过很快会发生一个很让我们失望的结果。
就是高级查询与分页之间似乎毫无关系。
试想一下,我在淘宝上搜索电脑,然后我不管再选第几页,我查到的都应该是电脑的数据吧!
因此,我们需要把高级查询与分页这两个家伙结合起来。
但是,现在的问题就是!
我们应该怎么去完成这个集成功能呢?
1完成DAO层的集成:
我的建议是:
从SQL入手!
我们要把高级查询与分页的功能都写到一条SQL中。
...
思考:
除了查询的数据,查询总条数是否也需要高级查询与分页?
高级查询肯定是需要了,还是以找电脑为例。
当我们做了查询后,总条件就应该是一共有多少条电脑信息,而不是应该是所有商品有多少条了。
分页就不需了,要页是针对当前结果分页,而我们查总条数只有一个结果。
因此根据就没有必要。
2完成前台的集成
后台条件集成后,我们可以看到结果依然有问题,那是由于前台的操作还没有合并。
什么意思呢?
咱们前台现在传给后台的条件只有两种可能:
1只传分页条件给前台
2只传高级查询条件给前台
其实我们要做的很简单:
将两种条件合并在一起就可以了(即点分页的时候带上查询条件)。
说起来简单,但是到底怎么怎么做?
分页是使用超连接直接到后台的,它怎么带上我们的高级查询条件呢?
我们可以通过JS来完成相应的功能:
第一:
将分页的条件(currentPage),放到高级查询中(隐藏域中)
第二:
点链接的时候不要直接跳转,而去执行一段JS代码
第三:
这段JS代码完成两件事
①将当前页的值赋给隐藏域(修改currentPage这个隐藏域)
②提交表单
完成这三步后,大家可以看到:
当我们点击分页条的时候,其实是把要查的页面与高级查询的条件一起通过表单进行了提供,这样,咱们前台的查询功能大功告成!
附:
功能分析图
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- day20MyBatis 高级 查询 分页 详解