DAO层的作用不多说了,大家都知道
说下我的DAO层结构
BaseDao<T> 泛型类,模板类的基类
BaseDaoImpl<T> 泛型模板类
ResultHandle<T> 一个接口, 负责对结果集进行解析。
AbstractResultHandle<T> 抽象类,把公用的提取出来
BaseDao
public interface BaseDao<T> { /** * 查询单条记录的sql语句,如返回多条则只取第一条记录,没有记录返回null */ public T executeQueryForEntity(String sql,Integer identity); /** * 一些不需要返回值的非query语句 */ public void executeUpdate(String sql,Object... params); /** * 查询只返回一个整数值的sql,没有则返回0 */ public Integer executeQueryForInteger(String sql,Object... params); /** * 返回插入数据的自增ID */ public Integer executeInsertForInteger(String sql,Object... params); /** * 返回一个查询的列表,没有数据则返回空的list */ public List<T> executeQueryForListEntity(String sql,Object... params); }
BaseDaoImpl
public class BaseDaoImpl<T> implements BaseDao<T>{ //从filter中获得连接,最后又filter进行释放,见BlogFilter Connection conn = BlogFilter.getConnection(); ResultHandle<T> handle; //通过构造方法传入相应的结果集解析实现 public BaseDaoImpl(ResultHandle<T> handle){ this.handle=handle; } //第一个参数为sql语句,第二个为参数数组,和sql中?位置对应 @Override public void executeUpdate(String sql,Object... params){ try { PreparedStatement pstat = conn.prepareStatement(sql); for(int i=1;i<=params.length;i++) pstat.setObject(i, params[i-1]); pstat.executeUpdate(); } catch (SQLException e) { throw new RuntimeException(e); } } @Override public T executeQueryForEntity(String sql, Integer identity) { try { PreparedStatement pstat = conn.prepareStatement(sql); pstat.setObject(1,identity); ResultSet res = pstat.executeQuery(); //调用恰当的方法,用解析器进行解析 return handle.getBean(res); } catch (SQLException e) { throw new RuntimeException(e); } } @Override public Integer executeQueryForInteger(String sql, Object... params) { try { PreparedStatement pstat = conn.prepareStatement(sql); for(int i=1;i<=params.length;i++) pstat.setObject(i, params[i-1]); ResultSet res = pstat.executeQuery(); //如果查询的结果集为空,则返回0。貌似没有为空的 if(!res.next()) return 0; return res.getInt(1); } catch (SQLException e) { throw new RuntimeException(e); } } @Override public Integer executeInsertForInteger(String sql, Object... params) { try { PreparedStatement pstat = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS); for(int i=1;i<=params.length;i++) pstat.setObject(i, params[i-1]); pstat.executeUpdate(); //取得插入数据后包含,主键值的结果集 ResultSet res = pstat.getGeneratedKeys(); res.next(); return res.getInt(1); } catch (SQLException e) { throw new RuntimeException(e); } } @Override public List<T> executeQueryForListEntity(String sql, Object... params) { try { PreparedStatement pstat = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); for(int i=1;i<=params.length;i++) pstat.setObject(i, params[i-1]); ResultSet res = pstat.executeQuery(); return handle.getBeanList(res); } catch (SQLException e) { throw new RuntimeException(e); } } /** * 后增加的,多处用到,所有提起到了模板类里面 * @param sql 一个sql语句,不含参数。如:select count(*) from table; 用于取得可计算的结果总数 * @param pageSize 每页的现实数 * @return 最少返回1 */ public Integer getMaxPageNum(String sql,Integer pageSize) { Integer total = executeQueryForInteger(sql, new Object[]{}); if(total==0) return 1; //计算一共有多少页 int maxNum = total/pageSize; //不足一页,则返回1 if(total%pageSize!=0) maxNum+=1; return maxNum; } }
具体使用以评论表为例子
CommentDao
public interface CommentDao { public void addComment(Comment comment); public void deleteComment(Integer commentId); public List<Comment> getListComment(Integer articleId); public Integer getNumOfCommentForArticle(Integer articleId); public List<Comment> getLaterCommentList(Integer size); }
CommentDaoImpl
public class CommentDaoImpl extends BaseDaoImpl<Comment> implements CommentDao { public CommentDaoImpl( ) { super(new CommentResultHandle()); } @Override public void addComment(Comment comment) { String sql = "insert into comment(comment_body,comment_date,comment_name,comment_image,article_id) values(?,?,?,?,?)"; Object []params = {comment.getCommentBody(),comment.getCommentDate(), comment.getCommentName(),comment.getCommentImage(),comment.getArticleId()}; Integer id = super.executeInsertForInteger(sql, params); comment.setCommentId(id); } @Override public void deleteComment(Integer commentId) { String sql = "delete from comment where comment_id = ?"; super.executeUpdate(sql, commentId); } @Override public List<Comment> getListComment(Integer articleId) { String sql = "select * from comment where article_id = ?"; return super.executeQueryForListEntity(sql, articleId); } @Override public Integer getNumOfCommentForArticle(Integer articleId) { String sql = "select count(*) from comment where article_id = ?"; return super.executeQueryForInteger(sql, articleId); } @Override public List<Comment> getLaterCommentList(Integer size) { String sql = "select * from comment order by comment_date desc limit ?"; return super.executeQueryForListEntity(sql, size); } }
下面贴出结果集解析的代码
ResultHandle<T>
public interface ResultHandle<T> { public T getBean(ResultSet res); public List<T> getBeanList(ResultSet res); }
AbstractResultHandle
public abstract class AbstractResultHandle<T> implements ResultHandle<T> { /** * 为了提高代码的再利用所以,把getBeanList方法提取到了这个抽象类中 */ @Override public List<T> getBeanList(ResultSet res) { try { //如果不存在任何数据则返回空的list if(!res.first()){ return Collections.emptyList(); } //将当前游标移动到第一行之上 res.previous(); } catch (SQLException e) { throw new RuntimeException(e); } List<T> list = new ArrayList<T>(); //将每行数据封装成实体对象并添加到list,c为null时表示所给全部记录封装完毕 T c = getBean(res); while(c!=null){ list.add(c); c = getBean(res); } return list; } }
CommentResultHandle
public class CommentResultHandle extends AbstractResultHandle<Comment> { @Override public Comment getBean(ResultSet res) { try { if(res.next()){ Comment c = new Comment(); c.setArticleId(res.getInt("article_id")); c.setCommentBody(res.getString("comment_body")); c.setCommentDate(new Date(res.getTimestamp("comment_date").getTime())); c.setCommentId(res.getInt("comment_id")); c.setCommentImage(res.getString("comment_image")); c.setCommentName(res.getString("comment_name")); return c; }else return null; } catch (SQLException e) { throw new RuntimeException(e); } } }
虽然比价简陋,都还能凑合着用。一旦表的数量太多,那恐怕就成负担了。