Java封装BaseDao时经常困扰的一个问题,就是封装executeQuery()方法的问题

1. 如果封装该方法返回一个ResultSet对象的话,会出现资源无法释放的尴尬情况

2. 如果提前关闭Connection对象和PreparedStatement对象的话返回出去的ResultSet对象将会无法使用

3. 不释放资源的话虽然可以使用,但是总觉得不舒服

为了解决这个问题,试了好久终于发现一个还算不错的方法,虽然不能完美的解决这个问题,最起码是可以任意使用的

废话不多说,贴代码:

首先,我们编写BaseDao类时,声明一个额外的抽象方法(所以BaseDao也要被定义为抽象类),该方法如下:

/*** 获取所有信息的方法返回一个List泛型集合
* 由实现该方法的类来确定返回的集合的类型
* 补充,在声明该方法时,需要将BaseDao声明一个泛型
*@paramrs
*@return
*/
public abstract List getAllInfo(ResultSet rs);
声明这个方法之后,我们就可以开始封装executeQuery()方法了,具体封装如下:
这里我们仍然返回的是一个泛型集合List
/*** 查询对象,返回一个泛型集合*/
public ListexecuteQuery(String sql,Object...params){//连接对象
Connection conn =getConnection();//执行SQL对象
PreparedStatement pstmt = null;//结果集对象
ResultSet rs = null;//处理SQL语句
try{
pstmt=conn.prepareStatement(sql);//判断传入的参数是否为空
if(params != null){//循环赋值
for (int i = 0; i < params.length; i++) {
pstmt.setObject(i+1,params[i]);
}
}//创建结果集对象
rs =pstmt.executeQuery();//调用抽象方法来返回一个泛型集合
List list =getAllInfo(rs);returnlist;
}catch(SQLException e) {
e.printStackTrace();return null;
}finally{//关闭连接
closeAll(conn,pstmt,rs);
}
}

接着我们就可以创建BaseDao的子类了,我们都知道子类继承父类时需要实现父类所有的抽象方法。

所以,我们在创建了子类后,利用子类来实现 List getAllInfo(ResultSet rs); 方法,具体实现如下:

PS:同时有必要给大家看一下 NewsDao 接口中的东西

NewsDao 接口:

1 packagedao;2
3 importentity.News;4
5 importjava.util.List;6
7 /**
8 * @user: Mr.Wang9 * @date: 2019/5/2110 * @time: 20:0211 */
12 public interfaceNewsDao {13
14 ListgetAllnews();15
16 }
NewsImpl 实现类:
1 packagedao.impl;2 importdao.BaseDao;3 importdao.NewsDao;4 importentity.News;5 importjava.sql.ResultSet;6 importjava.util.ArrayList;7 importjava.util.List;8
9 /**
10 * @user: Mr.Wang11 * @date: 2019/5/2112 * @time: 20:0413 */
14 public class NewsImpl extends BaseDao implementsNewsDao {15
16 /**
17 * 查询获得所有用户的方法18 *@return
19 */
20 @Override21 public ListgetAllnews() {22 //SQL语句
23 String sql = "SELECT * FROM news";24 //调用查询方法返回List集合
25 return executeQuery(sql,null);26 }27
28 /**
29 * 实现父类的方法30 *@paramrs 结果集31 *@return
32 */
33 @Override34 public ListgetAllInfo(ResultSet rs) {35 List list = null;36 try{37 //判断rs是否为空
38 if(null !=rs){39 //创建List
40 list = new ArrayList();41 //遍历结果集
42 while(rs.next()){43 //创建News对象
44 News news = newNews();45 //取出结果集中的值
46 news.setNid(rs.getInt("nid"));47 news.setNtitle(rs.getString("ntitle"));48 news.setNauthor(rs.getString("nauthor"));49 news.setNcontent(rs.getString("ncontent"));50 //将该对象添加进集合
51 list.add(news);52 }53 }54 //返回list
55 returnlist;56 } catch(Exception e){57 e.printStackTrace();58 return null;59 }60 }61 }
释:大概意思就是,实现时,确定了泛型的返回类型为,这时我们就可以创建一个List集合
正常的利用参数 Resultset rs 去遍历结果集,将结果集存入 List 中
因为我们在调用封装的executeQuery()方法时调用过了getAllInfo(ResultSet rs)方法
所以当我们重写后,将会调用我们重写后得方法,这样就可以顺利取出值。
缺点问题:大概就是这个流程,但是有个问题就是,有时我们继承BaseDao的类可能不需要用到查询出所有结果的要求,可能只是根据要求找出一个对象
这时我们继承BaseDao又得必须实现getAllInfo(ResultSet rs)方法显得有些鸡肋。。。这个问题本小白暂时没找出好的解决方法
我是用了一种比较投机取巧的方法去完成的,比如登录验证,只用返回单个结果,我是这样完成的,代码如下:
PS:BaseDao的代码和实现类的代码和上述基本一致,所以就不贴了,贴出来业务逻辑层的代码是怎么处理的!
因为同样返回了集合,所以在写SQL语句时将条件写在了WHERE条件中,这样就可以确保找到我们想要的数据
然后我们接收到返回的集合,通过判断集合的长度来确定我们是否找到符合条件的数据,详细代码如下:
packageservice;importdao.impl.NewsUsersImpl;importentity.NewsUsers;importjava.util.List;/*** @user: Mr.Wang
* @date: 2019/5/21
* @time: 16:44
* 业务逻辑类,负责进行逻辑判断*/
public classNewsUserService {//new一个NewsUserImpl对象,调用其登录验证的方法
private NewsUsersImpl newsUsers = newNewsUsersImpl();/*** 登录验证
*@paramname 登录名
*@parampwd 登录密码
*@return返回一个boolean类型*/
public booleanloginVerify(String name,String pwd){boolean flag = true;//调用验证方法返回一个集合
List list =newsUsers.loginVerify(name,pwd);//判断该集合的长度是否大于0
if(list.size() <= 0){
flag= false;
}returnflag;
}
}