一、Admin维护功能清单:
1、分页显示全部Admin数据
2、分页显示Admin数据的关键词查询结果
3、批量删除
4、单条删除
5、新增Admin
6、更新Admin
分页显示和查询结果可以合并为一个操作:
【select xxx,xxx from t_admin where xxx limit xxx,xxx;】查询操作也就比全部查询多了个where条件语句,在分页可以统一做。
批量与单条删除也可以合并为同一个操作:
【批量删除在Handler方法里面去接收的是用List<Integer>去接收,单条同样也可以用List<Integer>去接收,也就是看成是批量删除的一种特殊情况。】
二、分页数据请求:
哪些操作需要去请求分页数据?这些:
1、Admin通过以上三种方式给AdminHandler发送请求,再去AdminService查询分页数据,Service通过分页插件的方法传递回来一个页码,接着就从AdminMapper执行查询,分页插件查询会自动加上limit语句,所以我们做查询不需要考虑分页的事,SQL需要适配关键词存在与不存在这两种情况,最终返回List给Service,然后Service再封装PageInfo类型对象返回给AdminHandler。然后AdminHandler将类型存入模型,最终就返回给页面,页面需要使用Pagination显示分页导航条。
三、执行查询的SQL:
SELECT * FROM t_admin WHERE login_acct LIKE '%a%' OR username LIKE '%a%' OR email LIKE '%a%';
1、但是需要考虑空字符串查询的情况(文本框没有输入,为默认传入空字符串),所以需要去适配:
SELECT * FROM t_admin WHERE login_acct LIKE CONCAT ("%","","%")
OR username LIKE CONCAT ("%","","%")
OR email LIKE CONCAT ("%","","%") ;
CONCAT:拼字符串,执行字符串的连接。
四、AdminMapper:
AdminMapper.xml:
<select id="selectAdminListByKeyword" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from t_admin
WHERE login_acct LIKE CONCAT("%" , #{keyword} , "%")
OR username LIKE CONCAT("%" , #{keyword} , "%")
OR email LIKE CONCAT("%" , #{keyword} , "%")
</select>
AdminMapper.java:List<Admin> selectAdminListByKeyword(String keyword);
五、测试:
@Autowired
private AdminMapper adminMapper;
@Test
public void testAdminMapperSearch(){
String keyword = "a";
List<Admin> list = adminMapper.selectAdminListByKeyword(keyword);
for (Admin admin : list) {
System.out.println(admin);
}
}
六、AdminService:
1、依赖:
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
作用:以完全非侵入的方式在原有查询基础上附加的分页效果,从SQL层面来说,在SQL语句后面附加LIMIT子句,从Java代码来说,把原来返回的List类型封装为page类型。
2、配置方式:在spring-persist-mybatis.xml中的sqlSessionFactoryBean去配置:
<!--配置插件-->
<property name="plugins">
<array>
<!--PageHelper插件全类名-->
<bean class="com.github.pagehelper.PageHelper">
<!--配置插件属性-->
<property name="properties">
<props>
<!--配置数据库方言,MySQL分页:limit,Oracle分页:TopN分析-->
<prop key="dialect">mysql</prop>
<!--配置自动修正页码,pageNo的有效范围:1~总页数-->
<prop key="reasonable">true</prop>
</props>
</property>
</bean>
</array>
</property>
3、AdminService.java:public PageInfo<Admin> queryForKeywordSearch(Integer pageNum,Integer pageSize,String keyword);
4、AdminServiceImpl.java:
@Override
public PageInfo<Admin> queryForKeywordSearch(Integer pageNum,Integer pageSize,String keyword) {
//1、调用PageHandler的工具方,开启分页功能
PageHelper.startPage(pageNum,pageSize);
//2、执行分页查询
List<Admin> list = adminMapper.selectAdminListByKeyword(keyword);
//3、将List对象封装到PageInfo对象中
return new PageInfo<>(list);
}
七、AdminHandler.java:
jsp页面: <a href="admin/query/for/search.html"><i class="glyphicon glyphicon-user"></i> 用户维护</a>
CrowdfundingConstant:public static final String ATTR_NAME_PAGE_INFO = "PAGE-INFO";
@RequestMapping("/admin/query/for/search")
public String queryForSearch(
/**
* defaultValue:默认值是第一页,有默认值就需要required
* 如果页面没有提供对应的请求参数,那么可以使用指定默认值
*/
@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
@RequestParam(value = "pageSize",defaultValue = "5") Integer pageSize,
@RequestParam(value = "keyword",defaultValue = "") String keyword,
Model model){
PageInfo<Admin> pageInfo = adminService.queryForKeywordSearch(pageNum,pageSize,keyword);
model.addAttribute(CrowdfundingConstant.ATTR_NAME_PAGE_INFO,pageInfo);
return "admin-page";
}
八、测试:
@Test
public void testAdminMapperSearch(){
String keyword = "a";
List<Admin> list = adminMapper.selectAdminListByKeyword(keyword);
for (Admin admin : list) {
System.out.println(admin);
}
}
http://localhost:8080/crowdfunding-admin-4-webui/admin/query/for/search.html
九、页面显示
<tbody>
<c:if test="${empty requestScope['PAGE-INFO'].list}">
<tr><td style="text-align: center;" colspan="6">抱歉没有查询到你要的结果。</td></tr>
</c:if>
<c:if test="${!empty requestScope['PAGE-INFO'].list}">
<c:forEach items="${requestScope['PAGE-INFO'].list}" var="admin">
<tr>
<td>${myStatus.count}</td>
<td><input type="checkbox"></td>
<td>${admin.loginAcct}</td>
<td>${admin.username}</td>
<td>${admin.email}</td>
<td>
<button type="button" class="btn btn-success btn-xs"><i class=" glyphicon glyphicon-check"></i></button>
<button type="button" class="btn btn-primary btn-xs"><i class=" glyphicon glyphicon-pencil"></i></button>
<button type="button" class="btn btn-danger btn-xs"><i class=" glyphicon glyphicon-remove"></i></button>
</td>
</tr>
</c:forEach>
</c:if>
</tbody>
<tfoot>
<tr >
<td colspan="6" align="center">
<ul class="pagination">
<li class="disabled"><a href="#">上一页</a></li>
<li class="active"><a href="#">1 <span class="sr-only">(current)</span></a></li>
<li><a href="#">2</a></li>
<li><a href="#">3</a></li>
<li><a href="#">4</a></li>
<li><a href="#">5</a></li>
<li><a href="#">下一页</a></li>
</ul>
</td>
</tr>
十、导航条
1、导入jQuery分页导航条pagination插件文件:
2、
<link rel="stylesheet" href="css/pagination.css" />
<script src="jquery/jquery.pagination.js"></script>
3、
<tfoot>
<tr >
<td colspan="6" align="center">
<div id="Pagination" class="pagination"><!-- 这里显示分页 --></div>
</td>
</tr>
</tfoot>
<script type="text/javascript">
$(function(){
//对分页导航条显示进行初始化
initPagination();
});
//声明函数去封装导航条初始化的操作
function initPagination() {
//总记录数
var totalRecord = ${requestScope['PAGE-INFO'].total};
//声明变量存储分页导航条显示时的属性设置
var painationProperties= {
num_edge_entries: 1, //边缘页数
num_display_entries: 4, //主体页数
callback: pageselectCallback, //回调函数
items_per_page: ${requestScope['PAGE-INFO'].pageSize}, //每页显示数据数量
current_page: ${requestScope['PAGE-INFO'].pageNum - 1} ,//当前页
prev_text: "上一页", //上一页文本
next_text: "下一页", //下一页文本
}
//显示分页导航条
$("#Pagination").pagination(totalRecord,painationProperties);
}
//在每一次点击“上一页”、“下一页”、“页码”时执行这个函数跳转页面
function pageselectCallback(pageIndex, jq){
//pageIndex是从0开始的,pageNum是从1开始的
var pageNum = pageIndex + 1;
//跳转页面
window.location.href="admin/query/for/search.html?pageNum="+pageNum;
return false;
}
</script>
pagination.js需要修改:不然会一直刷新页面。
十一、关键词查询
<button type="submit" class="btn btn-warning">
<i class="glyphicon glyphicon-search"></i> 查询</button>
为什么这里的param能够使用,因为前面的操作与现在的操作都是属于同一个请求。