SSM分页查询

数据库:mysql5.7

分页查询主要用到的还是limit

    limit 10,2    查询从第11条开始的后两条,即查询结果为11,12

    limit 10         查询前10条

    limit 10,0    查询第11条开始后0条,即结果为0

    limit 10,-1   查询第11条开始后所有记录(早期版本支持,比较新的版本可以设置第二个参数为一个很大的值)

第一种方式,自定义分页查询

(1)工具类

package com.lzy.util;

public class FenyeParam {
	
	private String field;
	private Integer start=0,count=0;
	
	public void setField(String[] fields) {
		this.field="";
		for(String f:fields) {
			this.field+=f+",";
		}
		//抹掉最后的逗号
		this.field=this.field.substring(0, this.field.length()-1);
	}
	
	public void setField1(String sqlFields) {
		//like "field,field2,field3..."
		this.field=sqlFields;
	}
	
	public void setStart(Integer start) {
		this.start=start;
	}
	
	public void setCount(Integer count) {
		this.count=count;
	}
	
	public String getField() {
		return this.field;
	}
	
	public Integer getStart() {
		return this.start;
	}
	
	public Integer getCount() {
		return this.count;
	}

	@Override
	public String toString() {
		return "FenyeParam [field=" + field + ", start=" + start + ", count=" + count + "]";
	}
	
	
}

自定义了一个分页参数类FenyeParam:

    field参数为查询的字段,start为开始位置,count为查询记录条数;

    field参数设置提供两种方法,setField(String[])方法接收数组,自动拼接sql查询字段;setField1(String)接收String字符串,为sql字段样式(例:"id,name,sex");

(2)相关mapper.xml文件配置:

<!-- 分页查询 -->
  <select id="selectFenYe" parameterType="com.lzy.util.FenyeParam" resultType="com.lzy.bean.User">
  	SELECT ${fenyeParam.field} FROM User limit #{fenyeParam.start,jdbcType=INTEGER},#{fenyeParam.count,jdbcType=INTEGER}
  </select>

mybatis中${}和#{}区别:

    ${}为原样输入,不会修改或转义字符串

    #{}为字符串类型输入,根据PreparedStatement安全设置参数

扩充:

PreparedStatement为JDBC sql预处理,替换对应sql字符串中的?,安全,如下代码比较直观:

package sdfadf;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class JDBCUtil {
	public static void main(String[] args) {
		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testpq?characterEncoding=utf8&useSSL=true&serverTimezone=UTC","xxx","xxxxxx");
			String sql="select id,name from user where id=?";
			PreparedStatement ps = conn.prepareStatement(sql);
			ps.setString(1, "11");
			ResultSet rs = ps.executeQuery();
			while(rs.next()) {
				System.out.println(rs.getString("id")+","+rs.getString("name"));
			}
			rs.close();
			ps.close();
			conn.close();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}

本文用的是mysql5.7,Driver和url根据需自己版本

(3)调用(没有写完完整的controller层和service层,只完成了dao层和mapper.xml,这里的测试用的是junit的单元测试)

package com.lzy.test;

import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.lzy.bean.User;
import com.lzy.dao.UserMapper;
import com.lzy.util.FenyeParam;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"classpath:applicationContext.xml"})
public class MyTest {
	
	@Autowired
	UserMapper uMapper;
	
	@Test
	public void Test2() {
		FenyeParam fenyeParam=new FenyeParam();
		String[] fields=new String[] {"id","name"};
		fenyeParam.setField(fields);
		//fenyeParam.setField1("id,name");
		fenyeParam.setStart(10);
		fenyeParam.setCount(2);
		List<User> user = uMapper.selectFenYe(fenyeParam);
		System.out.println(user);
	}
	
	
}

结果:

6b694f9e493da2c92e2f71c2170cebf9678.jpg

第二种方式,MyBatis分页插件PageHelper的使用

1、pom加入PageHelper依赖关系

<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.1.8</version>
</dependency>

2、配置PageHelper

    配置PageHelper有在MyBatis配置文件中配置和在Spring配置文件中配置两种方式,详情请参考官方说明:

https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/en/HowToUse.md

本次采用Mybatis配置文件mybatis-config.xml中配置的方式,只需要在mybatis配置文件中加入PageInterceptor,具体如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <settings>
    <setting name="mapUnderscoreToCamelCase" value="true"/>
  </settings>
  <typeAliases>
    <package name="com.lzy.bean"/>
  </typeAliases>
  <plugins>
  	<plugin interceptor="com.github.pagehelper.PageInterceptor">
  		<!-- 详细配置项 -->
  	</plugin>
  </plugins>
</configuration>

没有特殊要求如上即可,具体配置参考官方地址:

https://pagehelper.github.io/docs/howtouse/

3、使用

PageHelper.startPage(pageNum, pageSize)方法后的第一个查询方法就会进行分页查询,故这里只需要将调用查询的方法放到PageHelper.startPage(pageNum, pageSize)方法之后就行。例如下在controller层使用PageHelper.startPage(pageNum, pageSize)对调用service层的查询方法进行分页查询:

package com.lzy.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.lzy.bean.User;
import com.lzy.service.TPQService;

@Controller
public class TPQController {
	
	@Autowired
	TPQService tService;
	
	@ResponseBody
	@RequestMapping("/tpq")
	public PageInfo<User> Tpq() {
		PageHelper.startPage(10, 2);
		List<User> list = tService.selectPQ();
		System.out.println(list);
		PageInfo<User> pu=new PageInfo<>(list);
		System.out.println(pu);
		return pu;
	}
	
}
package com.lzy.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.lzy.bean.User;
import com.lzy.bean.UserExample;
import com.lzy.dao.UserMapper;

@Service
public class TPQService {

	@Autowired
	UserMapper uMapper;
	
	public List<User> selectPQ() {
		UserExample example=new UserExample();
		return uMapper.selectByExample(example);
	}

}

查询结果:

76d15ef0ab6806a3072aaf7896fccb8addb.jpg

下方PageInfo具体结果如下:

PageInfo{pageNum=10, pageSize=2, size=2, startRow=19, endRow=20, total=99, pages=50, list=Page{count=true, pageNum=10, pageSize=2, startRow=18, endRow=20, total=99, pages=50, reasonable=false, pageSizeZero=false}[User [id=19, name=user19], User [id=20, name=user20]], prePage=9, nextPage=11, isFirstPage=false, isLastPage=false, hasPreviousPage=true, hasNextPage=true, navigatePages=8, navigateFirstPage=6, navigateLastPage=13, navigatepageNums=[6, 7, 8, 9, 10, 11, 12, 13]}

说明:

PageHelper.startPage(10, 2);//分页插件应用
List<User> list = tService.selectPQ();//查询数据

 

PageInfo<User> pu=new PageInfo<>(list);//转为分页结果对象

PageInfo属性说明:

pageNum				当前页码
pageSize			当前页码条数
startRow			查询结果开始记录位置,即结果是第startRow条记录开始
endRow				查询结果结束记录位置,即结果到第endRow条记录结束
pages				所有记录总共分为pages页
prePage				上一页页码
nextPage			下一页页码
isFirstPage			是否是第一页
isLastPage			是否是最后一页
hasPreviousPage		是否有前一页
hasNextPage			是否有后一页
navigatePages		导航条显示页码数目navigatePages,即navigatepageNums的个数
navigatepageNums	导航条显示具体页码的值
navigateFirstPage	导航条开始页码
navigateLastPage	导航条结束页码
total				总数据条数
list				查询结果

注意:

(1)根据官方建议,mybatis配置方式和spring配置方式最好二选其一。

(2)编辑代码时要注意分页时机,如下给出一段官方的不安全代码:

PageHelper.startPage(1, 10);
List<Country> list;
if(param1 != null){
    list = countryMapper.selectIf(param1);
} else {
    list = new ArrayList<Country>();
}

根据官方说明,PageHelper使用静态的ThreadLocal参数(听说:ThreadLocal用于保存某个线程共享变量:对于同一个static ThreadLocal,不同线程只能从中get,set,remove自己的变量,而不会影响其他线程的变量),分页参数和现场是绑定的。故上述代码中param1参数为null时,分页线程已经产生,但是没有被利用,也没有被释放(PageHelper在finally代码中自动清除了ThreadLocal存储对象),当这个线程再次被使用时就会导致分页结果与预期结果不一样的情况。而将上述代码改为如下代码就能保证安全:

List<Country> list;
if(param1 != null){
    PageHelper.startPage(1, 10);
    list = countryMapper.selectIf(param1);
} else {
    list = new ArrayList<Country>();
}

当然也可以调用PageHelper.clearPage();方法来清除ThreadLocal,但官方认为没有必要,嗯,没必要。

转载于:https://my.oschina.net/u/3804959/blog/3055407

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值