DAO层的作用不多说了,大家都知道
说下我的DAO层结构
BaseDao
BaseDaoImpl
ResultHandle
AbstractResultHandle
BaseDao
public interface BaseDao {
/**
* 查询单条记录的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 executeQueryForListEntity(String sql,Object... params);
}
BaseDaoImpl
public class BaseDaoImpl implements BaseDao{
//从filter中获得连接,最后又filter进行释放,见BlogFilter
Connection conn = BlogFilter.getConnection();
ResultHandle handle;
//通过构造方法传入相应的结果集解析实现
public BaseDaoImpl(ResultHandle 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 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 getListComment(Integer articleId);
public Integer getNumOfCommentForArticle(Integer articleId);
public List getLaterCommentList(Integer size);
}
CommentDaoImpl
public class CommentDaoImpl extends BaseDaoImpl 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 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 getLaterCommentList(Integer size) {
String sql = "select * from comment order by comment_date desc limit ?";
return super.executeQueryForListEntity(sql, size);
}
}
下面贴出结果集解析的代码
ResultHandle
public interface ResultHandle {
public T getBean(ResultSet res);
public List getBeanList(ResultSet res);
}
AbstractResultHandle
public abstract class AbstractResultHandle implements ResultHandle {
/**
* 为了提高代码的再利用所以,把getBeanList方法提取到了这个抽象类中
*/
@Override
public List getBeanList(ResultSet res) {
try {
//如果不存在任何数据则返回空的list
if(!res.first()){
return Collections.emptyList();
}
//将当前游标移动到第一行之上
res.previous();
} catch (SQLException e) {
throw new RuntimeException(e);
}
List list = new ArrayList();
//将每行数据封装成实体对象并添加到list,c为null时表示所给全部记录封装完毕
T c = getBean(res);
while(c!=null){
list.add(c);
c = getBean(res);
}
return list;
}
}
CommentResultHandle
public class CommentResultHandle extends AbstractResultHandle {
@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);
}
}
}
虽然比价简陋,都还能凑合着用。一旦表的数量太多,那恐怕就成负担了。