设计功能要求:
1:尽量保留原来API的操作
2:尽量简化JDBC操作的代码
3:带有分页功能
分析:
尽量保留原来API的操作,那么这个通用DAO不能过度封装,对于外界操作来说应该是透明的,为了简化一般的分页控制,提供了一个简单的基于超链接方式的上下页翻页操作,代码如下:
BaseDao.java
[CODE]
package xx.xx.xx;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
/**
* 作为所有数据库访问的父类<br/>适当的提供一些数据库的操作功能
*/
public class BaseDao {
protected Connection conn = null;
protected PreparedStatement pstmt = null;
protected ResultSet rs = null;
//最好通过配置文件加载,这样可以灵活的移动
private static String JNDI_DS = "java:comp/env/jdbc/msg";
public void query(String sql, Object... params) throws SQLException {
openConn();
preparedSql(sql, params);
rs = pstmt.executeQuery();
}
protected void preparedSql(String sql, Object... params) throws SQLException {
pstmt = conn.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
pstmt.setObject(i+1, params[i]);
}
}
/**
* @param sql,调用者方法中定义好的sql语句,通常是一个DAO类的方法
* @param params 传入的参数,多个参数用逗号隔开即可
* @return
*/
public int update(String sql, Object... params) {
openConn();
int count = 0;
try {
preparedSql(sql, params);
count = pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeAll();
}
return count;
}
/**
* pagedQuery分页查询功能
* @param pb 分页的bean用于封装分页信息
* @param sql
* @param params
* @throws SQLException
*/
public void queryByPage(PageBean pb, String sql, Object... params) throws SQLException {
//由于本方法有2次查询数据库,共用一个PreparedStatement,所以不重用本类中的query方法
openConn();
String totalSql = "select count(1) from (" + removeOrders(sql) + ")";
preparedSql(totalSql, params);
rs = pstmt.executeQuery();
//设置总记录数
if(rs.next()) {
pb.setTotal(rs.getInt(1));
}
String pagedSql = "select * from (select rownum as rn, t__.* from ("
+ sql + ") t__) where rn >= ? and rn <= ?";
Object[] p = new Object[params.length + 2];
for(int i =0; i < params.length; i++) {
p[i] = params[i];
}
p[params.length] = pb.getFirstResult();
p[params.length + 1] = pb.getMaxResult();
//分页查询结果
preparedSql(pagedSql, p);
rs = pstmt.executeQuery();
}
/**
* 由于order by消耗资源相当大,统计行数时不需要<br/>本例使用正则表达式处理掉order by子句
* @param sql
* @return
*/
protected String removeOrders(String sql) {
Pattern pattern = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*",
Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(sql);
StringBuffer buf = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(buf, "");
}
matcher.appendTail(buf);
return buf.toString();
}
protected void openConn() {
Context ctx;
try {
ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup(JNDI_DS);
conn = ds.getConnection();
} catch (NamingException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
protected void closeAll() {
try {
if (rs != null) {
rs.close();
}
if (pstmt != null) {
pstmt.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
[/CODE]
本段代码需要一个类PageBean,代码如下
[CODE]
package xx.xx.xx;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
public class PageBean {
private int pageSize = 10; //每页页面显示数据的条数
private int total = 0;//数据库表的总记录数
private int pageNum = 1;//当前第几页
public boolean getHasNext() {
if (this.getTotalPages() > pageNum) {
return true;
} else {
return false;
}
}
public int getNext() {
return (pageNum + 1);
}
public boolean getHasPrevious() {
if (pageNum > 1) {
return true;
} else {
return false;
}
}
public int getPrevious() {
return (pageNum - 1);
}
public int getFirstResult() {
return (pageNum - 1) * pageSize + 1;
}
public int getMaxResult() {
return pageNum * pageSize;
}
/**
* 获得分页的总页数
* @return
*/
public int getTotalPages() {
if (total % pageSize == 0) {
return (total/pageSize);
} else {
return (total/pageSize + 1);
}
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public int getPageNum() {
return pageNum;
}
public void setPageNum(int pageNum) {
this.pageNum = pageNum;
}
private Map<String, String[]> params;
/**
* 添加额外参数到页面上
* @param param
* @param value
*/
public void addParam(String param, String value) {
if (params == null) {
params = new HashMap<String, String[]>();
}
if (params.containsKey(param)) {
String[] oldValues = params.get(param);
//多加了一个参数
String[] pvalues = new String[oldValues.length+1];
for (int i = 0; i < pvalues.length; i++) {
pvalues[i] = oldValues[i];
}
pvalues[pvalues.length-1] = value;
} else {
params.put(param, new String[]{value});
}
}
/**
* 将网页的参数一次性添加上去,主要是为了在有查询条件的分页情况时使用
* @param params
*/
public void addAllParams(Map<String, String[]> params) {
if (params == null) {
return;
}
if (this.params == null) {
this.params = new HashMap<String, String[]>();
}
this.params.putAll(params);
}
/**
* 扩展参数
* @return
*/
private String getParamsString() {
//将分页的信息清除,因为每次换页都不一样
params.remove("pageNum");
params.remove("pageSize");
if (params == null || params.isEmpty()) {
return null;
} else {
StringBuilder sb = new StringBuilder("");
Iterator<Entry<String, String[]>> iter = params.entrySet().iterator();
while (iter.hasNext()) {
Entry<String, String[]> entry = iter.next();
for (String str : entry.getValue()) {
sb.append("&" + entry.getKey() + "=" + str);
}
}
return sb.toString().substring(1);
}
}
//基础路径,就是页面的访问路径
private String basePath = "";
public void setBasePath(String basePath) {
this.basePath = basePath;
}
/**
* 获得分页的控制面板
* @return 字符串
*/
public String getPagedPanel() {
StringBuilder sb = new StringBuilder("当前页数:[" + pageNum + "/" + this.getTotalPages() + "]");
sb.append(" ");
if (pageNum > 1) {
sb.append("<a href='【basePath】pageNum=1&pageSize=" + pageSize + "'>首页</a>");
} else {
sb.append("首页");
}
if (this.getHasPrevious()) {
sb.append("<a href='【basePath】pageNum=" + this.getPrevious() + "&pageSize=" + pageSize + "'>上一页</a>");
} else {
sb.append("上一页");
}
if (this.getHasNext()) {
sb.append("<a href='【basePath】pageNum=" + this.getNext() + "&pageSize=" + pageSize + "'>下一页</a>");
} else {
sb.append("下一页");
}
if (this.getTotalPages() > pageNum) {
sb.append("<a href='【basePath】pageNum=" + this.getTotalPages() + "&pageSize=" + pageSize + "'>尾页</a>");
} else {
sb.append("尾页");
}
String replacePath = basePath + "?";
String paramStr = this.getParamsString();
if (paramStr != null) {
replacePath = replacePath + paramStr + "&";
}
return sb.toString().replaceAll("【basePath】", replacePath);
}
}
[/CODE]