通用分页01

目录

一、junit4

二、反射通用后台查询方法

三、通用的分页后台查询方法


一、junit4

先说明一下我们的分页工具类

        封装了一个 PageBean类

package com.ycx.util;

/**
 * 分页工具类
 *
 */
public class PageBean {

	private int page = 1;// 页码

	private int rows = 10;// 页大小

	private int total = 0;// 总记录数

	private boolean pagination = true;// 是否分页

	public PageBean() {
		super();
	}

	public int getPage() {
		return page;
	}

	public void setPage(int page) {
		this.page = page;
	}

	public int getRows() {
		return rows;
	}

	public void setRows(int rows) {
		this.rows = rows;
	}

	public int getTotal() {
		return total;
	}

	public void setTotal(int total) {
		this.total = total;
	}

	public void setTotal(String total) {
		this.total = Integer.parseInt(total);
	}

	public boolean isPagination() {
		return pagination;
	}

	public void setPagination(boolean pagination) {
		this.pagination = pagination;
	}

	/**
	 * 获得起始记录的下标
	 * 
	 * @return
	 */
	public int getStartIndex() {
		return (this.page - 1) * this.rows;
	}

	@Override
	public String toString() {
		return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", pagination=" + pagination + "]";
	}

}

        我们以书本类为案例:

package com.ycx.entity;

public class Book {
	private int bid;
	private String bname;
	private float price;

	@Override
	public String toString() {
		return "Book [bid=" + bid + ", bname=" + bname + ", price=" + price + "]";
	}

	public int getBid() {
		return bid;
	}

	public void setBid(int bid) {
		this.bid = bid;
	}

	public String getBname() {
		return bname;
	}

	public void setBname(String bname) {
		this.bname = bname;
	}

	public float getPrice() {
		return price;
	}

	public void setPrice(float price) {
		this.price = price;
	}

	public Book(int bid, String bname, float price) {
		super();
		this.bid = bid;
		this.bname = bname;
		this.price = price;
	}
	
	public Book() {
		// TODO Auto-generated constructor stub
	}
}

接着写一个BookDao:

package com.ycx.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.ycx.entity.Book;
import com.ycx.util.DBAccess;
import com.ycx.util.PageBean;
import com.ycx.util.StringUtils;

public class BookDao {
	public List<Book> list(Book book,PageBean pageBean) throws Exception{
		List<Book> list=new ArrayList<Book>();
		/**
		 * 1、拿到数据库连接
		 * 2、拿到PreparedStatement
		 * 3、执行SQL语句
		 */
		Connection con=DBAccess.getConnection();
		String sql="select * from t_mvc_book where 1=1";
		String bname=book.getBname();
		if(StringUtils.isNotBlank(bname)) {
			sql+=" and bname like '%"+bname+"%'";
		}
		int bid=book.getBid();
		if(bid!=0) {
			sql+=" and bid ="+bid;
		}
		PreparedStatement pst = con.prepareStatement(sql);
		ResultSet rs = pst.executeQuery();
		while(rs.next()) {
			list.add(new Book(rs.getInt("bid"),rs.getString("bname"),rs.getFloat("price")));
		}
		return list;
	}
	public static void main(String[] args) throws Exception {
		List<Book> list = new BookDao().list(new Book(), null);
		for (Book book : list) {
			System.out.println(book);
		}
	}
}

我们的测试结果如下图:

(遍历出了我们MySql里 t_mvc_book 的所有数据)

 以前我们做测试就是写一个main方法,然后在里面一个一个写测试代码,这样会比较繁琐,导致我们的main方法内的代码过多,那么这里小编给大家讲解一个知识点:junit4

那么怎么使用呢,

我们先按快捷键:Ctrl+Shift+O

弹出框图片如下:

接着点击下一步后:

 

 

 OK之后:

 最后一个方法我们就把我们刚才前面我们要测试的查询方法放在下面即可(如图所示):

 

 比如我们再在下面写一个测试方法2:

 我们的打印结果如下图:

 可以看出我们的运行结果跟之前的是一样的,但是代码量大大减少,该测试方法更加便捷。

 (关键是跟 @Before @Test 的注解有关系)

总结: junit 能够针对单个方法进行测试,相较于main方法而言,

测试耦合性降低了!

 

二、反射通用后台查询方法

        通过上面的代码来看,我们的查询方法其实是不方便的,有很多的重复代码,比如:

Connection con=DBAccess.getConnection();//重复代码1

PreparedStatement pst = con.prepareStatement(sql);//重复代码2
ResultSet rs = pst.executeQuery();//重复代码3

 我们在做每一个表的查询的时候几乎都有这三样的代码,所以我们接下来就是要进行优化。

小编在com.ycx.util包内建了一个类:

 将来我们具体要查询哪张表我们不知道,所以我们可以用泛型,用泛型去替代。

 BaseDao<T>类:

package com.ycx.util;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import com.ycx.entity.Book;
/**
 * T代表的是实体类,可以是Book/User/Goods....
 * @author 杨总
 *
 * @param <T>
 */
public class BaseDao<T> {

	public List<T> executeQuery(String sql,PageBean pageBean,CallBack<T> callBack) throws Exception{
		List<Book> list=new ArrayList<Book>();
		/**
		 * 1、拿到数据库连接
		 * 2、拿到PreparedStatement
		 * 3、执行SQL语句
		 */
		Connection con=DBAccess.getConnection();//重复代码1
		PreparedStatement pst = con.prepareStatement(sql);//重复代码2
		ResultSet rs = pst.executeQuery();//重复代码3
//		while(rs.next()) {
//			list.add(new Book(rs.getInt("bid"),rs.getString("bname"),rs.getFloat("price")));
//		}
//		查询不同的表,必然要处理不同的结果集
//		接口是调用方来实现
		return callBack.foreach(rs);
	}
}

 BookDao:

//	Y阶段的第一个版本
	public List<Book> list2(Book book,PageBean pageBean) throws Exception{
		String sql="select * from t_mvc_book where 1=1";
		String bname=book.getBname();
		if(StringUtils.isNotBlank(bname)) {
			sql+=" and bname like '%"+bname+"%'";
		}
		int bid=book.getBid();
		if(bid!=0) {
			sql+=" and bid ="+bid;
		}
//		return super.executeQuery(sql, null,new CallBack<Book>(){
//			@Override
//			public List<Book> foreach(ResultSet rs) {
//				// TODO Auto-generated method stub
//				return null;
//			}
//		});
//	}
			
		return super.executeQuery(sql, null, rs->{
			List<Book> list=new ArrayList<Book>();
			try {
				while(rs.next()) {
					list.add(new Book(rs.getInt("bid"),rs.getString("bname"),rs.getFloat("price")));
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
			
			return list;
		});
	}

  新建一个 CallBack<T>:(这是回调函数)

package com.ycx.util;

import java.sql.ResultSet;
import java.util.List;

/**
 * 回调函数接口的作用?
 * 谁调用谁处理
 * @author 杨总
 *
 * @param <T>
 */
public interface CallBack<T> {

	List<T> foreach(ResultSet rs);
	
	

}

 然后我们在BookDaoTest内再次测试:

@Test
	public void testList2() {
		List<Book> list;
		try {
			 list = new BookDao().list(new Book(), null);
			for (Book book : list) {
				System.out.println(book);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
}

 打印结果如下:

 以上就是反射通用后台查询方法

三、通用的分页后台查询方法

我们查询数据库里的t_mvc_book中的总记录数:

 我们以前BookDao方法是这样写的,代码如下:

public class BookDao extends BaseDao<Book>{
//	S阶段的版本
	public List<Book> list(Book book,PageBean pageBean) throws Exception{
		List<Book> list=new ArrayList<Book>();
		/**
		 * 1、拿到数据库连接
		 * 2、拿到PreparedStatement
		 * 3、执行SQL语句
		 */
		Connection con=DBAccess.getConnection();//重复代码1
		String sql="select * from t_mvc_book where 1=1";
		String bname=book.getBname();
		if(StringUtils.isNotBlank(bname)) {
			sql+=" and bname like '%"+bname+"%'";
		}
		int bid=book.getBid();
		if(bid!=0) {
			sql+=" and bid ="+bid;
		}
		PreparedStatement pst = con.prepareStatement(sql);//重复代码2
		ResultSet rs = pst.executeQuery();//重复代码3
		while(rs.next()) {
			list.add(new Book(rs.getInt("bid"),rs.getString("bname"),rs.getFloat("price")));
		}
		return list;
	}
}

 那么存在很多问题

①重复代码太多;

②分页参数不清晰;

解决方案:一、重复代码用BaseDao解决

                  二、分页参数用传一个pageBean

我们优化后的BookDao:

public List<Book> list2(Book book,PageBean pageBean) throws Exception{
		String sql="select * from t_mvc_book where 1=1";
		String bname=book.getBname();
		if(StringUtils.isNotBlank(bname)) {
			sql+=" and bname like '%"+bname+"%'";
		}
		int bid=book.getBid();
		if(bid!=0) {
			sql+=" and bid ="+bid;
		}
		return super.executeQuery(sql, pageBean, rs->{
			List<Book> list=new ArrayList<Book>();
			try {
				while(rs.next()) {
					list.add(new Book(rs.getInt("bid"),rs.getString("bname"),rs.getFloat("price")));
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
			
			return list;
		});
	}

并且小编封装了一个 BaseDao<T>

 BaseDao<T> 代码:

public List<T> executeQuery(String sql,PageBean pageBean,CallBack<T> callBack) throws Exception{
//		select * from t_mvc_book where bname like '%圣墟%'
//		从上面得到SELECT count(1) as n from (SELECT * from t_mvc_book where bname like '%圣墟%') t;
//			目的是为了得到总记录数->得到总页数
//		select * from t_mvc_book where bname like '%圣墟%' limit 10,10;
			List<Book> list=new ArrayList<Book>();
			/**
			 * 1、拿到数据库连接
			 * 2、拿到PreparedStatement
			 * 3、执行SQL语句
			 */
			Connection con=null;
			PreparedStatement pst = null;
			ResultSet rs = null;
			if(pageBean != null&&pageBean.isPagination()) {
				String countSQL=getCountSQL(sql);
				con=DBAccess.getConnection();//重复代码1
				pst = con.prepareStatement(countSQL);//重复代码2
				rs=pst.executeQuery();//重复代码3
				if(rs.next()) {
					//当前实体类包含了总记录数
					pageBean.setTotal(rs.getString("n"));
				}
				String pageSQL=getPageSQL(sql,pageBean);
				con=DBAccess.getConnection();//重复代码1
				pst = con.prepareStatement(pageSQL);//重复代码2
				rs=pst.executeQuery();//重复代码3
			}
			else {
				con=DBAccess.getConnection();//重复代码1
				pst = con.prepareStatement(sql);//重复代码2
				rs=pst.executeQuery();//重复代码3
			}
			return callBack.foreach(rs);
		}
/**
 * 拼接第N页的数据的SQl
 * @param sql
 * @param pageBean
 * @return
 */
	private String getPageSQL(String sql, PageBean pageBean) {
		return sql+" limit "+pageBean.getStartIndex()+","+pageBean.getRows();
	}
/**
 * 拼装符合条件总记录数的SQL
 * @param sql
 * @return
 */
	private String getCountSQL(String sql) {
//		select * from t_mvc_book where bname like '%圣墟%'
//		从上面得到SELECT count(1) as n from (SELECT * from t_mvc_book where bname like '%圣墟%') t;
//			目的是为了得到总记录数->得到总页数
//		select * from t_mvc_book where bname like '%圣墟%' limit 10,10;

		return "select count(1) as n from ("+sql+")t";
	}

通过BaseDao发现:不同的人调用。处理ResultSet方式是不一样的,

解决方案:通过回调函数解决  (CallBack)

原始SQl:调用方拼装好的SQL

分页SQl:页面要展示数据的SQl,第N页的数据

符合条件的总记录数SQl:是为了拿到总记录数,计算总记录数

之后BookDaoTest测试代码:

@Test
		public void testList3() {
			List<Book> list;
			try {
				Book b=new Book();
				b.setBname("圣墟");
				PageBean pageBean=new PageBean();
				pageBean.setPage(2);
				pageBean.setRows(20);
				 list = new BookDao().list(b, pageBean);
				for (Book book : list) {
					System.out.println(book);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

其中: 

                b.setBname("圣墟");

运行结果为:

          pageBean.setPage(2);           

运行结果为:

         pageBean.setRows(20);

运行结果为:


              

 今日分享就到这里拜拜拜啦~mua~

猜你喜欢

转载自blog.csdn.net/weixin_65808248/article/details/125397047
今日推荐