关于Java怎样封装executeQuery()的问题

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

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

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

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

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

废话不多说,贴代码:

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

  /**
     * 获取所有信息的方法返回一个List泛型集合
     * 由实现该方法的类来确定返回的集合的类型
* 补充,在声明该方法时,需要将BaseDao声明一个<T>泛型 *
@param rs * @return */ public abstract List<T> getAllInfo(ResultSet rs);

声明这个方法之后,我们就可以开始封装executeQuery()方法了,具体封装如下:

这里我们仍然返回的是一个泛型集合List<T>

  /**
     * 查询对象,返回一个泛型集合
     */
    public List<T> executeQuery(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<T> list = getAllInfo(rs);
            return list;
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        } finally {
            //关闭连接
            closeAll(conn,pstmt,rs);
        }
    }

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

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

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

NewsDao 接口:

 

 1 package dao;
 2 
 3 import entity.News;
 4 
 5 import java.util.List;
 6 
 7 /**
 8  * @user: Mr.Wang
 9  * @date: 2019/5/21
10  * @time: 20:02
11  */
12 public interface NewsDao {
13 
14     List<News> getAllnews();
15 
16 }

 

NewsImpl 实现类:

 

 1 package dao.impl;
 2 import dao.BaseDao;
 3 import dao.NewsDao;
 4 import entity.News;
 5 import java.sql.ResultSet;
 6 import java.util.ArrayList;
 7 import java.util.List;
 8 
 9 /**
10  * @user: Mr.Wang
11  * @date: 2019/5/21
12  * @time: 20:04
13  */
14 public class NewsImpl extends BaseDao implements NewsDao {
15 
16     /**
17      * 查询获得所有用户的方法
18      * @return
19      */
20     @Override
21     public List<News> getAllnews() {
22         //SQL语句
23         String sql = "SELECT * FROM news";
24         //调用查询方法返回List集合
25         return executeQuery(sql,null);
26     }
27 
28     /**
29      * 实现父类的方法
30      * @param rs 结果集
31      * @return
32      */
33     @Override
34     public List<News> getAllInfo(ResultSet rs) {
35         List<News> list = null;
36         try{
37             //判断rs是否为空
38             if(null != rs){
39                 //创建List
40                 list = new ArrayList<News>();
41                 //遍历结果集
42                 while(rs.next()){
43                     //创建News对象
44                     News news = new News();
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             return list;
56         } catch (Exception e){
57             e.printStackTrace();
58             return null;
59         }
60     }
61 }

释:大概意思就是,实现时,确定了泛型的返回类型为<News>,这时我们就可以创建一个List<News>集合

  正常的利用参数 Resultset rs 去遍历结果集,将结果集存入 List<News> 中

  因为我们在调用封装的executeQuery()方法时调用过了getAllInfo(ResultSet rs)方法

  所以当我们重写后,将会调用我们重写后得方法,这样就可以顺利取出值。

缺点问题:大概就是这个流程,但是有个问题就是,有时我们继承BaseDao的类可能不需要用到查询出所有结果的要求,可能只是根据要求找出一个对象

这时我们继承BaseDao又得必须实现getAllInfo(ResultSet rs)方法显得有些鸡肋。。。这个问题本小白暂时没找出好的解决方法

我是用了一种比较投机取巧的方法去完成的,比如登录验证,只用返回单个结果,我是这样完成的,代码如下:

PS:BaseDao的代码和实现类的代码和上述基本一致,所以就不贴了,贴出来业务逻辑层的代码是怎么处理的!

因为同样返回了集合,所以在写SQL语句时将条件写在了WHERE条件中,这样就可以确保找到我们想要的数据

然后我们接收到返回的集合,通过判断集合的长度来确定我们是否找到符合条件的数据,详细代码如下:

 

package service;
import dao.impl.NewsUsersImpl;
import entity.NewsUsers;
import java.util.List;

/**
 * @user: Mr.Wang
 * @date: 2019/5/21
 * @time: 16:44
 * 业务逻辑类,负责进行逻辑判断
 */
public class NewsUserService {

    // new一个NewsUserImpl对象,调用其登录验证的方法
    private NewsUsersImpl newsUsers = new NewsUsersImpl();

    /**
     * 登录验证
     * @param name 登录名
     * @param pwd   登录密码
     * @return 返回一个boolean类型
     */
    public boolean loginVerify(String name,String pwd){
        boolean flag = true;
        //调用验证方法返回一个集合
        List<NewsUsers> list = newsUsers.loginVerify(name,pwd);
        //判断该集合的长度是否大于0
        if(list.size() <= 0){
            flag = false;
        }
        return flag;
    }

}

希望看到本贴的大佬们,能留言提出一个最完美的解决对策!!!感谢!!!!

希望看到本贴的大佬们,能留言提出一个最完美的解决对策!!!感谢!!!!

希望看到本贴的大佬们,能留言提出一个最完美的解决对策!!!感谢!!!!

 

posted @ 2019-05-21 23:43  斗佛Uncle  阅读(1904)  评论(0编辑  收藏  举报
Live2D