springMVC,myBatis的物理分页和高级查询
- 格式:docx
- 大小:79.21 KB
- 文档页数:23
Java的MyBatis框架中实现多表连接查询和查询结果分页实现多表联合查询还是在david.mybatis.model包下⾯新建⼀个Website类,⽤来持久化数据之⽤,重写下相应toString()⽅法,⽅便测试程序之⽤。
package david.mybatis.model;import java.text.SimpleDateFormat;import java.util.Date;public class Website {private int id;private String name;private int visitorId;private int status;private Date createTime;private Visitor visitor;public Website() {// TODO Auto-generated constructor stubcreateTime = new Date();visitor = new Visitor();}public Website(String name, int visitorId) { = name;this.visitorId = visitorId;visitor = new Visitor();status = 1;createTime = new Date();}public int getId() {return id;}public void setId(int id) {this.id = id;}public Visitor getVisitor() {return visitor;}public void setVisitor(Visitor visitor) {this.visitor = visitor;}public String getName() {return name;}public void setName(String name) { = name;}public int getStatus() {return status;}public void setStatus(int status) {this.status = status;}public Date getCreateTime() {return createTime;}public void setCreateTime(Date createTime) {this.createTime = createTime;}public int getVisitorId() {int id = 0;if (visitor == null)id = visitorId;elseid = visitor.getId();return id;}public void setVisitorId(int visitorId) {this.visitorId = visitorId;}@Overridepublic String toString() {StringBuilder sb = new StringBuilder(String.format("Website=> {Id:%d, Name:%s, CreateTime:%s}\r\n", id, name,new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(createTime)));if (visitor != null)sb.append(String.format("Visitor=> %s", visitor.toString()));return sb.toString();}}在david.mybatis.demo下⾯分别新建相应的操作接⼝:package david.mybatis.demo;import java.util.List;import david.mybatis.model.Website;public interface IWebsiteOperation {public int add(Website website);public int delete(int id);public int update(Website website);public Website query(int id);public List<Website> getList();}在mapper⽂件夹下新建WebsiteMapper.xml映射⽂件,分别参照上⼀张所说的把增删改查的单表操作配置分别放进去,这样你可以建造⼀点测试数据。
mybatis的pagehelper分页案例
以下是一个使用Mybatis的pagehelper插件进行分页的案例:
1. 添加依赖:在Spring Boot项目中引入pagehelper的依赖。
2. 配置分页插件:在配置文件中配置分页插件,配置内容如下:
```xml
< plugins>
<plugin
interceptor="com.github.pagehelper.PageInterceptor" /> </plugins>
```
3. 设置分页参数:在查询方法中设置分页参数,示例代码如下:
```java
Page<Article> page = articleMapper.findByTitle(title, new Page<Article>(pageNo, pageSize));
```
其中`Article`是实体类,`articleMapper`是对应的mapper接
口,`findByTitle`是查询方法,`title`是查询条件,`new Page(pageNo, pageSize)`是分页参数,分别表示页码和每页显示的条数。
4. 获取分页结果:通过分页对象`page`的方法获取分页结果,示例代码如下:
```java
List<Article> articles = page.getResult();
```
其中`articles`是分页结果。
以上是Mybatis的pagehelper分页案例的基本步骤。
请注意,具体的配置和参数可能因项目而异,你可以根据实际情况进行调整。
mybatisrowbounds分页原理MyBatis是一个流行的Java持久化框架,它提供了多种分页方式,其中一种是使用RowBounds来实现分页。
本文将介绍MyBatis RowBounds分页原理,包括如何使用RowBounds实现分页、分页的实现原理以及如何优化分页性能。
一、使用RowBounds实现分页MyBatis提供了两种分页方式:基于物理分页和基于逻辑分页。
基于物理分页是通过数据库分页语句(如MySQL的LIMIT语句)来实现分页,而基于逻辑分页是通过查询所有结果,然后在内存中进行分页。
RowBounds是一种基于逻辑分页的方式,它通过设置查询结果集的偏移量和限制数量来实现分页。
使用RowBounds实现分页非常简单。
首先,需要在Mapper接口中定义一个方法,该方法应该包含两个参数:一个是查询条件,另一个是RowBounds对象。
例如:```List<User> getUsersByPage(String name, RowBounds rowBounds);```在XML映射文件中,需要编写一个SQL语句,该语句应该查询所有符合条件的记录,并将结果集限制在指定的偏移量和限制数量内。
例如:```<select id='getUsersByPage' resultType='User'>select * from user where name like #{name} limit #{offset}, #{limit}</select>```在Java代码中,需要构造一个RowBounds对象,该对象包含偏移量和限制数量。
例如:```int offset = (pageNum - 1) * pageSize;int limit = pageSize;RowBounds rowBounds = new RowBounds(offset, limit);List<User> users = userMapper.getUsersByPage(name, rowBounds);```以上代码将查询所有名字包含name的用户,并将结果集限制在从offset开始的limit个记录内。
本文通过一个实例,详细地说明了如何用SpringMVC进行数据库查询并且分页显示开发环境:操作系统:windows XP sp3数据库:Oracle10gIDE:MyEclipse6Web容器:Tomcat5.xJDK版本:JDK1.6工程切图如下基本上参照之前示例修改得来,重点关注SimpleJdbcTemplate与JdbcTemplate用法以下只列出比较重要的类UserController.javapackage com.liuzd.sj.web;import java.util.List;import javax.annotation.Resource;import javax.servlet.http.HttpServletRequest;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.SessionAttributes; import org.springframework.web.servlet.ModelAndView;import com.liuzd.page.Page;import er;import erService;@Controller@RequestMapping("/user")@SessionAttributes("userList")public class UserController extends BaseController{private UserService userService;public UserService getUserService() {return userService;}@Resourcepublic void setUserService(UserService userService) {erService = userService;}@RequestMapping("/userList")public ModelAndView userList(HttpServletRequest request){ StringBuilder querySql = new StringBuilder();querySql.append("select * from users where 1=1 ");String oracleQuerySql = querySql.toString();//获取总条数Long totalCount = newLong(this.getUserService().pageCounts(oracleQuerySql));//设置分页对象Page page =executePage(request,oracleQuerySql,totalCount," id desc ");ModelAndView mv = new ModelAndView();//查询集合List<User> users =this.getUserService().pageList(page.getQuerySql());mv.addObject("userList",users);mv.setViewName("userList");return mv;}@RequestMapping("/addUser")public ModelAndView addUser(HttpServletRequest request,User user){System.out.println("ADD USER: "+ user);erService.addUser(user);return userList(request);}@RequestMapping("/toAddUser")public String toAddUser(){return "addUser";}@RequestMapping("/delUser/{id}")public ModelAndView delUser(@PathVariable("id") Stringid,HttpServletRequest request){erService.delUser(new User().setId(id));return userList(request);}@RequestMapping("/getUser/{id}")public ModelAndView getUser(@PathVariable("id") String id){ User user = erService.getUserById(newUser().setId(id));ModelAndView mv = new ModelAndView("updateUser");mv.addObject("user",user);return mv;}@RequestMapping("/updateUser")public ModelAndView editUser(User user,HttpServletRequest request){System.out.println("编辑: "+user);erService.editUser(user);return userList(request);}}BaseController.javapackage com.liuzd.sj.web;import javax.servlet.http.HttpServletRequest;import com.liuzd.page.Page;import com.liuzd.page.PageState;import com.liuzd.page.PageUtil;/***Title:*Description:*Copyright: Copyright (c) 2011*Company:/*Makedate:2011-5-23 下午03:31:03* @author liuzidong* @version 1.0* @since 1.0**/public class BaseController {/*** oracel的三层分页语句* 子类在展现数据前,进行分页计算!* @param querySql 查询的SQL语句,未进行分页* @param totalCount 根据查询SQL获取的总条数* @param columnNameDescOrAsc 列名+排序方式 : ID DESC or ASC*/protected Page executePage(HttpServletRequest request,String querySql,Long totalCount,String columnNameDescOrAsc){String oracleSql =PageUtil.createQuerySql(querySql,columnNameDescOrAsc);if(null == totalCount){totalCount = 0L;}/**页面状态,这个状态是分页自带的,与业务无关*/String pageAction = request.getParameter("pageAction");String value = request.getParameter("pageKey");/**获取下标判断分页状态*/int index = PageState.getOrdinal(pageAction);Page page = null;/*** index < 1 只有二种状态* 1 当首次调用时,分页状态类中没有值为 NULL 返回 -1* 2 当页面设置每页显示多少条: index=0,当每页显示多少条时,分页类要重新计算* */Page sessionPage = getPage(request);if(index < 1){page =PageUtil.inintPage(oracleSql,totalCount,index,value,sessionPage);}else{page =PageUtil.execPage(index,value,sessionPage);}setSession(request,page);return page;}private Page getPage(HttpServletRequest request) {Page page =(Page)request.getSession().getAttribute(PageUtil.SESSION_PAGE_KEY);if(page == null){page = new Page();}return page;}private void setSession(HttpServletRequest request,Page page) {request.getSession().setAttribute(PageUtil.SESSION_PAGE_KEY,p age);}}UserRowMapper.javapackage com.liuzd.sj.dao;import java.sql.ResultSet;import java.sql.SQLException;import org.springframework.jdbc.core.RowMapper;import er;public class UserRowMapper implements RowMapper<User> {public UserRowMapper(){}public User mapRow(ResultSet rs, int index) throws SQLException {User user = new User(rs.getString("id"),rs.getString("name"),rs.getString("password"),rs.getString("address"),rs.getString("sex"),rs.getInt("age"));return user;}}UserDAOImpl.javapackage com.liuzd.sj.dao.impl;import java.sql.PreparedStatement;import java.sql.SQLException;import java.util.List;import javax.annotation.Resource;import org.springframework.jdbc.core.BeanPropertyRowMapper;import org.springframework.jdbc.core.PreparedStatementSetter;import org.springframework.stereotype.Repository;import erDAO;import erRowMapper;import er;@Repository("userDao")public class UserDAOImpl implements UserDAO{private static final String INSERT = "insert intousers(id,name,age,sex,address,password)VALUES(?,?,?,?,?,?)";private static final String UPDATE = "update users setname=?,age=?,sex=?,address=?,password=? where id=?";private static final String GET = "select * from users where id=?";private static final String CHECK = "select count(1) from users where name=? and password=?";private static final String SELECT = "select * from users";private static final String DEL = "delete users where id=?";private org.springframework.jdbc.core.JdbcTemplate jdbcTemplate;public org.springframework.jdbc.core.JdbcTemplate getJdbcTemplate() {return jdbcTemplate;}@Resourcepublic void setJdbcTemplate(org.springframework.jdbc.core.JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;}public void addUser(final User user) {getJdbcTemplate().update(INSERT, new PreparedStatementSetter(){public void setValues(PreparedStatement ps)throws SQLException {int i = 0;ps.setString(++i, user.getId());ps.setString(++i, user.getName());ps.setInt(++i, user.getAge());ps.setString(++i,user.getSex());ps.setString(++i,user.getAddress());ps.setString(++i,user.getPassword());}});}public int checkUserExits(User user) {return getJdbcTemplate().queryForInt(CHECK,user.getName(),user.getPassword());}public void delUser(User user) {getJdbcTemplate().update(DEL, user.getId());}public void editUser(final User user) {getJdbcTemplate().update(UPDATE, new PreparedStatementSetter(){public void setValues(PreparedStatement ps)throws SQLException {int i = 0;ps.setString(++i, user.getName());ps.setInt(++i, user.getAge());ps.setString(++i,user.getSex());ps.setString(++i,user.getAddress());ps.setString(++i,user.getPassword());ps.setString(++i, user.getId());}});}public List<User> getAllUser() {return getJdbcTemplate().query(SELECT, new BeanPropertyRowMapper<User>(User.class));}public User getUserById(User user) {return getJdbcTemplate().queryForObject(GET, new UserRowMapper(),user.getId());}public int pageCounts(String querySql) {return getJdbcTemplate().queryForInt("select count(1) from("+querySql+")");}public List<User> pageList(String querySql) {return getJdbcTemplate().query(querySql, new UserRowMapper());}}UserDAOImpl2.javapackage com.liuzd.sj.dao.impl;import java.util.List;import java.util.Map;import javax.annotation.Resource;import org.springframework.jdbc.core.BeanPropertyRowMapper;import org.springframework.stereotype.Repository;import erDAO;import er;import com.liuzd.util.BeanToMapUtil;@Repository("userDao2")public class UserDAOImpl2 implements UserDAO{private static final String INSERT = "insert intousers(id,name,age,sex,address,password)VALUES(:id,:name,:age,:sex,:ad dress,:password)";private static final String UPDATE = "update users setname=:name,age=:age,sex=:sex,address=:address,password=:password where id=:id";private static final String GET = "select * from users where id=?";private static final String CHECK = "select count(1) from users where name=? and password=?";private static final String SELECT = "select * from users";private static final String DEL = "delete users where id=?";privateorg.springframework.jdbc.core.simple.SimpleJdbcTemplate simpleJdbcTemplate;public org.springframework.jdbc.core.simple.SimpleJdbcTemplate getSimpleJdbcTemplate() {return simpleJdbcTemplate;}@Resourcepublic void setSimpleJdbcTemplate(org.springframework.jdbc.core.simple.SimpleJdbcTemplate simpleJdbcTemplate) {this.simpleJdbcTemplate = simpleJdbcTemplate;}public void addUser(final User user) {Map<String,Object> userMap =BeanToMapUtil.beanToMap(user);getSimpleJdbcTemplate().update(INSERT, userMap);}public int checkUserExits(User user) {return getSimpleJdbcTemplate().queryForInt(CHECK, user.getName(),user.getPassword());}public void delUser(User user) {getSimpleJdbcTemplate().update(DEL, user.getId());}public void editUser(final User user) {Map<String,Object> userMap =BeanToMapUtil.beanToMap(user);getSimpleJdbcTemplate().update(UPDATE, userMap);}public List<User> getAllUser() {return getSimpleJdbcTemplate().query(SELECT, new BeanPropertyRowMapper<User>(User.class));}public User getUserById(User user) {return getSimpleJdbcTemplate().queryForObject(GET, new BeanPropertyRowMapper<User>(User.class),user.getId());}public int pageCounts(String querySql) {return getSimpleJdbcTemplate().queryForInt("select count(1) from("+querySql+")");}public List<User> pageList(String querySql) {return getSimpleJdbcTemplate().query(querySql, new BeanPropertyRowMapper<User>(User.class));}}springmvc.xml<?xml version="1.0" encoding="UTF-8" ?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:p="/schema/p"xmlns:context="/schema/context"xmlns:mvc="/schema/mvc"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans-3.0.xsd/schema/context/schema/context/spring-context-3.0.xsd /schema/mvc/schema/mvc/spring-mvc-3.0.xsd"><!--自动搜索@Controller标注的类用于指明系统从哪个路径下寻找controller,然后提前初始化这些对象。
SpringBoot:实现MyBatis分页综合概述想必⼤家都有过这样的体验,在使⽤Mybatis时,最头痛的就是写分页了,需要先写⼀个查询count的select语句,然后再写⼀个真正分页查询的语句,当查询条件多了之后,会发现真的不想花双倍的时间写 count 和 select,幸好我们有 pagehelper 分页插件,pagehelper 是⼀个强⼤实⽤的 MyBatis 分页插件,可以帮助我们快速的实现MyBatis分页功能,⽽且pagehelper有个优点是,分页和Mapper.xml完全解耦,并以插件的形式实现,对Mybatis执⾏的流程进⾏了强化,这有效的避免了我们需要直接写分页SQL语句来实现分页功能。
那么,接下来我们就来⼀起体验下吧。
实现案例接下来,我们就通过实际案例来讲解如何使⽤pagehelper来实现MyBatis分页,为了避免重复篇幅,此篇教程的源码基于《》⼀篇的源码实现,读者请先参考并根据教程链接先⾏获取基础源码和数据库内容。
添加相关依赖⾸先,我们需要在 pom.xml ⽂件中添加分页插件依赖包。
pom.xml<!-- pagehelper --><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.2.5</version></dependency>添加相关配置然后在 application.yml 配置⽂件中添加分页插件有关的配置。
application.yml# pagehelperpagehelper:helperDialect: mysqlreasonable: truesupportMethodsArguments: trueparams: count=countSql编写分页代码⾸先,在 DAO 层添加⼀个分页查找⽅法。
解决mybatisplus分页查询有条数,total和pages都是零的问题⼀. 问题还原1. Controller代码部分Page<FixedAssetsEntity> pageForPlus = getPage();Page<FixedAssetsEntity> fixedAssetsEntityPage = fixedAssetsService.selectPage(pageForPlus);2.spring-mybatis.xml中的sqlSessionFactory配置<bean id="sqlSessionFactory"class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean"><!-- 配置数据源 --><property name="dataSource" ref="dataSource" /><!-- ⾃动扫描 Xml ⽂件位置 --><property name="mapperLocations" value="classpath*:mapping/**/*.xml" /><!-- 配置 Mybatis 配置⽂件(可⽆) --><property name="configLocation" value="classpath:mybatis-config.xml" /><!-- 配置包别名,⽀持通配符 * 或者 ; 分割 --><property name="typeAliasesPackage" value="com.syb.dto,com.syb.sys.entity" /><!-- 枚举属性配置扫描,⽀持通配符 * 或者 ; 分割 --><!-- <property name="typeEnumsPackage" value="com.baomidou.springmvc.entity.*.enums"/> --><!-- 以上配置和传统 Mybatis ⼀致 --><!-- MP 全局配置注⼊ --><property name="globalConfig" ref="globalConfig" /></bean>打断点查看fixedAssetsEntityPage,records条⽬正确,但是total和pages都是0⼆. 解决查阅官⽅⽂档发现,缺少了分页插件的配置,在sqlSessionFactory中添加分页插件,添加后为<bean id="sqlSessionFactory"class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean"><!-- 配置数据源 --><property name="dataSource" ref="dataSource" /><!-- ⾃动扫描 Xml ⽂件位置 --><property name="mapperLocations" value="classpath*:mapping/**/*.xml" /><!-- 配置 Mybatis 配置⽂件(可⽆) --><property name="configLocation" value="classpath:mybatis-config.xml" /><!-- 配置包别名,⽀持通配符 * 或者 ; 分割 --><property name="typeAliasesPackage" value="com.syb.dto,com.syb.sys.entity" /><!-- 枚举属性配置扫描,⽀持通配符 * 或者 ; 分割 --><!-- <property name="typeEnumsPackage" value="com.baomidou.springmvc.entity.*.enums"/> --><!-- 以上配置和传统 Mybatis ⼀致 --><!-- MP 全局配置注⼊ --><property name="plugins"><array><!-- 分页插件配置 --><bean id="paginationInterceptor" class="com.baomidou.mybatisplus.plugins.PaginationInterceptor"><property name="dialectType" value="mysql" /></bean></array></property><property name="globalConfig" ref="globalConfig" /></bean>运⾏程序,打断点查看,total和page已经正常显⽰补充知识:mybatisPlus分页查询多次查到相同数据的问题⼀、问题描述使⽤ mybatisPlus 3.1.0,在同⼀个⽅法内,多次调⽤同⼀个⽅法进⾏分页查询,每次查询的分页页码递增,结果每次查到的数据都⼀样。
Mybatis-Plus实现分页查询⽬录Mybatis-Plus实现分页查询技术概述分页查询是⼀项常⽤的数据库查询⽅法,⽽使⽤Mybatis-Plus的分页插件,可以为你省去更多的时间去编写复杂的数据库语句,当然,前提是你还是要懂得⼀些数据库查询语句以及Mybatis-Plus的常⽤⽅法。
之所以学习该技术,也是因为在软⼯实践中有分页查询的需求,为了能够加快开发效率,所以选择了使⽤分页插件。
难点:需要注意Mybatis-Plus不同版本的要求不同;对Mybatis-Plus的相关⽅法还是需要进⾏学习。
技术详述配置分页插件1、spring和mybatis-plus整合<!-- spring xml ⽅式 --><property name="plugins"><array><bean class="com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor"><property name="sqlParser" ref="⾃定义解析类、可以没有"/><property name="dialectClazz" value="⾃定义⽅⾔类、可以没有"/><!-- COUNT SQL 解析.可以没有 --><property name="countSqlParser" ref="countSqlParser"/></bean></array></property><bean id="countSqlParser" class="com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize"><!-- 设置为 true 可以优化部分 left join 的sql --><property name="optimizeJoin" value="true"/></bean>2、spring boot和mybatis-plus整合//Spring boot⽅式@Configuration@MapperScan("mapper包名")public class MybatisPlusConfig {// 旧版@Beanpublic PaginationInterceptor paginationInterceptor() {PaginationInterceptor paginationInterceptor = new PaginationInterceptor();// 设置请求的页⾯⼤于最⼤页后操作, true调回到⾸页,false 继续请求默认false// paginationInterceptor.setOverflow(false);// 设置最⼤单页限制数量,默认 500 条,-1 不受限制// paginationInterceptor.setLimit(500);// 开启 count 的 join 优化,只针对部分 left joinpaginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));return paginationInterceptor;}// 最新版@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));return interceptor;}}⾃定义分页1、如果你的mapper没有继承BaseMapperUserMapper.java ⽅法内容public interface UserMapper {//可以继承或者不继承BaseMapper/*** <p>* 查询 : 根据state状态查询⽤户列表,分页显⽰* </p>** @param page 分页对象,xml中可以从⾥⾯进⾏取值,传递参数 Page 即⾃动分页,必须放在第⼀位(你可以继承Page实现⾃⼰的分页对象)* @param state 状态* @return 分页对象*/IPage<User> selectPageVo(Page<?> page, Integer state);}UserMapper.xml 等同于编写⼀个普通 list 查询,mybatis-plus ⾃动替你分页<!-- 下⾯给出⼀个简单的查询例⼦<select>标签就是表⽰查询,id属性是唯⼀标识符,注意要与你的mapper类的⽅法名⼀⼀对应,resultType就是获取的数据将被封装成的类型,关于mybatis的mapper.xml的语法、属性有很多种,这<select id="selectPageVo" resultType="erVo">SELECT id,name FROM user WHERE state=#{state}</select>UserServiceImpl.java 调⽤分页⽅法public IPage<User> selectUserPage(Page<User> page, Integer state) {// 不进⾏ count sql 优化,解决 MP ⽆法⾃动优化 SQL 问题,这时候你需要⾃⼰查询 count 部分// page.setOptimizeCountSql(false);// 当 total 为⼩于 0 或者设置 setSearchCount(false) 分页插件不会进⾏ count 查询// 要点!! 分页返回的对象与传⼊的对象是同⼀个return userMapper.selectPageVo(page, state);}需要注意的是:如果返回类型是 IPage 则⼊参的 IPage 不能为null,因为返回的IPage == ⼊参的IPage如果返回类型是 List 则⼊参的 IPage 可以为 null(为 null 则不分页),但需要你⼿动⼊参的IPage.setRecords(返回的 List);如果 xml 需要从 page ⾥取值,需要 page.属性获取。
mybatis分页查询语句MyBatis是一个开源的持久层框架,提供了简化数据库访问的功能。
在实际应用中,我们常常需要对数据库进行分页查询,以便在大量数据中快速定位所需信息。
使用MyBatis进行分页查询可以通过两种方式实现:基于数据库的分页和基于内存的分页。
1. 基于数据库的分页查询基于数据库的分页查询是通过在SQL语句中使用LIMIT关键字来实现的。
LIMIT关键字可以指定查询结果的起始位置和返回的行数。
例如,下面的SQL语句可以查询从第10行开始的10条记录:```SELECT * FROM table_name LIMIT 10, 10;```其中,10表示起始位置,10表示返回的行数。
2. 基于内存的分页查询基于内存的分页查询是通过将查询结果全部加载到内存中,然后在内存中进行分页操作来实现的。
这种方式适用于数据量较小的情况。
在MyBatis中,可以通过设置fetchSize属性来控制每次从数据库中读取的记录数,然后在内存中进行分页操作。
3. 使用RowBounds进行分页查询除了上述两种方式,MyBatis还提供了一种更简洁的分页查询方式,即使用RowBounds进行分页查询。
RowBounds是MyBatis框架中的一个辅助类,用于指定查询结果的起始位置和返回的行数。
在SQL映射文件中,可以使用RowBounds来指定分页参数。
例如,下面的代码演示了如何使用RowBounds进行分页查询:```List<User> getUsers(SqlSession sqlSession, int offset, int limit) {RowBounds rowBounds = new RowBounds(offset, limit);return sqlSession.selectList("getUserList", null, rowBounds); }```其中,getUserList是SQL映射文件中定义的查询语句的ID。
private Date createdate;private Date lastlogintime;private List<Role> roleList;public List<Role> getRoleList() {return roleList;}public void setRoleList(List<Role> roleList) {this.roleList = roleList;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUname() {return uname;}public void setUname(String uname) {this.uname = uname == null ? null : uname.trim();}public String getPwd() {return pwd;}public void setPwd(String pwd) {this.pwd = pwd == null ? null : pwd.trim();}public String getName() {return name;}public void setName(String name) { = name == null ? null : name.trim();}public Integer getSex() {return sex;}public void setSex(Integer sex) {this.sex = sex;}public String getPhone() {return phone;}public void setPhone(String phone) {this.phone = phone == null ? null : phone.trim();}public String getCompany() {return company;}public void setCompany(String company) {pany = company == null ? null : company.trim(); }public String getJobtitle() {return jobtitle;}public void setJobtitle(String jobtitle) {this.jobtitle = jobtitle == null ? null : jobtitle.trim();}public String getBirth() {return birth;}public void setBirth(String birth) {this.birth = birth == null ? null : birth.trim();private boolean isFirstPage = false;是否为最后⼀页private boolean isLastPage = false;是否有前⼀页private boolean hasPreviousPage = false;是否有下⼀页private boolean hasNextPage = false;导航页码数private int navigatePages;所有导航页号private int[] navigatepageNums;View Code。
mybatis-plus分页查询在springboot中整合mybatis-plus 按照官⽅⽂档进⾏的配置: 引⼊依赖:1<!-- 引⼊mybatisPlus -->2 <dependency>3<groupId>com.baomidou</groupId>4<artifactId>mybatis-plus-boot-starter</artifactId>5<version>3.2.0</version>6</dependency>7<!-- 引⼊mysql驱动包 -->8<dependency>9<groupId>mysql</groupId>10<artifactId>mysql-connector-java</artifactId>11<version>5.1.27</version>12</dependency>13<!-- 引⼊Druid依赖,阿⾥巴巴所提供的数据源 -->14<dependency>15<groupId>com.alibaba</groupId>16<artifactId>druid</artifactId>17<version>1.0.29</version>18 </dependency> 在application.yml配置1 spring:2 datasource:3 type: com.alibaba.druid.pool.DruidDataSource4 driver-class-name: com.mysql.jdbc.Driver5 url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-86 username: root7 password: 123456 在启动类上⾯添加@MapperScan注解,扫描mapper包1 @SpringBootApplication2 @MapperScan("com.qiao.demo02.mapper")3public class SpringbootDemo02Application {45public static void main(String[] args) {6 SpringApplication.run(SpringbootDemo02Application.class, args);7 }89 } 新建User和UserMapper user类1 @Data2public class User {3 @TableId4private Integer userId;5private String userName;6private Integer userAge;7private String userEmail;8 }View Code UserMapper接⼝1public interface UserMapper extends BaseMapper<User> {23 }View Code 最重要的是继承BaseMapper<E>接⼝:⾥⾯声明了很强⼤的CRUD⽅法1public interface BaseMapper<T> extends Mapper<T> {2int insert(T entity);34int deleteById(Serializable id);56int deleteByMap(@Param("cm") Map<String, Object> columnMap);78int delete(@Param("ew") Wrapper<T> wrapper);910int deleteBatchIds(@Param("coll") Collection<? extends Serializable> idList);1112int updateById(@Param("et") T entity);1314int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper);1516 T selectById(Serializable id);1718 List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> idList);1920 List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);2122 T selectOne(@Param("ew") Wrapper<T> queryWrapper);2324 Integer selectCount(@Param("ew") Wrapper<T> queryWrapper);2526 List<T> selectList(@Param("ew") Wrapper<T> queryWrapper);2728 List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> queryWrapper);2930 List<Object> selectObjs(@Param("ew") Wrapper<T> queryWrapper);3132 IPage<T> selectPage(IPage<T> page, @Param("ew") Wrapper<T> queryWrapper);3334 IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param("ew") Wrapper<T> queryWrapper);35 }View Code分页查询 这点官⽅⽂档讲的也很详细: 新建⼀个config包,在⾥⾯建⼀个MybatisPlus配置类返回⼀个分页拦截器1package com.qiao.demo02.config;23 @Configuration4 @ConditionalOnClass(value = {PaginationInterceptor.class})5public class MybatisPlusConfig {6 @Bean7public PaginationInterceptor paginationInterceptor() {8 PaginationInterceptor paginationInterceptor = new PaginationInterceptor();9return paginationInterceptor;10 }11 } 这样就能使⽤mybatis的分页功能了 Junit测试1 @Resource2private UserMapper userMapper;3 @Test4public void queryUserForPage(){5 IPage<User> userPage = new Page<>(2, 2);//参数⼀是当前页,参数⼆是每页个数6 userPage = userMapper.selectPage(userPage, null);7 List<User> list = userPage.getRecords();8for(User user : list){9 System.out.println(user);10 }11 } Controller返回json串 先定义⼀个包装类UserVo,⽤来保存分页所需要的数据1package com.qiao.demo02.vo;23 @Data4public class UserVo {5private Integer current;6private Integer size;7private Long total;8private List<User> userList;9 } 然后在控制器编写代码,这⾥省略了service层,实际开发业务代码写在service层,Controller只负责:接受参数、调⽤service层⽅法处理业务逻辑,返回结果 Controller类贴上了@RestController注解1 @GetMapping("queryUser")2public UserVo queryList(Integer current, Integer size) {3/**4 * 这些代码应该写在service层5*/6 UserVo userVo = new UserVo();7 IPage<User> page = new Page<>(current, size);8 userMapper.selectPage(page, null);9 userVo.setCurrent(current);10 userVo.setSize(size);11 userVo.setTotal(page.getTotal());12 userVo.setUserList(page.getRecords());13return userVo;14 } 附上结果,前端直接处理json数据即可。
Spring整合Mybatis之分页插件使⽤【分页插件项⽬中的正式代码⼀共有个5个Java⽂件,这5个⽂件的说明如下】Page<E>[必须]:分页参数类,该类继承ArrayList,虽然分页查询返回的结果实际类型是Page<E>,但是可以完全不出现所有的代码中,可以直接当成List使⽤。
返回值不建议使⽤Page,建议仍然⽤List。
如果需要⽤到分页信息,使⽤下⾯的PageInfo类对List进⾏包装即可。
PageHelper[必须]:分页插件拦截器类,对Mybatis的拦截在这个类中实现。
PageInfo[可选]:Page<E>的包装类,包含了全⾯的分页属性信息。
SqlParser[可选]:提供⾼效的count查询sql。
主要是智能替换原sql语句为count(*),去除不带参数的order by语句。
需要jsqlparser-0.9.1.jar⽀持。
SqlUtil[必须]:分页插件⼯具类,分页插件逻辑类,分页插件的主要实现⽅法都在这个类中。
使⽤步骤(基于maven):1、添加maven依赖<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>3.4.2</version></dependency><dependency><groupId>com.github.jsqlparser</groupId><artifactId>jsqlparser</artifactId><version>0.9.1</version></dependency>2、配置PageHelper拦截器插件(2种⽅法)⽅法⼀:a : 在mybatis-config.xml中配置插件<plugins><!-- com.github.pagehelper为PageHelper类所在包名 --><plugin interceptor="com.github.pagehelper.PageHelper"><!-- 数据库类型,没有默认值,此项必填,⼀般就配置这⼀个参数 --><property name="dialect" value="mysql"/><!-- 该参数默认为false --><!-- 设置为true时,会将RowBounds第⼀个参数offset当成pageNum页码使⽤ --><!-- 和startPage中的pageNum效果⼀样--><property name="offsetAsPageNum" value="true"/><!-- 该参数默认为false --><!-- 设置为true时,使⽤RowBounds分页会进⾏count查询 --><property name="rowBoundsWithCount" value="true"/><!-- 设置为true时,如果pageSize=0或者RowBounds.limit = 0就会查询出全部的结果 --><!-- (相当于没有执⾏分页查询,但是返回结果仍然是Page类型)--><property name="pageSizeZero" value="true"/><!-- 3.3.0版本可⽤ - 分页参数合理化,默认false禁⽤ --><!-- 启⽤合理化时,如果pageNum<1会查询第⼀页,如果pageNum>pages会查询最后⼀页 --><!-- 禁⽤合理化时,如果pageNum<1或pageNum>pages会返回空数据 --><property name="reasonable" value="true"/></plugin></plugins>b:在applicationContext-mybatis.xml中引⼊mybatis⽂件<!-- 配置sqlSessionFactory整合MyBatis的Bean组件 --><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"></property><property name="configLocation" value="classpath:mybatis-config.xml"></property><property name="typeAliasesPackage" value="com.del.pojo"></property></bean>⽅法⼆:在applicationContext-mybatis.xml中整合配置拦截器插件<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"/><property name="mapperLocations"><array><value>classpath:mapper/*.xml</value></array></property><property name="typeAliasesPackage" value="com.isea533.ssm.model"/><property name="plugins"><array><bean class="com.github.pagehelper.PageHelper"><property name="properties"><value>dialect=hsqldbreasonable=true</value></property></bean></array></property></bean>3、在代码中使⽤PageHelper分页controller层使⽤:/** 展⽰⽤户列表管理*/@RequestMapping(value="/user")public String doUserList(@RequestParam(value="currentPage")String currentPage,Model model){ if(Integer.parseInt(currentPage)==1){PageHelper.startPage(1,7);}PageHelper.startPage(Integer.parseInt(currentPage),7);List<User> userlist = userService.findUserList();PageInfo<User> info = new PageInfo<User>(userlist);/*System.out.println("totol======="+info.getTotal());System.out.println("EndRow======="+info.getEndRow());System.out.println("FirstPage======="+info.getFirstPage());System.out.println("LastPage======="+info.getLastPage());System.out.println("NavigatePages======="+info.getNavigatePages());System.out.println("NavigatepageNums======="+info.getNavigatepageNums());System.out.println("PageSize======="+info.getPageSize());System.out.println("Size======="+info.getSize());System.out.println("PrePage======="+info.getPrePage());System.out.println("StartRow======="+info.getStartRow());System.out.println("Pages======="+info.getPages());System.out.println("OrderBy======="+info.getOrderBy());System.out.println("NextPage======="+info.getNextPage());System.out.println("List======="+info.getList());System.out.println("LastPage======="+info.getLastPage());System.out.println("FirstPage======="+info.getFirstPage());System.out.println("isIsFirstPage()======="+info.isIsFirstPage());System.out.println("isHasNextPage()======="+info.isHasNextPage());System.out.println("isHasPreviousPage()======="+info.isHasPreviousPage());System.out.println("PageNum()======="+info.getPageNum());*///PageInfo<T> pageInfo = new PageInfo(userlist);//mView.addObject("userlist", userlist);//mView.setViewName("manager/user");model.addAttribute("userlist", userlist);model.addAttribute("page", info);return "manager/user.jsp";}Jsp页⾯:[重要说明]1:只有紧跟在PageHelper.startPage⽅法后的第⼀个Mybatis的查询(Select⽅法)⽅法会被分页。
MyBatis高级查询与分页一课程介绍●高级查询1 高级查询的概念2 #与$的区别3 使用代码完成高极查询4 使用MyBatis完成高级查询5 Web页面完成高级查询●分页功能1 真分页与假分页2 分页的设计原理3 后台完成分页功能4 前台完成分页●高级查询与分页的集成(难点)二高级查询2.1 高级查询的概念什么叫高级查询?为什么我们需要高级查询?在我们的课程系统中,高级查询就是多条件查询。
大家在上网的时候一定遇到很多这种相应的查询功能。
它可以帮我们更快更好的找到需要的信息与资源。
试想一下,以后咱们做一个客户管理系统。
一张表中有10000多个客户,我们是让用户从10000多个人中去找,还是根据一些条件(如名称,性别等)过一次过滤查询就找到。
下面为一些经常看到的高级查询:以咱们的Product这个货品为例:如果我们现在要根据这个货品的名称与价格做高级查询应该是怎么样的呢?下图分析:根据上面的分析我们可以得出以下结论:1 高级查询就是在查询基础上添加后面的where条件2 根据不同的情况,where后面的条件都不同的3 提供的过滤条件越多,我们查询的排列组合也就越多综上可以看到,我们需要提供相应的查询字段,但是会不会用到,就看客户自己。
但是由于这么多排列组合,我们不可能把所有的Sql全部准备好。
因此,咱们必需要能生成动态SQL(说白了就是根据用户选择条件来拼接字符串(where语句))怎么拼接呢?用户选择了,这个字段就不为空,当这个字段不为空的时候,我们就在where后的查询加上这个条件过滤2.2 使用代码完成高级查询在完成高级查询之前,我们要准备一个Query对象。
为什么要准备这个Query对象呢?1 查询的条件是有很多的,如果我们不封装成对象,传多个参数的话很麻烦,也不利于以后的修改与扩展2 调用MyBatis中配置的sql的时候,只能传一个参数,那咱们只有把所有参数都封装到一个对象中,然后把这个对象传递过去Query对象就是咱们的查询对象,创建Query对象是有一定的规范的:它应该在一个query包中,这个包与domain同级,名称为XxxQuery---Xxx表示实体的名称如:StudentQuery/ProductQuery在Query中我们准备好相应的查询条件字段与属性(Query就是一个JavaBean)根据上面的分析,咱们为Product准备相应的Query对象:然后咱们在dao层准备一个高级查询的方法直接传入ProductQuery,如下:List<Product> queryAll(ProductQuery query);我们接着完成这个queryAll的功能,包含xml中也搞定相应的代码。
SSM框架条件分页查询研究与实现唐权【摘要】本文应用PageHelper技术与SSM框架进行整合,实现带条件分页查询,为项目开发中数据维护提供了快速的解决方案.【期刊名称】《四川职业技术学院学报》【年(卷),期】2019(029)001【总页数】5页(P139-143)【关键词】SSM框架;PageHelper;条件分页查询【作者】唐权【作者单位】四川职业技术学院,遂宁 629000【正文语种】中文【中图分类】TP3110.引言SSM(Spring+SpringMVC+Mybatis)框架是一个非常优秀的Java EE轻量级框架,应用于Java EE企业级项目的开发中,成为当前主流Web应用程序开发框架。
在Web应用项目中数据维护是基础性工作,具有非常重要的作用,也是工作量较大的环节,主要包括对数据的查询、增加、删除与修改。
项目开发中如何减轻这些工作量,实现方式与标准统一,节省开发时间,提高工作效率具有重要的作用。
本文就数据维护中的条件分页查询,把PageHelper技术整合到SSM框架中,对SSM框架以最小的侵入,实现快速分页查询。
1.SSM框架概述SSM框架包括三个部分,分别是Spring技术、SpringMVC技术、Mybatis技术。
Spring技术是整个框架的核心,通过Spring依赖注入模式,把SpringMVC与MyBatis框架整合在一起。
其中SpringMVC主要实现模块的 MVC(Model View Controller)功能,负责把用户的请求根据映射关系提交到对应的控制器;MyBatis实现数据访问层的功能,通过ORM映射与数据库进行数据交互,读取数据库的数据或保存数据实现数据持久化;业务逻辑层也叫服务层,实现应用程序的业务逻辑,向上给控制层的提供服务,向下调用数据访问层和数据库进行数据交互。
SSM框架整合后数据查询业务流程各模块对象序列图如图1所示。
第一.用户通过Browser发送查询请求,被SpringMVC框架的DispatcherServlet拦截,通过请求映射关系,转到对应的控制器Con图1 SSM整合框架查询业务序列图第二.Controller根据请求的url找到对应的处理方法,在方法中调用服务层Service对应的方法查询数据。
mybatis的两种分页⽅式:RowBounds和PageHelper1.原理:拦截器。
使⽤⽅法:RowBounds:在mapper.java中的⽅法中传⼊RowBounds对象//接⼝⽅法public List<Honor> getHonorList(HashMap<String, Object> maps,RowBounds rowBounds);//调⽤⽅法RowBounds rowBounds = new RowBounds(offset, page.getPageSize()); // offset起始⾏ // limit是当前页显⽰多少条数据RowBounds rowBounds = new RowBounds(2, 2);List<Honor> honors = studentMapper.getHonorList(maps,rowBounds);Mybatis使⽤RowBounds对象进⾏分页,它是针对ResultSet结果集执⾏的内存分页,⽽⾮物理分页,可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使⽤分页插件来完成物理分页。
分页插件的基本原理是使⽤Mybatis提供的插件接⼝,实现⾃定义插件,在插件的拦截⽅法内拦截待执⾏的sql,然后重写sql,根据dialect⽅⾔,添加对应的物理分页语句和物理分页参数。
举例:select * from student,拦截sql后重写为:select t.* from (select * from student)t limit 0,102.Mybatis的插件 PageHelper 分页查询使⽤⽅法Mybatis的⼀个插件,PageHelper,⾮常⽅便mybatis分页查询。
国内⽜⼈的⼀个开源项⽬,有兴趣的可以去看源码,都有中⽂注释(ps:某些源码⼀⼤堆英⽂,痛哭流涕!)在github上仓库地址为:Mybatis-PageHelper它⽀持基本主流与常⽤的数据库,这可以在它的⽂档上看到。
Mybatis四种分页⽅式数组分页查询出全部数据,然后再list中截取需要的部分。
mybatis接⼝List<Student> queryStudentsByArray();xml配置⽂件<select id="queryStudentsByArray" resultMap="studentmapper">select * from student</select>service接⼝List<Student> queryStudentsByArray(int currPage, int pageSize);实现接⼝@Overridepublic List<Student> queryStudentsByArray(int currPage, int pageSize) {//查询全部数据List<Student> students = studentMapper.queryStudentsByArray();//从第⼏条数据开始int firstIndex = (currPage - 1) * pageSize;//到第⼏条数据结束int lastIndex = currPage * pageSize;return students.subList(firstIndex, lastIndex); //直接在list中截取}controller@ResponseBody@RequestMapping("/student/array/{currPage}/{pageSize}")public List<Student> getStudentByArray(@PathVariable("currPage") int currPage, @PathVariable("pageSize") int pageSize) { List<Student> student = StuServiceIml.queryStudentsByArray(currPage, pageSize);return student;}sql分页mybatis接⼝List<Student> queryStudentsBySql(Map<String,Object> data);xml⽂件<select id="queryStudentsBySql" parameterType="map" resultMap="studentmapper">select * from student limit #{currIndex} , #{pageSize}</select>service接⼝List<Student> queryStudentsBySql(int currPage, int pageSize);实现类public List<Student> queryStudentsBySql(int currPage, int pageSize) {Map<String, Object> data = new HashedMap();data.put("currIndex", (currPage-1)*pageSize);data.put("pageSize", pageSize);return studentMapper.queryStudentsBySql(data);}拦截器分页创建拦截器,拦截mybatis接⼝⽅法id以ByPage结束的语句package com.autumn.interceptor;import org.apache.ibatis.executor.Executor;import org.apache.ibatis.executor.parameter.ParameterHandler;import org.apache.ibatis.executor.resultset.ResultSetHandler;import org.apache.ibatis.executor.statement.StatementHandler;import org.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.plugin.*;import org.apache.ibatis.reflection.MetaObject;import org.apache.ibatis.reflection.SystemMetaObject;import java.sql.Connection;import java.util.Map;import java.util.Properties;/*** @Intercepts 说明是⼀个拦截器* @Signature 拦截器的签名* type 拦截的类型四⼤对象之⼀( Executor,ResultSetHandler,ParameterHandler,StatementHandler)* method 拦截的⽅法* args 参数,⾼版本需要加个Integer.class参数,不然会报错*/@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class})})public class MyPageInterceptor implements Interceptor {//每页显⽰的条⽬数private int pageSize;//当前现实的页数private int currPage;//数据库类型private String dbType;@Overridepublic Object intercept(Invocation invocation) throws Throwable {//获取StatementHandler,默认是RoutingStatementHandlerStatementHandler statementHandler = (StatementHandler) invocation.getTarget();//获取statementHandler包装类MetaObject MetaObjectHandler = SystemMetaObject.forObject(statementHandler);//分离代理对象链while (MetaObjectHandler.hasGetter("h")) {Object obj = MetaObjectHandler.getValue("h");MetaObjectHandler = SystemMetaObject.forObject(obj);}while (MetaObjectHandler.hasGetter("target")) {Object obj = MetaObjectHandler.getValue("target");MetaObjectHandler = SystemMetaObject.forObject(obj);}//获取连接对象//Connection connection = (Connection) invocation.getArgs()[0];//object.getValue("delegate"); 获取StatementHandler的实现类//获取查询接⼝映射的相关信息MappedStatement mappedStatement = (MappedStatement) MetaObjectHandler.getValue("delegate.mappedStatement"); String mapId = mappedStatement.getId();//statementHandler.getBoundSql().getParameterObject();//拦截以.ByPage结尾的请求,分页功能的统⼀实现if (mapId.matches(".+ByPage$")) {//获取进⾏数据库操作时管理参数的handlerParameterHandler parameterHandler = (ParameterHandler) MetaObjectHandler.getValue("delegate.parameterHandler");//获取请求时的参数Map<String, Object> paraObject = (Map<String, Object>) parameterHandler.getParameterObject();//也可以这样获取//paraObject = (Map<String, Object>) statementHandler.getBoundSql().getParameterObject();//参数名称和在service中设置到map中的名称⼀致currPage = (int) paraObject.get("currPage");pageSize = (int) paraObject.get("pageSize");String sql = (String) MetaObjectHandler.getValue("delegate.boundSql.sql");//也可以通过statementHandler直接获取//sql = statementHandler.getBoundSql().getSql();//构建分页功能的sql语句String limitSql;sql = sql.trim();limitSql = sql + " limit " + (currPage - 1) * pageSize + "," + pageSize;//将构建完成的分页sql语句赋值个体'delegate.boundSql.sql',偷天换⽇MetaObjectHandler.setValue("delegate.boundSql.sql", limitSql);}//调⽤原对象的⽅法,进⼊责任链的下⼀级return invocation.proceed();}//获取代理对象@Overridepublic Object plugin(Object o) {//⽣成object对象的动态代理对象return Plugin.wrap(o, this);}//设置代理对象的参数@Overridepublic void setProperties(Properties properties) {//如果项⽬中分页的pageSize是统⼀的,也可以在这⾥统⼀配置和获取,这样就不⽤每次请求都传递pageSize参数了。
springMVC、myBatis的物理分页和高级查询分类:JavaEE2013-06-0913:44797人阅读评论(4)收藏举报springMVCmybatis高级查询分页ajax最新项目用到springMVC和mybatis,分页其实用一个RowBounds可以实现,但是高级查询不好封装,经过反复测试,总算搞出来了,感觉封装的不是很好,有待优化和提高!原理:利用mybatis自定义插件功能,自定义一个拦截器,拦截需要分页的sql,并想办法通过BoundSql对象进行处理,大致分8步:1、获得BoundSql对象2、获取原始的写在配置文件中的SQL3、拦截到mapper中定义的执行查询方法中的参数4、解析参数,获取高级查询参数信息5、解析参数,获取查询限制条件6、根据4、5中的参数拼装并重新生成SQL语句7、将SQL设置回BoundSql对象中8、完成。
拦截器:[java]view plaincopyprint?1.package com.wtas.page.interceptor;2.3.import java.sql.Connection;4.import java.sql.PreparedStatement;5.import java.sql.ResultSet;6.import java.sql.SQLException;7.import java.util.List;8.import java.util.Map;9.import java.util.Properties;10.import java.util.Set;11.12.import javax.xml.bind.PropertyException;13.14.import org.apache.ibatis.executor.ErrorContext;15.import org.apache.ibatis.executor.ExecutorException;16.import org.apache.ibatis.executor.statement.BaseStatementHandler;17.import org.apache.ibatis.executor.statement.RoutingStatementHandler;18.import org.apache.ibatis.executor.statement.StatementHandler;19.import org.apache.ibatis.mapping.BoundSql;20.import org.apache.ibatis.mapping.MappedStatement;21.import org.apache.ibatis.mapping.ParameterMapping;22.import org.apache.ibatis.mapping.ParameterMode;23.import org.apache.ibatis.plugin.Interceptor;24.import org.apache.ibatis.plugin.Intercepts;25.import org.apache.ibatis.plugin.Invocation;26.import org.apache.ibatis.plugin.Plugin;27.import org.apache.ibatis.plugin.Signature;28.import org.apache.ibatis.reflection.MetaObject;29.import org.apache.ibatis.reflection.property.PropertyTokenizer;30.import org.apache.ibatis.scripting.xmltags.ForEachSqlNode;31.import org.apache.ibatis.session.Configuration;32.import org.apache.ibatis.type.TypeHandler;33.import org.apache.ibatis.type.TypeHandlerRegistry;34.import org.slf4j.Logger;35.import org.slf4j.LoggerFactory;36.37.import com.wtas.page.PageContext;38.import com.wtas.page.Pager;39.import com.wtas.page.Query;40.import com.wtas.utils.SystemUtil;41.42./**43.*查询分页拦截器,用户拦截SQL,并加上分页的参数和高级查询条件44.*45.*@author dendy46.*47.*/48.@Intercepts({@Signature(type=StatementHandler.class,method="prepare",args={Connection.class})})49.public class PaginationInterceptor implements Interceptor{50.51.private final Logger logger=LoggerFactory52..getLogger(PaginationInterceptor.class);53.54.private String dialect="";55.56.//暂时不需要这个参数,现在根据参数类型来判断是否是分页sql57.//private String pageMethodPattern="";58.59.public Object intercept(Invocation ivk)throws Throwable{60.if(!(ivk.getTarget()instanceof RoutingStatementHandler)){61.return ivk.proceed();62.}63.RoutingStatementHandler statementHandler=(RoutingStatementHandler)ivk64..getTarget();65.BaseStatementHandler delegate=(BaseStatementHandler)SystemUtil66..getValueByFieldName(statementHandler,"delegate");67.MappedStatement mappedStatement=(MappedStatement)SystemUtil68..getValueByFieldName(delegate,"mappedStatement");69.70.//BoundSql封装了sql语句71.BoundSql boundSql=delegate.getBoundSql();72.//获得查询对象73.Object parameterObject=boundSql.getParameterObject();74.//根据参数类型判断是否是分页方法75.if(!(parameterObject instanceof Query)){76.return ivk.proceed();77.}78.logger.debug("beginning to intercept page SQL...");79.Connection connection=(Connection)ivk.getArgs()[0];80.String sql=boundSql.getSql();81.Query query=(Query)parameterObject;82.//查询参数对象83.Pager pager=null;84.//查询条件Map85.Map<String,Object>conditions=query.getQueryParams();86.pager=query.getPager();87.//拼装查询条件88.if(conditions!=null){89.Set<String>keys=conditions.keySet();90.Object value=null;91.StringBuffer sb=new StringBuffer();92.boolean first=true;93.for(String key:keys){94.value=conditions.get(key);95.if(first){96.sb.append("where").append(key).append(value);97.first=!first;98.}else{99.sb.append("and").append(key).append(value); 100.}101.}102.sql+=sb.toString();103.}104.105.//获取查询数来的总数目106.String countSql="SELECT COUNT(0)FROM("+sql+")AS t mp";107.PreparedStatement countStmt=connection.prepareStatement( countSql);108.BoundSql countBS=new BoundSql(mappedStatement.getConfigu ration(),109.countSql,boundSql.getParameterMappings(),paramet erObject);110.setParameters(countStmt,mappedStatement,countBS,paramet erObject);111.ResultSet rs=countStmt.executeQuery();112.int count=0;113.if(rs.next()){114.count=rs.getInt(1);115.}116.rs.close();117.countStmt.close();118.119.//设置总记录数120.pager.setTotalResult(count);121.//设置总页数122.pager.setTotalPage((count+pager.getShowCount()-1) 123./pager.getShowCount());124.//放到作用于125.PageContext.getInstance().set(pager);126.127.//拼装查询参数128.String pageSql=generatePageSql(sql,pager);129.SystemUtil.setValueByFieldName(boundSql,"sql",pageSql);130.logger.debug("generated pageSql is:"+pageSql); 131.132.return ivk.proceed();133.}134.135./**136.*setting parameters137.*138.*@param ps139.*@param mappedStatement140.*@param boundSql141.*@param parameterObject142.*@throws SQLException143.*/144.private void setParameters(PreparedStatement ps,145.MappedStatement mappedStatement,BoundSql boundSql,146.Object parameterObject)throws SQLException{147.ErrorContext.instance().activity("setting parameters") 148..object(mappedStatement.getParameterMap().getId());149.List<ParameterMapping>parameterMappings=boundSql 150..getParameterMappings();151.if(parameterMappings!=null){152.Configuration configuration=mappedStatement.getConfi guration();153.TypeHandlerRegistry typeHandlerRegistry=configuratio n154..getTypeHandlerRegistry();155.MetaObject metaObject=parameterObject==null?null156.:configuration.newMetaObject(parameterObject);157.for(int i=0;i<parameterMappings.size();i++){ 158.ParameterMapping parameterMapping=parameterMappi ngs.get(i);159.if(parameterMapping.getMode()!=ParameterMode.OU T){160.Object value;161.String propertyName=parameterMapping.getProp erty();162.PropertyTokenizer prop=new PropertyTokenizer (propertyName);163.if(parameterObject==null){164.value=null;165.}else if(typeHandlerRegistry166..hasTypeHandler(parameterObject.getCla ss())){167.value=parameterObject;168.}else if(boundSql.hasAdditionalParameter(pro pertyName)){169.value=boundSql.getAdditionalParameter(pr opertyName);170.}else if(propertyName171..startsWith(ForEachSqlNode.ITEM_PREFIX)172.&&boundSql.hasAdditionalParameter(pro p.getName())){173.value=boundSql.getAdditionalParameter(pr op.getName());174.if(value!=null){175.value=configuration.newMetaObject(va lue)176..getValue(177.propertyName.substring (prop178..getName().len gth()));179.}180.}else{181.value=metaObject==null?null:metaOb ject182..getValue(propertyName);183.}184.@SuppressWarnings("unchecked")185.TypeHandler<Object>typeHandler=(TypeHandler <Object>)parameterMapping186..getTypeHandler();187.if(typeHandler==null){188.throw new ExecutorException( 189."There was no TypeHandler found fo r parameter"190.+propertyName+"of stat ement"191.+mappedStatement.getId());192.}193.typeHandler.setParameter(ps,i+1,value, 194.parameterMapping.getJdbcType()); 195.}196.}197.}198.}199.200./**201.*生成Sql语句202.*203.*@param sql204.*@param page205.*@return206.*/207.private String generatePageSql(String sql,Pager page){208.if(page!=null&&(dialect!=null||!dialect.equals("") )){209.StringBuffer pageSql=new StringBuffer();210.if("mysql".equals(dialect)){211.pageSql.append(sql);212.pageSql.append("LIMIT"+page.getCurrentResult() +","213.+page.getShowCount());214.}else if("oracle".equals(dialect)){215.pageSql.append("SELECT*FROM(SELECT t.*,ROWNUM r FROM(");216.pageSql.append(sql);217.pageSql.append(")t WHERE r<=");218.pageSql.append(page.getCurrentResult()+page.getS howCount());219.pageSql.append(")WHERE r>");220.pageSql.append(page.getCurrentResult());221.}222.return pageSql.toString();223.}else{224.return sql;225.}226.}227.228.public Object plugin(Object arg0){229.return Plugin.wrap(arg0,this);230.}231.232.public void setProperties(Properties p){233.dialect=p.getProperty("dialect");234.if(dialect==null||dialect.equals("")){235.try{236.throw new PropertyException("dialect property is n ot found!");237.}catch(PropertyException e){238. e.printStackTrace();239.}240.}241.//pageMethodPattern=p.getProperty("pageMethodPattern");242.if(dialect==null||dialect.equals("")){243.try{244.throw new PropertyException( 245."pageMethodPattern property is not found!") ;246.}catch(PropertyException e){247. e.printStackTrace();248.}249.}250.}251.252.}查询对象的封装:1、map封装查询条件2、pager对象封装查询限制条件,就是MySql中limit后的参数等附加信息[java]view plaincopyprint?1.package com.wtas.page;2.3./**4.*分页描述信息5.*6.*@author dendy7.*8.*/9.public class Pager{10.//每一页的显示条数11.private int showCount;12.//总的页数13.private int totalPage;14.//查询的数据总条数15.private int totalResult;16.//当前页17.private int currentPage;18.//从第几条开始获取数据19.@SuppressWarnings("unused")20.private int currentResult;21.22.public Pager(){23.this(1);24.}25.26.public Pager(int currentPage){27.//默认每页显示10条记录28.this(currentPage,10);29.}30.31.public Pager(int currentPage,int showCount){32.this.currentPage=currentPage;33.if(showCount>0){34.this.showCount=showCount;35.}36.//错误处理37.if(this.currentPage<1){38.this.currentPage=1;39.}40.}41.42.//只列出关键的getter和setter……43.44.public int getTotalPage(){45.//分页算法,计算总页数46.return this.totalPage;47.}48.49.public int getCurrentResult(){50.//计算从第几条获取数据51.return(currentPage-1)*showCount;52.}53.54.}[java]view plaincopyprint?1.package com.wtas.page;2.3.import java.util.Map;4.5./**6.*封装查询蚕食和查询条件7.*8.*@author dendy9.*10.*/11.public class Query{12.private Map<String,Object>queryParams;13.private Pager pager;14.15.public Map<String,Object>getQueryParams(){16.return queryParams;17.}18.19.public void setQueryParams(Map<String,Object>queryParams){20.this.queryParams=queryParams;21.}22.23.//省略getter和setter24.}控制层关键代码:[java]view plaincopyprint?1./**2.*分页时获取所有的学生3.*4.*@return5.*/6.@RequestMapping("pageStus")7.@ResponseBody8.public List<User>pageAllStudents(HttpServletRequest req){9.try{10.Query query=new Query();11.Pager pager=new Pager();12.Map<String,Object>queryParams=new HashMap<String,Object>();13.14.//获取分页参数15.String showCount=req.getParameter("showCount");16.String currentPage=req.getParameter("currentPage");17.18.if(StringUtils.hasLength(showCount)){19.pager.setShowCount(Integer.parseInt(showCount));20.}21.if(StringUtils.hasLength(currentPage)){22.pager.setCurrentPage(Integer.parseInt(currentPage));23.}24.25.//高级查询条件:学生真实姓名26.String trueNameForQuery=req.getParameter("trueNameForQuery");27.if(StringUtils.hasLength(trueNameForQuery)){28.queryParams.put("u.REAL_NAME like","'%"+trueNameForQuery29.+"%'");30.}31.32.query.setPager(pager);33.query.setQueryParams(queryParams);34.List<User>users=userService.pageUsersByRole(query);35.36.//req.setAttribute("pager",PageContext.getInstance().get());37.38.return users;39.}catch(Exception e){40.LOG.error("getAllStudents error:"+e.getMessage());41.}42.return null;43.}44.45.@RequestMapping("getPager")46.@ResponseBody47.public Pager getPager(){48.return PageContext.getInstance().get();49.}dao中的方法:[java]view plaincopyprint?1./**2.*级联查询所有某一角色的用户信息,带分页3.*4.*@param roleValue5.*@param page6.*@return7.*/8.ist<User>pageUsers(Object query);dao的Mappder.xml定义:[html]view plaincopyprint?1.<select id="pageUsers"resultMap="userMapping"parameterType="hashMap">2.SELECT DISTINCT u.*FROM T_USER u LEFT JOIN T_REL_USER_ROLE ur ON3.u.id=er_id4.LEFT JOIN T_ROLE r ON ur.role_id=r.id5.</select>页面通过javascript来异常发送请求获取数据,关键代码:[javascript]view plaincopyprint?1./**2.*处理分页3.*4.*@param curPage5.*@param id6.*/7.function page(curPage,id){8.if(curPage<=0){9.curPage=1;10.}11.12.var trueNameForQuery=$("#findByTrueNameInput").val().trim();13.14.var url=path+"/studygroup/pageStus.do";15.var thCss="class='s-th-class'";16.var tdCss="class='s-td-class'";17.$.ajax({18.type:"POST",19.url:url,20.dataType:"json",21.data:{22."id":id,23."currentPage":curPage,24."trueNameForQuery":trueNameForQuery25.},26.success:function(data){27.var json=eval(data);28.var res="<tr><th"+thCss+">选择</th>"29.+"<th"+thCss+">用户名</th>"30.+"<th"+thCss+">真实姓名</th>"31.+"<th"+thCss+">性别</th>"32.+"<th"+thCss+">学校</th>"33.+"<th"+thCss+">年级</th>"34.+"<th"+thCss+">班级</th></tr>";35.for(var i=0;i<json.length;i++){36.var userId=json[i].id;37.var name=json[i].name;38.var trueName=json[i].trueName;39.var sex=json[i].sex;40.var school="";41.if(json[i].school){42.school=json[i];43.}44.var grade="";45.if(json[i].grade){46.grade=json[i];47.}48.var clazz="";49.if(json[i].clazz){50.clazz=json[i];51.}52.res+="<tr><td align='center'"+tdCss+"><input type='checkbox'value='"+userId+"'/></td>"53.+"<td align='center'"+tdCss+">"+(name||"")+"</td>"54.+"<td align='center'"+tdCss+">"+(trueName||"")+"</td>"55.+"<td align='center'"+tdCss+">"+(sex==1?'女':'男'||"")+"</td>"56.+"<td align='center'"+tdCss+">"+school+"</td>"57.+"<td align='center'"+tdCss+">"+grade+"</td>"58.+"<td align='center'"+tdCss+">"+clazz+"</td>"59.+"</td></tr>";60.}61.$("#inviteStudentsTbl").html(res);62.//每次加载完成都要刷新分页栏数据63.freshPager(id);64.}65.});66.}67.68./**69.*重新获取分页对象,刷新分页工具栏70.*/71.function freshPager(id){72.var url=path+"/studygroup/getPager.do";73.var studyGroupId=id;74.$.ajax({75.type:"POST",76.url:url,77.dataType:"json",78.success:function(data){79.var pager=eval(data);80.var currentPage=pager.currentPage;81.//var currentResult=pager.currentResult;82.//var showCount=pager.showCount;83.var totalPage=pager.totalPage;84.//var totalResult=pager.totalResult;85.86.var prePage=currentPage-1;87.var nextPage=currentPage+1;88.if(prePage<=0){89.prePage=1;90.}91.if(nextPage>totalPage){92.nextPage=totalPage;93.}94.95.$("#topPageId").attr("href","javascript:page(1,"+studyGroupId+");");96.$("#prefixPageId").attr("href","javascript:page("+prePage+","+studyGroupId+");");97.$("#nextPageId").attr("href","javascript:page("+nextPage+","+studyGroupId+");");98.$("#endPageId").attr("href","javascript:page("+totalPage+","+studyGroupId+");");99.$("#curPageId").html(currentPage);100.$("#totalPageId").html(totalPage);101.}102.});103.}104.105./**106.*按真实姓名搜索107.*/108.function findByTrueName(){109.page(1,studyGroupId);110.}end.————————————————————————————————————————————————应网友需要,贴上SystemUtil的代码:[java]view plaincopyprint?1.package mon.utils;2.3.import ng.reflect.Field;4.5.import javax.servlet.http.HttpSession;6.7.import mon.consts.SystemConst;8.import er;9.10./**11.*系统工具类,定义系统常用的工具方法12.*13.*@author dendy14.*15.*/16.public class SystemUtil{17.private SystemUtil(){18.19.}20.21./**22.*获取系统访问的相对路径,如:/WTAS23.*24.*@return25.*/26.public static String getContextPath(){27.return System.getProperty(SystemConst.SYSTEM_CONTEXT_PATH_KEY);28.}29.30./**31.*修改一个bean(源)中的属性值,该属性值从目标bean获取32.*33.*@param dest34.*目标bean,其属性将被复制到源bean中35.*@param src36.*需要被修改属性的源bean37.*@param filtNullProps38.*源bean的null属性是否覆盖目标的属性<li>true:源bean中只有为null的属性才会被覆盖<li>false39.*:不管源bean的属性是否为null,均覆盖40.*@throws IllegalArgumentException41.*@throws IllegalAccessException42.*/43.public static void copyBean(Object dest,Object src,boolean filtNullProps)44.throws IllegalArgumentException,IllegalAccessException{45.if(dest.getClass()==src.getClass()){46.//目标bean的所有字段47.Field[]destField=dest.getClass().getDeclaredFields();48.//源bean的所有字段49.Field[]srcField=src.getClass().getDeclaredFields();50.for(int i=0;i<destField.length;i++){51.String destFieldName=destField[i].getName();52.String destFieldType=destField[i].getGenericType().toString();53.for(int n=0;n<srcField.length;n++){54.String srcFieldName=srcField[n].getName();55.String srcFieldType=srcField[n].getGenericType()56..toString();57.//String srcTypeName=58.//srcField[n].getType().getSimpleName();59.if(destFieldName.equals(srcFieldName)60.&&destFieldType.equals(srcFieldType)){61.destField[i].setAccessible(true);62.srcField[n].setAccessible(true);63.Object srcValue=srcField[n].get(src);64.Object destValue=destField[i].get(dest);65.if(filtNullProps){66.//源bean中的属性已经非空,则不覆盖67.if(srcValue==null){68.srcField[n].set(src,destValue);69.}70.}else{71.srcField[n].set(dest,srcValue);72.}73.}74.}75.}76.}77.}78.79./**80.*根据字段的值获取该字段81.*82.*@param obj83.*@param fieldName84.*@return85.*/86.public static Field getFieldByFieldName(Object obj,String fieldName){87.for(Class<?>superClass=obj.getClass();superClass!=Object.class;superClass=superClass88..getSuperclass()){89.try{90.return superClass.getDeclaredField(fieldName);91.}catch(NoSuchFieldException e){92.}93.}94.return null;95.}96.97./**98.*获取对象某一字段的值99.*100.*@param obj101.*@param fieldName102.*@return103.*@throws SecurityException104.*@throws NoSuchFieldException105.*@throws IllegalArgumentException106.*@throws IllegalAccessException107.*/108.public static Object getValueByFieldName(Object obj,String fi eldName)109.throws SecurityException,NoSuchFieldException,110.IllegalArgumentException,IllegalAccessException{ 111.Field field=getFieldByFieldName(obj,fieldName);112.Object value=null;113.if(field!=null){114.if(field.isAccessible()){115.value=field.get(obj);116.}else{117.field.setAccessible(true);118.value=field.get(obj);119.field.setAccessible(false);120.}121.}122.return value;123.}124.125./**126.*向对象的某一字段上设置值127.*128.*@param obj129.*@param fieldName130.*@param value131.*@throws SecurityException132.*@throws NoSuchFieldException133.*@throws IllegalArgumentException134.*@throws IllegalAccessException135.*/136.public static void setValueByFieldName(Object obj,String fiel dName,137.Object value)throws SecurityException,NoSuchFieldExc eption,138.IllegalArgumentException,IllegalAccessException{ 139.Field field=obj.getClass().getDeclaredField(fieldName);140.if(field.isAccessible()){141.field.set(obj,value);142.}else{143.field.setAccessible(true);144.field.set(obj,value);145.field.setAccessible(false);146.}147.}148.149./**150.*从session中获取当前登录用户151.*152.*@param session153.*@return154.*/155.public static User getLoginUser(HttpSession session){156.return(User)session.getAttribute(ER_IN_SES SION);157.}158.159./**160.*@Description设置更新信息后的登录用户给session161.*@param user登录用户162.*@param session session163.*/164.public static void setUser(User user,HttpSession session){ 165.session.setAttribute(ER_IN_SESSION,user); 166.}167.}。
MyBatis-Plus实现2种分页⽅法(QueryWrapper查询分页和SQL查询分页)⽬录1 MyBatisPlusConfig2 UserPagination3 Mapper3.1 UserMapper.java3.2 UserMapper.xml4 Service4.1 UserService4.2 UserServiceImpl5 UserController6 调试结果6.1 QueryWrapper查询分页6.2 SQL查询分页1 MyBatisPlusConfigMyBatisPlus配置类。
package com.config;import com.baomidou.mybatisplus.annotation.DbType;import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;import org.springframework.context.annotation.*;/*** MyBatisPlus配置类*/@Configurationpublic class MyBatisPlusConfig {/*** MyBatisPlus拦截器(⽤于分页)*/@Beanpublic MybatisPlusInterceptor paginationInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();//添加MySQL的分页拦截器interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}}2 UserPagination⽤户查询条件类。
springMVC、myBatis的物理分页和高级查询分类:JavaEE 2013-06-09 13:44 797人阅读评论(4) 收藏举报springMVCmybatis高级查询分页ajax最新项目用到springMVC和mybatis,分页其实用一个RowBounds可以实现,但是高级查询不好封装,经过反复测试,总算搞出来了,感觉封装的不是很好,有待优化和提高!原理:利用mybatis自定义插件功能,自定义一个拦截器,拦截需要分页的sql,并想办法通过BoundSql对象进行处理,大致分8步:1、获得BoundSql对象2、获取原始的写在配置文件中的SQL3、拦截到mapper中定义的执行查询方法中的参数4、解析参数,获取高级查询参数信息5、解析参数,获取查询限制条件6、根据4、5中的参数拼装并重新生成SQL语句7、将SQL设置回BoundSql对象中8、完成。
拦截器:[java]view plaincopyprint?1.package com.wtas.page.interceptor;2.3.import java.sql.Connection;4.import java.sql.PreparedStatement;5.import java.sql.ResultSet;6.import java.sql.SQLException;7.import java.util.List;8.import java.util.Map;9.import java.util.Properties;10.import java.util.Set;11.12.import javax.xml.bind.PropertyException;13.14.import org.apache.ibatis.executor.ErrorContext;15.import org.apache.ibatis.executor.ExecutorException;16.import org.apache.ibatis.executor.statement.BaseStatementHandler;17.import org.apache.ibatis.executor.statement.RoutingStatementHandler;18.import org.apache.ibatis.executor.statement.StatementHandler;19.import org.apache.ibatis.mapping.BoundSql;20.import org.apache.ibatis.mapping.MappedStatement;21.import org.apache.ibatis.mapping.ParameterMapping;22.import org.apache.ibatis.mapping.ParameterMode;23.import org.apache.ibatis.plugin.Interceptor;24.import org.apache.ibatis.plugin.Intercepts;25.import org.apache.ibatis.plugin.Invocation;26.import org.apache.ibatis.plugin.Plugin;27.import org.apache.ibatis.plugin.Signature;28.import org.apache.ibatis.reflection.MetaObject;29.import org.apache.ibatis.reflection.property.PropertyTokenizer;30.import org.apache.ibatis.scripting.xmltags.ForEachSqlNode;31.import org.apache.ibatis.session.Configuration;32.import org.apache.ibatis.type.TypeHandler;33.import org.apache.ibatis.type.TypeHandlerRegistry;34.import org.slf4j.Logger;35.import org.slf4j.LoggerFactory;36.37.import com.wtas.page.PageContext;38.import com.wtas.page.Pager;39.import com.wtas.page.Query;40.import com.wtas.utils.SystemUtil;41.42./**43. * 查询分页拦截器,用户拦截SQL,并加上分页的参数和高级查询条件44. *45. * @author dendy46. *47. */48.@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }) })49.public class PaginationInterceptor implements Interceptor {50.51. private final Logger logger = LoggerFactory52. .getLogger(PaginationInterceptor.class);53.54. private String dialect = "";55.56. // 暂时不需要这个参数,现在根据参数类型来判断是否是分页sql57. // private String pageMethodPattern = "";58.59. public Object intercept(Invocation ivk) throws Throwable {60. if (!(ivk.getTarget() instanceof RoutingStatementHandler)) {61. return ivk.proceed();62. }63. RoutingStatementHandler statementHandler = (RoutingStatementHandler) ivk64. .getTarget();65. BaseStatementHandler delegate = (BaseStatementHandler) SystemUtil66. .getValueByFieldName(statementHandler, "delegate");67. MappedStatement mappedStatement = (MappedStatement) SystemUtil68. .getValueByFieldName(delegate, "mappedStatement");69.70. // BoundSql封装了sql语句71. BoundSql boundSql = delegate.getBoundSql();72. // 获得查询对象73. Object parameterObject = boundSql.getParameterObject();74. // 根据参数类型判断是否是分页方法75. if (!(parameterObject instanceof Query)) {76. return ivk.proceed();77. }78. logger.debug(" beginning to intercept page SQL...");79. Connection connection = (Connection) ivk.getArgs()[0];80. String sql = boundSql.getSql();81. Query query = (Query) parameterObject;82. // 查询参数对象83. Pager pager = null;84. // 查询条件Map85. Map<String, Object> conditions = query.getQueryParams();86. pager = query.getPager();87. // 拼装查询条件88. if (conditions != null) {89. Set<String> keys = conditions.keySet();90. Object value = null;91. StringBuffer sb = new StringBuffer();92. boolean first = true;93. for (String key : keys) {94. value = conditions.get(key);95. if (first) {96. sb.append(" where ").append(key).append(value);97. first = !first;98. } else {99. sb.append(" and ").append(key).append(value); 100. }101. }102. sql += sb.toString();103. }104.105. // 获取查询数来的总数目106. String countSql = "SELECT COUNT(0) FROM (" + sql + ") AS t mp ";107. PreparedStatement countStmt = connection.prepareStatement( countSql);108. BoundSql countBS = new BoundSql(mappedStatement.getConfigu ration(),109. countSql, boundSql.getParameterMappings(), paramet erObject);110. setParameters(countStmt, mappedStatement, countBS, paramet erObject);111. ResultSet rs = countStmt.executeQuery();112. int count = 0;113. if (rs.next()) {114. count = rs.getInt(1);115. }116. rs.close();117. countStmt.close();118.119. // 设置总记录数120. pager.setTotalResult(count);121. // 设置总页数122. pager.setTotalPage((count + pager.getShowCount() - 1) 123. / pager.getShowCount());124. // 放到作用于125. PageContext.getInstance().set(pager);126.127. // 拼装查询参数128. String pageSql = generatePageSql(sql, pager);129. SystemUtil.setValueByFieldName(boundSql, "sql", pageSql);130. logger.debug("generated pageSql is : " + pageSql); 131.132. return ivk.proceed();133. }134.135. /**136. * setting parameters137. *138. * @param ps139. * @param mappedStatement140. * @param boundSql141. * @param parameterObject142. * @throws SQLException143. */144. private void setParameters(PreparedStatement ps,145. MappedStatement mappedStatement, BoundSql boundSql, 146. Object parameterObject) throws SQLException {147. ErrorContext.instance().activity("setting parameters") 148. .object(mappedStatement.getParameterMap().getId()) ;149. List<ParameterMapping> parameterMappings = boundSql 150. .getParameterMappings();151. if (parameterMappings != null) {152. Configuration configuration = mappedStatement.getConfi guration();153. TypeHandlerRegistry typeHandlerRegistry = configuratio n154. .getTypeHandlerRegistry();155. MetaObject metaObject = parameterObject == null ? null156. : configuration.newMetaObject(parameterObject) ;157. for (int i = 0; i < parameterMappings.size(); i++) { 158. ParameterMapping parameterMapping = parameterMappi ngs.get(i);159. if (parameterMapping.getMode() != ParameterMode.OU T) {160. Object value;161. String propertyName = parameterMapping.getProp erty();162. PropertyTokenizer prop = new PropertyTokenizer (propertyName);163. if (parameterObject == null) {164. value = null;165. } else if (typeHandlerRegistry166. .hasTypeHandler(parameterObject.getCla ss())) {167. value = parameterObject;168. } else if (boundSql.hasAdditionalParameter(pro pertyName)) {169. value = boundSql.getAdditionalParameter(pr opertyName);170. } else if (propertyName171. .startsWith(ForEachSqlNode.ITEM_PREFIX )172. && boundSql.hasAdditionalParameter(pro p.getName())) {173. value = boundSql.getAdditionalParameter(pr op.getName());174. if (value != null) {175. value = configuration.newMetaObject(va lue)176. .getValue(177. propertyName.substring (prop178. .getName().len gth()));179. }180. } else {181. value = metaObject == null ? null : metaOb ject182. .getValue(propertyName);183. }184.@SuppressWarnings("unchecked")185. TypeHandler<Object> typeHandler = (TypeHandler <Object>) parameterMapping186. .getTypeHandler();187. if (typeHandler == null) {188. throw new ExecutorException(189. "There was no TypeHandler found fo r parameter "190. + propertyName + " of stat ement "191. + mappedStatement.getId()) ;192. }193. typeHandler.setParameter(ps, i + 1, value, 194. parameterMapping.getJdbcType()); 195. }196. }197. }198. }199.200. /**201. * 生成Sql语句202. *203. * @param sql204. * @param page205. * @return206. */207. private String generatePageSql(String sql, Pager page) { 208. if (page != null && (dialect != null || !dialect.equals(""))) {209. StringBuffer pageSql = new StringBuffer();210. if ("mysql".equals(dialect)) {211. pageSql.append(sql);212. pageSql.append(" LIMIT " + page.getCurrentResult() + ","213. + page.getShowCount());214. } else if ("oracle".equals(dialect)) {215. pageSql.append("SELECT * FROM (SELECT t.*,ROWNUM r FROM (");216. pageSql.append(sql);217. pageSql.append(") t WHERE r <= ");218. pageSql.append(page.getCurrentResult() + page.getS howCount());219. pageSql.append(") WHERE r >");220. pageSql.append(page.getCurrentResult());221. }222. return pageSql.toString();223. } else {224. return sql;225. }226. }227.228. public Object plugin(Object arg0) {229. return Plugin.wrap(arg0, this);230. }231.232. public void setProperties(Properties p) {233. dialect = p.getProperty("dialect");234. if (dialect == null || dialect.equals("")) {235. try {236. throw new PropertyException("dialect property is n ot found!");237. } catch (PropertyException e) {238. e.printStackTrace();239. }240. }241. // pageMethodPattern = p.getProperty("pageMethodPattern");242. if (dialect == null || dialect.equals("")) {243. try {244. throw new PropertyException(245. "pageMethodPattern property is not found!");246. } catch (PropertyException e) {247. e.printStackTrace();248. }249. }250. }251.252.}查询对象的封装:1、map封装查询条件2、pager对象封装查询限制条件,就是MySql中limit后的参数等附加信息[java]view plaincopyprint?1.package com.wtas.page;2.3./**4. * 分页描述信息5. *6. * @author dendy7. *8. */9.public class Pager {10. // 每一页的显示条数11. private int showCount;12. // 总的页数13. private int totalPage;14. // 查询的数据总条数15. private int totalResult;16. // 当前页17. private int currentPage;18. // 从第几条开始获取数据19.@SuppressWarnings("unused")20. private int currentResult;21.22. public Pager() {23. this(1);24. }25.26. public Pager(int currentPage) {27. // 默认每页显示10条记录28. this(currentPage, 10);29. }30.31. public Pager(int currentPage, int showCount) {32. this.currentPage = currentPage;33. if (showCount > 0) {34. this.showCount = showCount;35. }36. // 错误处理37. if (this.currentPage < 1) {38. this.currentPage = 1;39. }40. }41.42. //只列出关键的getter和setter……43.44. public int getTotalPage() {45. // 分页算法,计算总页数46. return this.totalPage;47. }48.49. public int getCurrentResult() {50. // 计算从第几条获取数据51. return (currentPage - 1) * showCount;52. }53.54.}[java]view plaincopyprint?1.package com.wtas.page;2.3.import java.util.Map;4.5./**6. * 封装查询蚕食和查询条件7. *8. * @author dendy9. *10. */11.public class Query {12. private Map<String, Object> queryParams;13. private Pager pager;14.15. public Map<String, Object> getQueryParams() {16. return queryParams;17. }18.19. public void setQueryParams(Map<String, Object> queryParams) {20. this.queryParams = queryParams;21. }22.23. //省略getter和setter24.}控制层关键代码:[java]view plaincopyprint?1. /**2. * 分页时获取所有的学生3. *4. * @return5. */6.@RequestMapping("pageStus")7.@ResponseBody8.public List<User> pageAllStudents(HttpServletRequest req) {9. try {10. Query query = new Query();11. Pager pager = new Pager();12. Map<String, Object> queryParams = new HashMap<String, Object>();13.14. // 获取分页参数15. String showCount = req.getParameter("showCount");16. String currentPage = req.getParameter("currentPage");18. if (StringUtils.hasLength(showCount)) {19. pager.setShowCount(Integer.parseInt(showCount));20. }21. if (StringUtils.hasLength(currentPage)) {22. pager.setCurrentPage(Integer.parseInt(currentPage));23. }24.25. // 高级查询条件:学生真实姓名26. String trueNameForQuery = req.getParameter("trueNameForQuery");27. if (StringUtils.hasLength(trueNameForQuery)) {28. queryParams.put(" u.REAL_NAME like ", "'%" + trueNameForQuery29. + "%'");30. }31.32. query.setPager(pager);33. query.setQueryParams(queryParams);34. List<User> users = userService.pageUsersByRole(query);35.36. // req.setAttribute("pager", PageContext.getInstance().get());37.38. return users;39. } catch (Exception e) {40. LOG.error("getAllStudents error : " + e.getMessage());41. }42. return null;43.}44.45.@RequestMapping("getPager")46.@ResponseBody47.public Pager getPager() {48. return PageContext.getInstance().get();dao中的方法:[java]view plaincopyprint?1. /**2.* 级联查询所有某一角色的用户信息,带分页3.*4.* @param roleValue5.* @param page6.* @return7.*/8.ist<User> pageUsers(Object query);dao的Mappder.xml定义:[html]view plaincopyprint?1.<select id="pageUsers"resultMap="userMapping"parameterType="hashMap">2. SELECT DISTINCT u.* FROM T_USER u LEFT JOIN T_REL_USER_ROLE ur ON3.u.id=er_id4. LEFT JOIN T_ROLE r ON ur.role_id=r.id5.</select>页面通过javascript来异常发送请求获取数据,关键代码:[javascript]view plaincopyprint?1./**2. * 处理分页3. *4. * @param curPage5. * @param id6. */7.function page(curPage, id) {8. if(curPage <= 0){9. curPage = 1;10. }11.12. var trueNameForQuery = $("#findByTrueNameInput").val().trim();13.14. var url = path + "/studygroup/pageStus.do";15. var thCss = "class='s-th-class'";16. var tdCss = "class='s-td-class'";17. $.ajax({18. type : "POST",19. url : url,20. dataType : "json",21. data : {22. "id" : id,23. "currentPage" : curPage,24. "trueNameForQuery" : trueNameForQuery25. },26. success : function(data) {27. var json = eval(data);28. var res = "<tr><th " + thCss + ">选择</th>"29. + "<th " + thCss + ">用户名</th>"30. + "<th " + thCss + ">真实姓名</th>"31. + "<th " + thCss + ">性别</th>"32. + "<th " + thCss + ">学校</th>"33. + "<th " + thCss + ">年级</th>"34. + "<th " + thCss + ">班级</th></tr>";35. for ( var i = 0; i < json.length; i++) {36. var userId = json[i].id;37. var name = json[i].name;38. var trueName = json[i].trueName;39. var sex = json[i].sex;40. var school = "";41. if (json[i].school) {42. school = json[i];43. }44. var grade = "";45. if (json[i].grade) {46. grade = json[i];47. }48. var clazz = "";49. if (json[i].clazz) {50. clazz = json[i];51. }52. res += "<tr><td align='center' " + tdCss + "><input type='checkbox' value='" + userId + "' /></td>"53. + "<td align='center' " + tdCss + ">" + (name|| "") + "</td>"54. + "<td align='center' " + tdCss + ">" + (trueName || "") + "</td>"55. + "<td align='center' " + tdCss + ">" + (sex== 1 ? '女' : '男' || "") + "</td>"56. + "<td align='center' " + tdCss + ">" + school + "</td>"57. + "<td align='center' " + tdCss + ">" + grade+ "</td>"58. + "<td align='center' " + tdCss + ">" + clazz+ "</td>"59. + "</td></tr>";60. }61. $("#inviteStudentsTbl").html(res);62. // 每次加载完成都要刷新分页栏数据63. freshPager(id);64. }65. });66.}67.68./**69. * 重新获取分页对象,刷新分页工具栏70. */71.function freshPager(id){72. var url = path + "/studygroup/getPager.do";73. var studyGroupId = id;74. $.ajax({75. type : "POST",76. url : url,77. dataType : "json",78. success : function (data) {79. var pager = eval(data);80. var currentPage = pager.currentPage;81.// var currentResult = pager.currentResult;82.// var showCount = pager.showCount;83. var totalPage = pager.totalPage;84.// var totalResult = pager.totalResult;85.86. var prePage = currentPage - 1;87. var nextPage = currentPage + 1;88. if (prePage <= 0) {89. prePage = 1;90. }91. if (nextPage > totalPage) {92. nextPage = totalPage;93. }94.95. $("#topPageId").attr("href", "javascript:page(1, " + studyGroupId + ");");96. $("#prefixPageId").attr("href", "javascript:page(" + prePage + ", " + studyGroupId + ");");97. $("#nextPageId").attr("href", "javascript:page(" + nextPage + ", " + studyGroupId + ");");98. $("#endPageId").attr("href", "javascript:page(" + totalPage + ", " + studyGroupId + ");");99. $("#curPageId").html(currentPage);100. $("#totalPageId").html(totalPage);101. }102. });103.}104.105./**106. * 按真实姓名搜索107. */108.function findByTrueName() {109. page(1, studyGroupId);110.}end. ————————————————————————————————————————————————应网友需要,贴上SystemUtil的代码:[java]view plaincopyprint?1.package mon.utils;2.3.import ng.reflect.Field;4.5.import javax.servlet.http.HttpSession;6.7.import mon.consts.SystemConst;8.import er;9.10./**11. * 系统工具类,定义系统常用的工具方法12. *13. * @author dendy14. *15. */16.public class SystemUtil {17. private SystemUtil() {18.19. }20.21. /**22. * 获取系统访问的相对路径,如:/WTAS23. *24. * @return25. */26. public static String getContextPath() {27. return System.getProperty(SystemConst.SYSTEM_CONTEXT_PATH_KEY);28. }29.30. /**31. * 修改一个bean(源)中的属性值,该属性值从目标bean获取32. *33. * @param dest34. * 目标bean,其属性将被复制到源bean中35. * @param src36. * 需要被修改属性的源bean37. * @param filtNullProps38. * 源bean的null属性是否覆盖目标的属性<li>true : 源bean中只有为null的属性才会被覆盖<li>false39. * : 不管源bean的属性是否为null,均覆盖40. * @throws IllegalArgumentException41. * @throws IllegalAccessException42. */43. public static void copyBean(Object dest, Object src, boolean filtNullProps)44. throws IllegalArgumentException, IllegalAccessException {45. if (dest.getClass() == src.getClass()) {46. // 目标bean的所有字段47. Field[] destField = dest.getClass().getDeclaredFields();48. // 源bean的所有字段49. Field[] srcField = src.getClass().getDeclaredFields();50. for (int i = 0; i < destField.length; i++) {51. String destFieldName = destField[i].getName();52. String destFieldType = destField[i].getGenericType().toString();53. for (int n = 0; n < srcField.length; n++) {54. String srcFieldName = srcField[n].getName();55. String srcFieldType = srcField[n].getGenericType()56. .toString();57. // String srcTypeName =58. // srcField[n].getType().getSimpleName();59. if (destFieldName.equals(srcFieldName)60. && destFieldType.equals(srcFieldType)) {61. destField[i].setAccessible(true);62. srcField[n].setAccessible(true);63. Object srcValue = srcField[n].get(src);64. Object destValue = destField[i].get(dest);65. if (filtNullProps) {66. // 源bean中的属性已经非空,则不覆盖67. if (srcValue == null) {68. srcField[n].set(src, destValue);69. }70. } else {71. srcField[n].set(dest, srcValue);72. }73. }74. }75. }76. }77. }78.79. /**80. * 根据字段的值获取该字段81. *82. * @param obj83. * @param fieldName84. * @return85. */86. public static Field getFieldByFieldName(Object obj, String fieldName) {87. for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass88. .getSuperclass()) {89. try {90. return superClass.getDeclaredField(fieldName);91. } catch (NoSuchFieldException e) {92. }93. }94. return null;95. }96.97. /**98. * 获取对象某一字段的值99. *100. * @param obj101. * @param fieldName102. * @return103. * @throws SecurityException104. * @throws NoSuchFieldException105. * @throws IllegalArgumentException106. * @throws IllegalAccessException107. */108. public static Object getValueByFieldName(Object obj, String fi eldName)109. throws SecurityException, NoSuchFieldException, 110. IllegalArgumentException, IllegalAccessException { 111. Field field = getFieldByFieldName(obj, fieldName); 112. Object value = null;113. if (field != null) {114. if (field.isAccessible()) {115. value = field.get(obj);116. } else {117. field.setAccessible(true);118. value = field.get(obj);119. field.setAccessible(false);120. }121. }122. return value;123. }124.125. /**126. * 向对象的某一字段上设置值127. *128. * @param obj129. * @param fieldName130. * @param value131. * @throws SecurityException132. * @throws NoSuchFieldException133. * @throws IllegalArgumentException134. * @throws IllegalAccessException135. */136. public static void setValueByFieldName(Object obj, String fiel dName,137. Object value) throws SecurityException, NoSuchFieldExc eption,138. IllegalArgumentException, IllegalAccessException { 139. Field field = obj.getClass().getDeclaredField(fieldName);140. if (field.isAccessible()) {141. field.set(obj, value);142. } else {143. field.setAccessible(true);144. field.set(obj, value);145. field.setAccessible(false);146. }147. }148.149. /**150. * 从session中获取当前登录用户151. *152. * @param session153. * @return154. */155. public static User getLoginUser(HttpSession session) { 156. return (User) session.getAttribute(ER_IN_SES SION);157. }158.159. /**160. * @Description 设置更新信息后的登录用户给session161. * @param user 登录用户162. * @param session session163. */164. public static void setUser(User user, HttpSession session) { 165. session.setAttribute(ER_IN_SESSION, user); 166. }167.}。