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; } }
希望看到本贴的大佬们,能留言提出一个最完美的解决对策!!!感谢!!!!
希望看到本贴的大佬们,能留言提出一个最完美的解决对策!!!感谢!!!!
希望看到本贴的大佬们,能留言提出一个最完美的解决对策!!!感谢!!!!