J2EE之通用分页

一,简单的查询功能

1.编码思路 :①建立数据库连接 ②定义预定义对象preparestatement ③.查询结果集④返回结果集

2.不足之处:①数据库连接   定义预定义对象 查询结果集 都是重复代码
              ②都是要返回数据库表对应的集合(集合中对象不同)
             ③都是要处理结果集 resultset
3.代码不一样在于:①具体体现在 不同表有不同的字段,那么实体类对应的属性就会不一样
                               ②  需要写大量的重复代码,系统的查询功能越多重复代码量越大

4 提供解决方案:
1,抽取变化部分作为参数(sql语句,class对象)
2,抽取公共的父类,把重复性代码剥离出来

如下:类为BaseDao<T>是所有dao类的父类
 

package com.zking.util;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

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

/**
 * 所有Dao层的父类
 * 	BookDao
 * 	UserDao
 * 	OrderDao
 * 	...
 * @author Administrator
 *
 * @param <T>
 */
public class BaseDao<T> {
	/**
	 * 通用的增删改方法
	 * @param book
	 * @throws Exception
	 */
	public void executeUpdate(String sql, T t, String[] attrs) throws Exception {
//		String[] attrs = new String[] {"bid", "bname", "price"};
		Connection con = DBAccess.getConnection();
		PreparedStatement pst = con.prepareStatement(sql);
//		pst.setObject(1, book.getBid());
//		pst.setObject(2, book.getBname());
//		pst.setObject(3, book.getPrice());
		/*
		 * 思路:
		 * 	1.从传进来的t中读取属性值
		 *  2.往预定义对象中设置了值
		 *  
		 *  t->book
		 *  f->bid
		 */
		for (int i = 0; i < attrs.length; i++) {
			Field f = t.getClass().getDeclaredField(attrs[i]);
			f.setAccessible(true);
			pst.setObject(i+1, f.get(t));
		}
		pst.executeUpdate();
	}
	
	/**
	 * 通用分页查询
	 * @param sql
	 * @param clz
	 * @return
	 * @throws Exception
	 */
	public List<T> executeQuery(String sql,Class<T> clz,PageBean pageBean) throws Exception{
		List<T> list = new ArrayList<T>();
		Connection con = DBAccess.getConnection();;
		PreparedStatement pst = null;
		ResultSet rs = null;
		
		/*
		 * 是否需要分页?
		 * 	无需分页(项目中的下拉框,查询条件教员下拉框,无须分页)	
		 * 	必须分页(项目中列表类需求、订单列表、商品列表、学生列表...)
		 */
		if(pageBean != null && pageBean.isPagination()) {
//			必须分页(列表需求)
			String countSQL = getCountSQL(sql);
			pst = con.prepareStatement(countSQL);
			rs = pst.executeQuery();
			if(rs.next()) {
				pageBean.setTotal(String.valueOf(rs.getObject(1)));
			}
			
//			挪动到下面,是因为最后才处理返回的结果集
//			-- sql=SELECT * FROM t_mvc_book WHERE bname like '%圣墟%'
//			-- pageSql=sql limit (page-1)*rows,rows 	对应某一页的数据
//			-- countSql=select count(1) from (sql) t 	符合条件的总记录数
			String pageSQL = getPageSQL(sql,pageBean);//符合条件的某一页数据
			pst = con.prepareStatement(pageSQL);
			rs = pst.executeQuery();
		}else {
//			不分页(select需求)
			pst = con.prepareStatement(sql);//符合条件的所有数据
			rs = pst.executeQuery();
		}
		
		
		while (rs.next()) {
			T t = clz.newInstance();
			Field[] fields = clz.getDeclaredFields();
			for (Field f : fields) {
				f.setAccessible(true);
				f.set(t, rs.getObject(f.getName()));
			}
			list.add(t);
		}
		return list;
	}

	/**
	 * 将原生SQL转换成符合条件的总记录数countSQL
	 * @param sql
	 * @return
	 */
	private String getCountSQL(String sql) {
//		-- countSql=select count(1) from (sql) t 	符合条件的总记录数
		return "select count(1) from ("+sql+") t";
	}

	/**
	 * 将原生SQL转换成pageSQL
	 * @param sql
	 * @param pageBean
	 * @return
	 */
	private String getPageSQL(String sql,PageBean pageBean) {
//		(this.page - 1) * this.rows
//		pageSql=sql limit (page-1)*rows,rows
		return sql + " limit "+ pageBean.getStartIndex() +","+pageBean.getRows();
	}

}

下面是bookdao:

 
public class bookDao extends BaseDao<Book>{
	/**
	 * 简单的查询
	 * 思路 :1建立数据库连接
	 * 2定义预定义对象preparestatement
	 * 3查询结果集
	 * 4返回结果集
	
	 * @throws Exception 
	 */
 
普通方法 没有继承父类
	public List<Book> list(Book book) throws Exception{
		List<Book> books=new ArrayList<Book>();
		String sql="select * from t_mvc_book where 1=1 ";
		//书籍名称
		String bname = book.getBname();
		//书籍名称模糊查询  圣墟最终是通过jsp页面传递过来的
		if(StringUtils.isNotBlank(bname)) {
			sql+=" and bname like '%"+bname+"%'";
		}
		Connection con=DBAccess.getConnection();
		PreparedStatement ps = con.prepareStatement(sql);
		ResultSet rs = ps.executeQuery();
		while(rs.next()) {
			books.add(new Book(rs.getInt("bid"),rs.getString("bname"), rs.getFloat("price"))); 
		}
		return books;
	}
	
	继承了父类的方法   代码明显要少,
	public List<Book> list1(Book book) throws Exception{
		String sql="select * from t_mvc_book where 1=1";
		String bname = book.getBname();
		//书籍名称模糊查询  圣墟最终是通过jsp页面传递过来的
		if(StringUtils.isNotBlank(bname)) {
			sql+=" and bname like '%"+bname+"%'";
		}
		return super.list(sql, Book.class);
	}
	
	测试
	public static void main(String[] args) throws Exception {
		bookDao bo=new bookDao();
		Book book=new Book();
		book.setBname("圣墟");
	List<Book> list=bo.list(book);
	for (Book book2 : list) {
		System.out.println(book2);
	}
}
}

 三,通用分页

/**
     * 通用分页查询
     * @param book
     * @return
     * @throws Exception
     */
    public List<Book> list3(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+%'";
        }
        return super.executeQuery(sql, Book.class,pageBean);
    }
    
    
    /**
     * 做一个通用分页查询   子类继承父类  自带分页功能
     * 最终碰到分页需求的时候  续写少量代码
     * 1.mysql分页
     *         sql=select * from t_mvc_book where bname like '%圣墟%'
     *         pagesql=sql limit (page-1)* rows,rows
     *         countsql=select count(1) from (sql) t
     * 2.编码
     *        ①原来list集合中返回的是符合的所有数据,现在需要发挥page页的数据  那么数据库加工成
     *        ②需要分页  要求条件符合的总记录数 
     *      total % rows == 0 ? total / rows : total / rows + 1
     * @param args
     * @throws Exception
     */

 分页查询的工具类

mysql的分页:

sql=select * from t_mvc_book where bname like '%aa%'

pageSQL=sql limit (page-1)*rows,row

countSQL=select * from (sql) t

当项目中要多次实现分页功能时,定义父类处理重复的代码,将重复代码放到父类由子类继承,这样当再次遇到分页时,可以节省重复代码和时间,提高效率

package com.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;
	}


  /**
     * 最大页数
     * @return
     */
    public int maxPage() {
        return this.total % this.rows == 0 ? this.total / this.rows : this.total / this.rows +1;
    }

    /**
     * 下一页
     * @return
     */
    public int maxtPage() {
        //如果当前页小于最大页 那就下一页+1,
        //如果不小于,说明当前页最大页 那就不用+1
        return this.page < this.maxPage() ? this.page + 1 : this.page;
    }
    
    /**
     * 上一页
     * @return
     */
    public int previousPage() {
        return this.page > 1 ? this.page -1 :this.page;
    } 


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

}





定义page标签,tld中的配置如下:

 <tag>
        <!-- 标签名 -->
        <name>PageTag</name>
        <!-- 标签工具类 -->
        <tag-class>com.tag.PageTag</tag-class>
        <!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 -->
        <body-content>jsp</body-content>
        <!-- 自定义标签的属性定义,请注意一定要在标签类中提供对应的get/set方法 -->
        <attribute>
            <!-- 自定义标签的属性名称 -->
            <name>PageBean</name>
            <!-- true表示必填 -->
            <required>true</required>
            <!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值