分页,关键字:count, limit, offset
JPA 通常 repository, myBatis 则 mapper 多一些
mongodb, redis, spring data 官方推荐 repository
Java 中一个方法可以返回多个值吗?包装后可以。
数据库:注意:如果数据过多,可以采用
select * from city \G
工程目录:
application.properties
#数据源
spring.datasource.url=jdbc:mysql://阿里云ip:3306/world
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.http.log-request-details=true
logging.level.web=debug
City.java
package com.newer.page.pojo;
//驼峰式命名法
//+-------------+----------+------+-----+---------+----------------+
//| Field | Type | Null | Key | Default | Extra |
//+-------------+----------+------+-----+---------+----------------+
//| ID | int | NO | PRI | NULL | auto_increment |
//| Name | char(35) | NO | | | |
//| CountryCode | char(3) | NO | MUL | | |
//| District | char(20) | NO | | | |
//| Population | int | NO | | 0 | |
public class City {
int id;
String name;
String countryCode;
String district;
int population;
public City() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCountryCode() {
return countryCode;
}
public void setCountryCode(String countryCode) {
this.countryCode = countryCode;
}
public String getDistrict() {
return district;
}
public void setDistrict(String district) {
this.district = district;
}
public int getPopulation() {
return population;
}
public void setPopulation(int population) {
this.population = population;
}
@Override
public String toString() {
return "City [id=" + id + ", name=" + name + ", countryCode=" + countryCode + ", district=" + district
+ ", population=" + population + "]";
}
}
CityRepository.java
package com.newer.page.repository;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import com.newer.page.pojo.City;
//JPA 通常 repository, myBatis 则 mapper 多一些
/**
* City的数据访问
* @author Admin
*
*/
@Mapper
public interface CityRepository {
/**
* 分页查询
*
* @param limit 记录行数
* @param offset 偏移量
* @return
*/
// 语句简单
@Select("select * from city where CountryCode='CHN' order by id limit #{limit} offset #{offset}")
// 用到动态SQL
// @SelectProvider
List<City> find(@Param("limit") int limit, @Param("offset") int offset);
/**
* 记录总数
*
* @return int 记录总数
*/
@Select("select count(id) from city where CountryCode='CHN'")
int count();
}
AppService.java
package com.newer.page.service;
import java.util.HashMap;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.newer.page.pojo.City;
import com.newer.page.repository.CityRepository;
import com.newer.page.util.Page;
/**
*
* 业务逻辑:粒度远大于POJO
* @author Admin
*
*/
@Service
public class AppService {
@Autowired
CityRepository cityRepository;
/**
*
* @param page 第几页,从0开始
* @param size 一页多少数据
* @return
*/
public Page<City> cityByPage(int page,int size) {
// 10
// 总记录数
int count=cityRepository.count();
// 第page+1页的数据
List<City> list=cityRepository.find(size, size*page );
// 向上取整计算出页数
int total=(int)Math.ceil(Double.valueOf(count)/size);
//
// HashMap<String,Object> data=new HashMap<>();
//// 列表数据
// data.put("list", list);
//// 总页数
// data.put("total", total);
//// 当前页码
// data.put("current", page);
Page<City> cityPage=new Page<>();
cityPage.setData(list);
cityPage.setTotal(total);
cityPage.setCurrent(page);
return cityPage;
}
}
HomeController.java
package com.newer.page.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HomeController {
// 返回视图
@GetMapping("/")
public String home() {
return "index.html";
}
}
CityController.java
package com.newer.page.controller;
import java.util.HashMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.newer.page.pojo.City;
import com.newer.page.service.AppService;
import com.newer.page.util.Page;
@RestController
@RequestMapping("/api/city")
public class CityController {
@Autowired
AppService appService;
// Get/api/city ?p=5&s=20
/**
* 获得分页数据
* @param page 页码
* @param size 一页的记录数,可选,默认20条数据
* @return
*/
@GetMapping
public Page<City> find(
@RequestParam(name="p",defaultValue = "0") int page,
@RequestParam(name="s",defaultValue = "20") int size
){
// 控制器调用业务逻辑
return appService.cityByPage(page, size);
}
}
Page.java
package com.newer.page.util;
import java.util.List;
/**
* 一页数据
*
* @author Admin
*
*/
public class Page<T> {
/**
* 数据
*/
List<T> data;
/**
* 总页数:基于0的开始到total-1
*/
int total;
/**
* 当前页数:基于0的开始
*/
int current;
public Page() {
}
public List<T> getData() {
return data;
}
public void setData(List<T> data) {
this.data = data;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public int getCurrent() {
return current;
}
public void setCurrent(int current) {
this.current = current;
}
}
index.html
<!doctype html>
<html lang="en">
<head>
<title>数据分页</title>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<!-- axios -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<!-- vue -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div class="jumbotron jumbotron-fluid">
<div class="container">
<h1 class="display-3">数据分页</h1>
<p class="lead">Vue & Spring Boot &MyBatis& MySQL</p>
</div>
</div>
<div id="app" class="container">
<!-- 表格 -->
<table class="table">
<thead>
<tr>
<th>编号</th>
<th>城市</th>
<th>国家</th>
<th>所在地区</th>
<th>人口</th>
</tr>
</thead>
<tbody>
<tr v-for="(city, index) in cityList" :key="index">
<td>{{city.id}}</td>
<td>{{city.name}}</td>
<td>{{city.countryCode}}</td>
<td>{{city.district}}</td>
<td>{{city.population}}</td>
</tr>
</tbody>
</table>
<!-- 分页 -->
<nav aria-label="Page navigation">
<ul class="pagination justify-content-center">
<li class="page-item ">
<a class="page-link" href="#" aria-label="Previous">
<span @click="page(index--)" aria-hidden="true" :class="{active: index===current}" >上一页</span>
</a>
</li>
<!-- 默认的样式 -->
<!-- <li class="page-item active"><a class="page-link" href="#">当前</a></li> -->
<li v-for="(n, index) in total" :key="index" class="page-item" :class="{active: n-1===current}">
<a @click="page(n-1)" class="page-link" href="#">
{{n}}
</a>
</li>
<li class="page-item">
<a class="page-link" href="#" aria-label="Next">
<span @click="page(index++)" aria-hidden="true" :class="{active: index===current}">下一页</span>
</a>
</li>
</ul>
</nav>
</div>
<script>
new Vue({
el: '#app',
data: {
cityList: [],
// 总页数
total: '',
// 当前页
current: '',
index:1
},
methods: {
page: function (num) {
axios.get('/api/city', {
params: {
p: num
}
})
.then(res => {
// console.log(res);
this.cityList = res.data.data;
this.total = res.data.total;
this.current = res.data.current;
})
},
next:function(i){
axios.get('/api/city', {
params: {
p:i
}
})
.then(res => {
console.log(res);
})
}
},
created() {
// 本地URL
let url = '/api/city';
axios.get(url)
.then(res => {
console.log(res)
this.cityList = res.data.data;
this.total = res.data.total;
this.current = res.data.current;
})
.catch(err => {
console.error(err);
})
},
})
</script>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
crossorigin="anonymous"></script>
</body>
</html>
程序运行,浏览器看效果: