通過hibernate封裝資料庫持久化過程回顧泛型/繼承/實現等概念

来源:http://www.cnblogs.com/young-z/archive/2017/11/16/7842905.html
-Advertisement-
Play Games

前言 在開發過程中,我們不難發現,客戶的需求以及產品的定位對開發內容的走向有很大的決策作用,而這些往往需要在一開始就儘可能考慮周全和設計完善。為什麼說是儘可能,因為我們都知道,需求這種東西,一言難盡...作為開發者,既然無法掌控需求的變更等因素,那我們就要把握好自身能決定的工具資源等,架構設計、技術 ...


  前言

在開發過程中,我們不難發現,客戶的需求以及產品的定位對開發內容的走向有很大的決策作用,而這些往往需要在一開始就儘可能考慮周全和設計完善。為什麼說是儘可能,因為我們都知道,需求這種東西,一言難盡...作為開發者,既然無法掌控需求的變更等因素,那我們就要把握好自身能決定的工具資源等,架構設計、技術選型等等。有的人可能會說,我才多久經驗之類,架構什麼的不都是leader們大佬們的事情麽,選什麼資料庫用什麼技術又不是我能決定的。如果你有這種想法,我只能覺得你說得很對。不知道大家在開發過程中,有沒有遇到,某個場景或者效果用現有的工具技術你覺得無法實現或者很難實現,又或者你知道又可以實現的技術框架卻不會用?echarts、POI等,對於我來說,都符合上述場景。總的來說,有的東西在開發過程中可以當作學習,有些東西卻需要你額外花時間在工作之外去研究。當然,如果你說你工作中不管需要什麼新技術,你一天之類就可以掌握,那也是能力。而且這不是嘲諷什麼的,是實實在在的,我現在愈發覺得學習能力的重要性,他對一個人的潛在能力增長曲線的影響太大,當然你有能力卻不學習,那也註定是一條直線射穿。Spring、Strus 2、Hibernate、Mybatis、Spring MVC是比較常見的Web項目會用到的框架,持久層目前來看主要有Hibernate、Mybatis、Spring data jpa等,目前我在用Spring data jpa,這個東西真的厲害,用起來比我以前的想法又上了一個臺階,而且跟hibernate支持的也很好,Hibernate本身也是jpa規範的實現。接下來文中項目中類與方法設計的思路是之前基於Hibernate的,正好回顧一下,認識下其中的不足,好結合現在用的Jpa改進。

  項目結構一覽

以web項目技術框架選型為Spring+Hibernate+Spring MVC為例,忽略配置以及web前端文件,後臺結果最精簡情況大致如下:

從資料庫方向依次向前介紹:

1.domain層,這個東西的標準解釋是領域模型,我們orm對象關係映射的實體類一般就放在該層下,即實體層,類似的叫法,entity、model、pojo等作用大抵如此;

2.repository層,資料庫訪問層,這個就是dao層,存放資料庫訪問操作的方法;

3.service層,業務邏輯層,用於存放業務邏輯方法的地方,與dao層相比,有的人可能開始會覺得這個service層沒有什麼必要,或者不太清楚兩者的區別。首先關於兩者區別:業務邏輯層,故名思意,他的重要定位是業務,業務需求什麼,他就要提供什麼,舉個例子,dao層提供了你刪除商品的方法和添加日誌的方法,這兩個方法分別對應有兩個實體對象商品和日誌,操作的也是資料庫相應的單個表,但是實際情況是你通過單個方法總感覺哪裡不對勁,業務場景下,如果需要你刪除東西後會有相應的日誌記錄,而日誌又不會憑空捏造,需要有事件對應。這時候,service層的作用就體現出來了,簡單的可以這麼理解,複雜的資料庫處理你靠單個dao方法無法實現的時候,你在service層去構造這個方法就行,通過SpringIOC特性,在service層註入你需要的調用的dao方法所在的類或者介面,實際場景一般都是介面。其次關於必要性,我曾經也想過,直接在controller裡面註入多個dao類或者介面不是也能達到想要的效果嗎?Controller顧名思義,控制器,它在web結果中,主要起到一個接受和轉發請求並控制的作用,當你的業務邏輯相對簡單的時候,你覺得看不出多大區別,當實際項目業務邏輯相對複雜很多的情況下,這個controller就有點炸了,像個身兼多職操勞過度的苦工,另外結合上一個疑惑,還有一個很重要的概念就是事務,而Spring的事務管理做得也很到位,通過編程式事務管理或者聲明式事務管理都可以實現,而事務一般就設置在業務邏輯也就是service層上,關於事務也是很重要和精髓的一塊,需要學習也值得學習。

4.controller層,控制層,用struts 2也許會叫action層吧,或者通用點,叫web層其實也可以。他可以接收不同的請求url,調用相應的service層代碼,操作資料庫,跳轉到制定頁面,也可以不跳轉,直接返回數據,這裡的數據目前用json的比較多,典型的應用場景:ajax發起非同步請求,DispatcherServlet捕獲請求後對url進行解析,分發到相應的控制類中的相應方法中執行其中代碼,該方法上加上@ResponseBody即可。

  關於Hibernate在項目中的定位

Hibernate是一個典型的ORM持久層框架,ORM即Object Relational Mapping(對象關係映射),即實體類與資料庫表之間的關係映射,通俗的講,一張表對應一個實體類,一條記錄對應一個實體類對象,欄位對應實體類屬性。對資料庫的操作在Hibernate中有一個重要對象session,通過session封裝一系列資料庫操作方法在資料庫訪問層,所以在上面的結構中,Hibernate主要操作和作用的有domain層和repository層,下麵示例也省略其他層代碼。

  示例

domain層,這裡簡單使用,Mysql資料庫主鍵也用的int自增型,實際應用數據量較大等情況下會用varchar,保存使用UUID賦值主鍵。

 1 @Entity
 2 @Table(name="TBL_USER")
 3 public class User {
 4     private Integer id;
 5     private String username;
 6     private String password;
 7     @Id
 8     @GeneratedValue(strategy=GenerationType.AUTO)
 9     public Integer getId() {
10         return id;
11     }
12     public void setId(Integer id) {
13         this.id = id;
14     }
15     public String getUsername() {
16         return username;
17     }
18     public void setUsername(String username) {
19         this.username = username;
20     }
21     public String getPassword() {
22         return password;
23     }
24     public void setPassword(String password) {
25         this.password = password;
26     }
27     @Override
28     public String toString() {
29         return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
30     }
31     
32     
33     
34 }

repository層

BaseDao泛型介面

public interface BaseDao<T> {
    public void edit(Object obj);        //添加或者更新一條記錄 
    public void delete(int id);            //根據主鍵刪除一條記錄
    public T load(int id);                //根據主鍵查找一條記錄(懶載入)
    public T get(int id);                //根據主鍵查找一條記錄(非懶載入)
}

BaseDao泛型實現類

public class BaseDaoImpl<T> implements BaseDao<T> {
    @Resource
    private SessionFactory factory;
    private Class<T> clazz = GeneriscUtil.getGenericType(this.getClass());
    
    protected Session getSession() {
        return factory.getCurrentSession();
    }
    
    public void edit(Object obj) {
        getSession().saveOrUpdate(obj);
    }

    public void delete(int id) {
        Object object = getSession().get(clazz, id);
        if(object != null) {
            getSession().delete(object);
        }
    }

    public T load(int id) {
        return (T) getSession().load(clazz, id);
    }

    public T get(int id) {
        return (T) getSession().get(clazz, id);
    }

}

泛型工具類

public class GeneriscUtil {
    @SuppressWarnings("rawtypes")
    public static Class getGenericType(Class clazz){
        Type genType = clazz.getGenericSuperclass();//獲取泛型父類  
        Type[] types = ((ParameterizedType) genType).getActualTypeArguments();
        if (!(types[0] instanceof Class)) {
            return Object.class;   
        } 
        return (Class) types[0];
    }
}

 最後:UserDao介面和UserDaoImpl實現類

public interface UserDao extends BaseDao<User> {
    User login(String username, String password);
}
@Repository("UserDao")
public class UserDaoImpl extends BaseDaoImpl<User> implements UserDao {

    public User login(String username, String password) {
        String hql = "from User u where u.username=:un and u.password=:pwd";
        Query query = getSession().createQuery(hql);
        query.setString("un", username) 
            .setString("pwd", password);
        Object obj = query.uniqueResult();
        return obj != null ? (User)obj : null;
    }
    
}

  還有其的XXXDao和XXXDaoImpl,通過繼承和實現,可以讓全部Impl實現類很輕鬆地就擁有基本的CRUD等通用資料庫操作方法,如果某個實體有特殊的Dao操作只需要在相應Dao介面實現,然後在Impl實現類中實現該特殊方法就行,以前認識到的知識點在這裡有了深入理解。

  泛型是一種思想,也是一種技術,動態的獲取類型,讓編程更加靈活,這裡利用泛型,我們可以先不制定實體類對象具體類型,構造一個泛型的Dao介面和實現類,讓後面各自具體的實體Dao去繼承泛型的時候再確定類型,從而也得到了泛型中定義的基本方法。

  繼承體現的是代碼重用思想,當一個方法被構造多次的時候我們就要思考代碼重用的問題了,在這裡每個實體對象都需要基本的資料庫操作方法,如果一個個的去定義將會十分繁瑣和枯燥,通過繼承我們可以省去很多代碼。

  實現不同於繼承,它沒有節省代碼,而且又涉及到抽象的概念,在單個父類與多個子類的繼承關係中,父類某個方法對應的子類實現有差異時,我們對於父類的該方法,即可定義為抽象方法,子類各自實現具體細節即可。舉個例子:動物父類,子類有鳥、魚等,定義動物時,會定義睡覺方法,但是每種動物睡覺情況都不一樣,鳥睡樹上,魚睡水下,你沒法指定具體實現細節,所以就可以定義一個抽象的睡覺方法void sleep();具體的動物實現介面後,重寫該抽象方法,展示實現細節。

  總結繼承和實現:繼承通用的,實現特殊的。在文中構造的持久層中,我們的所有實體通過繼承輕鬆地擁有了所有的通用資料庫操作方法,各自特殊的操作需求可在各自介面中生命然後在實現類中實現即可。

  最後,文中的項目中其實還存在許多不足的地方,主鍵的類型其實也可以用泛型,dao層有通用組件,service層是否應該也有通用的,若是有該如何構造等等,一些問題我在現在用的spring data jpa中得到了答案,所以應該會另外梳理一下寫出來。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 採集美女模特圖片庫時,需要對標題進行分詞,找了好久,終於找到了一個不錯的分詞庫 分詞系統簡介:PHPAnalysis分詞程式使用居於unicode的詞庫,使用反向匹配模式分詞,理論上相容編碼更廣泛,並且對utf-8編碼尤為方便。 由於PHPAnalysis是無組件的系統,因此速度會比有組件的稍慢,不 ...
  • 作者:NiceCui 本文謝絕轉載,如需轉載需徵得作者本人同意,謝謝。 本文鏈接:http://www.cnblogs.com/NiceCui/p/7846812.html 郵箱:[email protected] 日期:2017-11-16 平時寫代碼有時會常用到一些處理日期的邏輯,自己寫了一個工 ...
  • 產品分類管理的html頁面之前忘記做了,這次附件里補上。 好了先上圖 從頁面效果圖來看,我們需要開發列表獲取介面、添加介面、單條記錄獲取介面、編輯介面和刪除介面 對於產品分類列表,我們將使用jqgrid前端表格框架,jqgrid與介面交互時,它會提交頁面索引、頁面大小、排序欄位名以及順序還是倒序排序 ...
  • 一直都以為C/C++中形如 這樣的函數聲明其意義就是一個參數 void(沒有參數)的函數。然而今天在看C++的時候突然看到這麼一句: 這一點老師並沒有講到,學校教科書里也沒有提到,帶著好奇心,我特意試了一下 test.c 這也解釋了為什麼主函數要寫成這樣的原因 ...
  • redis集群的特點: 1.機器多,能夠保證redis伺服器出現問題後,影響較小 2.自備主從結構,自動的根據演算法劃分主從結構.動態的實現 3.能夠根據主從結構自動的實現高可用 4.實現數據文件的備份 3.Redis集群的搭建步驟: 準備9台伺服器 3主6從 一個主機下有2個子節點 7000-700 ...
  • 雖然後臺使用了讀寫分離技術,能夠在一定程度上抗擊高併發,但是如果併發量特別巨大時,主資料庫不能同時處理高併發的請求,這時資料庫容易宕機. 問題: 現在的問題是如何既能保證資料庫正常運行,又能實現用戶數據的入庫操作? 解決方案: 引入rabbitMQ技術: 說明: 當資料庫的訪問壓力過載時,這時會將過 ...
  • 首先在原有的jar包: 需Spring壓縮包中的四個核心JAR包 beans 、context、core 和expression 下載地址: https://pan.baidu.com/s/1qXLHzAW 以及日誌jar包 commons-logging 和log4j 下載地址: https:// ...
  • 註冊、驗證登錄,三次密碼錯誤關進小黑屋 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...