目录
使用例子 :分页查询最新股票交易时间点下沪深两市个股行情数据,并根据涨幅降序排序展示
PageHelper插件
PageHelper.startPage(page, pageSize);
是 MyBatis 分页插件 PageHelper 的一个方法,用于在 MyBatis 进行数据库查询操作时实现分页功能。PageHelper 是一个非常流行的 MyBatis 分页插件,它通过拦截 MyBatis 的 SQL 语句来自动添加分页参数,从而实现分页查询。
参数说明
page
:当前页码,从 1 开始计数。pageSize
:每页显示的记录数。
作用
- 设置分页参数:
startPage
方法会设置当前的分页参数,包括页码和每页的记录数。 - 拦截 SQL 语句:PageHelper 会拦截后续的 MyBatis 查询操作,自动在 SQL 语句末尾添加分页参数(如
LIMIT
子句),从而实现分页查询。 - 返回分页结果:执行分页查询后,PageHelper 会返回一个
Page
对象(继承ArrayList类),再把该Page对象封装到PageInfo对象中获取更多的分页信息
PageHelper使用
1.导入依赖
<!--分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>
2.yml文件配置
# pagehelper配置
pagehelper:
helper-dialect: mysql #指定分页数据库类型(方言)
reasonable: true #合理查询超过最大页,则查询最后一页
3.测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestPageHelper {
@Autowired
private SysUserMapper sysUserMapper;
@Test
public void test(){
Integer page=2;//设置当前页
Integer pageSize=5;//设置每页的条数
PageHelper.startPage(page,pageSize);//开启分页查询
List<SysUser> all = sysUserMapper.findAll();
//将查询的page对象(page对象继承了ArrayList类)封装到PageInfo下就可以获取分页的各种数据
PageInfo<SysUser> pageInfo = new PageInfo<>(all);
int pageNum = pageInfo.getPageNum();//获取当前页
int pages = pageInfo.getPages();//获取总页数
int pageSize1 = pageInfo.getPageSize();//获取每页大小
int size = pageInfo.getSize();//获取当前页的记录数
long total = pageInfo.getTotal();//获取总记录数
List<SysUser> list = pageInfo.getList();//获取当前页的内容
System.out.println(all);
}
}
执行findAll()方法后,可以发现PageHelper自动执行了得到了记录总数的sql语句,并添加了limit
然后两个占位符分别赋值为5,5
即从第六条数据开始查询五条数据
from sys_user LIMIT ?, ?
联合唯一索引(Composite Unique Index)在数据库表中的作用非常重要,它涉及两个或多个列的组合,确保这些列的组合值在整个表中是唯一的。以下是联合唯一索引的主要作用和好处:
1. 确保数据的唯一性
联合唯一索引最重要的作用是确保表中两个或多个列的组合值不会重复。这对于维护数据的完整性和准确性至关重要。例如,在订单表中,你可能希望确保每个客户对每个产品的订单是唯一的,这可以通过在客户ID和产品ID上创建联合唯一索引来实现。
2. 提高查询性能
联合唯一索引可以显著提高涉及这些列的查询性能。当数据库查询优化器决定如何执行查询时,它会考虑可用的索引。如果一个查询涉及到多个列的搜索条件,并且这些列已经被索引,数据库可以利用这个索引来快速定位数据,而不是扫描整个表。
CREATE TABLE orders (
order_id INT AUTO_INCREMENT PRIMARY KEY,
customer_id INT NOT NULL,
product_id INT NOT NULL,
order_date DATE NOT NULL,
quantity INT NOT NULL,
UNIQUE (customer_id, product_id) -- 为customer_id和product_id添加联合唯一索引
);
联合唯一索引
查询时遵循最左匹配原则,如果使用where条件,使用了customer_id(在左边)就走联合唯一索引,如果只使用了product_id,就不会走联合唯一索引
使用例子 :分页查询最新股票交易时间点下沪深两市个股行情数据,并根据涨幅降序排序展示
要返回的数据
{
"code": 1,
"data": {
"totalRows": 46750,//总行数
"totalPages": 4675,//总页数
"pageNum": 2,//当前页
"pageSize": 10,//每页大小
"size": 10,//当前页大小
"rows": [
{
"tradeAmt": 4594802,//交易量
"preClosePrice": 18.78,//前收盘价
"amplitude": 0.059638,//振幅
"code": "000004",//股票编码
"name": "国华网安",//股票名称
"curDate": "2021-12-30 10:20",//当前日期
"tradeVol": 4594802,//交易金额
"increase": 0.039936,//涨跌
"upDown": 0.75,//涨幅
"tradePrice": 19.53//当前价格
},
//省略......
]
}
}
我们可以把code,data封装成一个R对象,用来返回数据,totalRows,totalPages,PageNum,pageSize,size,rows封装成一个PageResult类,放到vo包-->view object下,因为直接与前端交互
把rows类里面的封装成一个domain类放到domain包下,因为这个类要与数据库直接交互(通过sql语句进行赋值)
R:
/**
* 返回数据类
* @JsonInclude 保证序列化json的时候,如果是null的对象,key也会消失
* @param <T>
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class R<T> implements Serializable {
private static final long serialVersionUID = 7735505903525411467L;
// 成功值,默认为1
private static final int SUCCESS_CODE = 1;
// 失败值,默认为0
private static final int ERROR_CODE = 0;
//状态码
private int code;
//消息
private String msg;
//返回数据
private T data;
private R(int code){
this.code = code;
}
private R(int code, T data){
this.code = code;
this.data = data;
}
private R(int code, String msg){
this.code = code;
this.msg = msg;
}
private R(int code, String msg, T data){
this.code = code;
this.msg = msg;
this.data = data;
}
public static <T> R<T> ok(){
return new R<T>(SUCCESS_CODE,"success");
}
public static <T> R<T> ok(String msg){
return new R<T>(SUCCESS_CODE,msg);
}
public static <T> R<T> ok(T data){
return new R<T>(SUCCESS_CODE,data);
}
public static <T> R<T> ok(String msg, T data){
return new R<T>(SUCCESS_CODE,msg,data);
}
public static <T> R<T> error(){
return new R<T>(ERROR_CODE,"error");
}
public static <T> R<T> error(String msg){
return new R<T>(ERROR_CODE,msg);
}
public static <T> R<T> error(int code, String msg){
return new R<T>(code,msg);
}
public static <T> R<T> error(ResponseCode res){
return new R<T>(res.getCode(),res.getMessage());
}
public int getCode(){
return code;
}
public String getMsg(){
return msg;
}
public T getData(){
return data;
}
}
PageResult:
@Data
@ApiModel(description = "分页工具类")
public class PageResult<T> implements Serializable {
/**
* 总记录数
*/
@ApiModelProperty("总记录数")
private Long totalRows;
/**
* 总页数
*/
@ApiModelProperty("总页数")
private Integer totalPages;
/**
* 当前第几页
*/
@ApiModelProperty("当前第几页")
private Integer pageNum;
/**
* 每页记录数
*/
@ApiModelProperty("每页记录数")
private Integer pageSize;
/**
* 当前页记录数
*/
@ApiModelProperty("当前页记录数")
private Integer size;
/**
* 结果集
*/
@ApiModelProperty("结果集")
private List<T> rows;
/**
* 分页数据组装
* @param pageInfo
* @return
*/
public PageResult(PageInfo<T> pageInfo) {
totalRows = pageInfo.getTotal();
totalPages = pageInfo.getPages();
pageNum = pageInfo.getPageNum();
pageSize = pageInfo.getPageSize();
size = pageInfo.getSize();
rows = pageInfo.getList();
}
}
StockUpDownDomain:
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(description = "股票涨跌信息")
public class StockUpDownDomain {
@ApiModelProperty("交易量")
private Long tradeAmt;//交易量
@ApiModelProperty("前收盘价")
private BigDecimal preClosePrice;//前收盘价
/**
* (最高价-最低价) / 前收盘价 x100%
*/
@ApiModelProperty("振幅")
private BigDecimal amplitude;//振幅
@ApiModelProperty("股票编码")
private String code;//股票编码
@ApiModelProperty("股票名称")
private String name;//股票名称
@ApiModelProperty("当前日期")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")//设置返回给前端的数据格式
private Date curDate;//当前日期-"2021-12-30 10:20"
@ApiModelProperty("交易金额")
private BigDecimal tradeVol;//交易金额
/**
* 当前价格减去前收盘价格
*/
@ApiModelProperty("涨跌")
private BigDecimal increase;//涨跌
/**
* 涨跌除以前收盘价 x 100%
*/
@ApiModelProperty("涨幅")
private BigDecimal upDown;//涨幅
@ApiModelProperty("当前价格")
private BigDecimal tradePrice;//当前价格
}
设置接口
@GetMapping("/stock/all")
@ApiOperation("获取个股信息")
@ApiImplicitParams({
@ApiImplicitParam(name = "page", value = "当前页数", required = false, defaultValue = "1"),
@ApiImplicitParam(name = "pageSize", value = "每页的记录数", required = false, defaultValue = "20")
}
)
public R<PageResult<StockUpDownDomain>>getStockPageInfo(
@RequestParam(name="page",required = false,defaultValue = "1")
Integer page,
@RequestParam(name="pageSize",required = false,defaultValue = "20")
Integer pageSize){
return stockService.getStockPageInfo(page,pageSize);
}
设置业务
@Override
public R<PageResult<StockUpDownDomain>> getStockPageInfo(Integer page, Integer pageSize) {
//1.设置PageHelper分页插件
PageHelper.startPage(page,pageSize);
//2.获取当前时间的最新交易点
Date curDate=DateTimeUtil.getLastDate4Stock(DateTime.now()).toDate();
//mock data
curDate=DateTime.parse("2021-12-21 11:30:00",DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
//3.使用mapper对象查询
List<StockUpDownDomain>data=stockRtInfoMapper.getNewestStockInfo(curDate);
if(data==null){
return R.error(ResponseCode.NO_RESPONSE_DATA);
}
//4.将Page对象封装到PageInfo
PageInfo<StockUpDownDomain> pageInfo = new PageInfo<>(data);
//封装数据
PageResult<StockUpDownDomain> pageResult = new PageResult<>(pageInfo);
//5.返回数据
return R.ok(pageResult);
}
mapper接口
/**
* 获取最新交易时间点的个股信息根据涨幅进行降序排序
* @param curDate 最新交易时间点
*/
List<StockUpDownDomain> getNewestStockInfo(@Param("curDate") Date curDate);
mapperXml文件
<select id="getNewestStockInfo" resultType="com.hhh.stock.pojo.domain.StockUpDownDomain">
select
trade_amount as tradeAmt,
pre_close_price as preClosePrice,
(max_price-min_price) / pre_close_price as amplitude,
stock_code as code,
stock_name as name,
cur_time as curDate,
trade_volume as tradeVol,
(cur_price-pre_close_price) as increase,
(cur_price-pre_close_price) / pre_close_price as upDown,
cur_price as tradePrice
from stock_rt_info
where cur_time=#{curDate}
order by upDown desc
</select>
注意sql末尾不能加; 因为PageHelper要给查询语句加上limit关键字,设置分页查询