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; } }
希望看到本貼的大佬們,能留言提出一個最完美的解決對策!!!感謝!!!!
希望看到本貼的大佬們,能留言提出一個最完美的解決對策!!!感謝!!!!
希望看到本貼的大佬們,能留言提出一個最完美的解決對策!!!感謝!!!!