1. 程式人生 > >如何對 JPA 或者 MyBatis 進行技術選型

如何對 JPA 或者 MyBatis 進行技術選型

下面看看大精華總結如下:面看看大精華總結如下:

最佳回答

首先表達個人觀點,JPA必然是首選的。

個人認為僅僅討論兩者使用起來有何區別,何者更加方便,不足以真正的比較這兩個框架。要評判出更加優秀的方案,我覺得可以從軟體設計的角度來評判。個人對 mybatis 並不熟悉,但 JPA 規範和 springdata 的實現,設計理念絕對是超前的。軟體開發複雜性的一個解決手段是遵循 DDD(DDD 只是一種手段,但不是唯一手段),而我著重幾點來聊聊 JPA 的設計中是如何體現領域驅動設計思想的,拋磚引玉。

聚合根和值物件

領域驅動設計中有兩個廣為大家熟知的概念,entity(實體)和 value object(值物件)。entity 的特點是具有生命週期的,有標識的,而值物件是起到一個修飾的作用,其具有不可變性,無標識。在 JPA中 ,需要為資料庫的實體類新增 

@Entity 註解,相信大家也注意到了,這並不是巧合。

 
  1. @Entity

  2. @Table(name = "t_order")

  3. public class Order {

  4. @Id

  5. private String oid;

  6.  
  7. @Embedded

  8. private CustomerVo customer;

  9. @OneToMany(cascade = {CascadeType.ALL}, orphanRemoval = true, fetch = FetchType.LAZY, mappedBy = "order")

  10. private List<OrderItem> orderItems;

  11. }

如上述的程式碼,Order 便是 DDD 中的實體,而 CustomerVo,OrderItem 則是值物件。程式設計者無需關心資料庫如何對映這些欄位,因為在 DDD 中,需要做的工作是領域建模,而不是資料建模。實體和值物件的意義不在此展開討論,但通過此可以初見端倪,JPA 的內涵絕不僅僅是一個 ORM 框架。

倉儲

Repository 模式是領域驅動設計中另一個經典的模式。在早期,我們常常將資料訪問層命名為:DAO,而在 SpringData JPA 中,其稱之為 Repository(倉儲),這也不是巧合,而是設計者有意為之。

熟悉 SpringData JPA 的朋友都知道當一個介面繼承 JpaRepository 介面之後便自動具備了 一系列常用的資料操作方法,findAll, findOne ,save等。

 
  1. public interface OrderRepository extends JpaRepository<Order, String>{

  2. }

那麼倉儲和DAO到底有什麼區別呢?這就要提到一些遺留問題,以及一些軟體設計方面的因素。在這次SpringForAll 的議題中我能夠預想到有很多會強調 SpringData JPA 具有方便可擴充套件的 API,像下面這樣:

 
  1. public interface OrderRepository extends JpaRepository<Order, String>{

  2.  
  3. findByOrderNoAndXxxx(String orderNo,Xxx xx);

  4.  
  5. @Transactional

  6. @Modifying(clearAutomatically = true)

  7. @Query("update t_order set order_status =?1 where id=?2")

  8. int updateOrderStatusById(String orderStatus, String id);

  9. }

但我要強調的是,這是 SpringData JPA 的妥協,其支援這一特性,並不代表其建議使用。因為這並不符合領域驅動設計的理念。注意對比,SpringData JPA 的設計理念是將 Repository 作為資料倉庫,而不是一系列資料庫指令碼的集合,findByOrderNoAndXxxx 方法可以由下面一節要提到的JpaSpecificationExecutor代替,而 updateOrderStatusById 方法則可以由 findOne + save 代替,不要覺得這變得複雜了,試想一下真正的業務場景,修改操作一般不會只涉及一個欄位的修改, findOne + save 可以幫助你完成更加複雜業務操作,而不必關心我們該如何編寫 SQL 語句,真正做到了面向領域開發,而不是面向資料庫 SQL 開發,面向物件的擁躉者也必然會覺得,這更加的 OO。

Specification

上面提到 SpringData JPA 可以藉助 Specification 模式代替複雜的 findByOrderNoAndXxxx 一類 SQL 指令碼的查詢。試想一下,業務不停在變,你怎麼知道將來的查詢會不會多一個條件 變成 findByOrderNoAndXxxxAndXxxxAndXxxx.... 。SpringData JPA 為了實現領域驅動設計中的 Specification 模式,提供了一些列的 Specification 介面,其中最常用的便是 :JpaSpecificationExecutor

 
  1. public interface OrderRepository extends JpaRepository<Order,String>,JpaSpecificationExecutor<Order>{

  2. }

使用 SpringData JPA 構建複雜查詢(join操作,聚集操作等等)都是依賴於 JpaSpecificationExecutor 構建的 Specification 。例子就不介紹,有點長。

請注意,上述程式碼並不是一個例子,在真正遵循 DDD 設計規範的系統中,OrderRepository 介面中就應該是乾乾淨淨的,沒有任何程式碼,只需要繼承 JpaRepository (負責基礎CRUD)以及 JpaSpecificationExecutor (負責Specification 查詢)即可。當然, SpringData JPA 也提供了其他一系列的介面,根據特定業務場景繼承即可。

樂觀鎖

為了解決資料併發問題,JPA 中提供了 @Version ,一般在 Entity 中 新增一個 Long version 欄位,配合 @Version 註解,SpringData JPA 也考慮到了這一點。這一點側面體現出,JPA 設計的理念和 SpringData 作為一個工程解決方案的雙劍合璧,造就出了一個偉大的設計方案。

複雜的多表查詢

很多人青睞 Mybatis ,原因是其提供了便利的 SQL 操作,自由度高,封裝性好……SpringData JPA對複雜 SQL 的支援不好,沒有實體關聯的兩個表要做 join ,的確要花不少功夫。但 SpringData JPA 並不把這個當做一個問題。為什麼?因為現代微服務的架構,各個服務之間的資料庫是隔離的,跨越很多張表的 join 操作本就不應該交給單一的業務資料庫去完成。解決方案是:使用 elasticSearch做檢視查詢 或者 mongodb 一類的Nosql 去完成。問題本不是問題。

總結

真正走進 JPA,真正走進 SpringData 會發現,我們並不是在解決一個數據庫查詢問題,並不是在使用一個 ORM 框架,而是真正地在實踐領域驅動設計。

(再次補充:DDD 只是一種手段,但不是唯一手段)

第二名回答

lexburne 兄說的也很不錯了,不過我還想在補充2點,來消除大家對使用spring data jpa 的誤解
spring data jpa 的好處我相信大家都瞭解,就是開發速度很快,很方便,大家不願意使用spring data jpa 的地方通常是因為sql 不是自己寫的,不可控,複雜查詢不好搞,那麼下面我要說的就是其實對於這種需求,spring data jpa 是完全支援的!!

  1. 第一種方式:@query 註解指定nativeQuery,這樣就可以使用原生sql查詢了,示例程式碼來自官方文件:

     
    1. public interface UserRepository extends JpaRepository<User, Long> {

    2.  
    3. @Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?1", nativeQuery = true)

    4. User findByEmailAddress(String emailAddress);

    5. }

    2.如果單靠sql搞不定怎麼辦?必須要寫邏輯怎麼辦?可以使用官方文件3.6.1 節:Customizing individual repositories 提供的功能去實現,先看官方文件的程式碼:

     
    1. interface CustomizedUserRepository {

    2. void someCustomMethod(User user);

    3. }

    4. class CustomizedUserRepositoryImpl implements CustomizedUserRepository {

    5.  
    6. public void someCustomMethod(User user) {

    7. // Your custom implementation

    8. }

    9. }

    10. interface UserRepository extends CrudRepository<User, Long>, CustomizedUserRepository {

    11.  
    12. // Declare query methods here

    13. }

    我來解釋下上面的程式碼,如果搞不定的查詢方法,可以自定義介面,例如CustomizedUserRepository ,和他的實現了類,然後在這個實現類裡用你自己喜歡的dao 框架,比如說mybatis ,jdbcTemplate ,都隨意,最後在用UserRepository 去繼承CustomizedUserRepository介面,就實現了和其他dao 框架的組合使用!!

那麼下面我在總結1下,有了上面介紹的2種功能,你還在擔心,使用spring data jpa 會有侷限麼,他只會加速你的開發速度,並允許你組合使用其他框架,只有好處,沒有壞處。。
最後再說1點,我最近在看es ,然後看了下spring data es 的文件,大概掃了1下,我發現,學會spring data 其中某1個系列以後,在看其他的,我發現我都不用花時間學。。直接就可以用,對就是這麼神奇~~

第三

工作以來一直是使用 hibernate 和 mybatis,總結下來一般傳統公司、個人開發(可能只是我)喜歡用jpa,網際網路公司更青睞於 mybatis
原因:,而mybatis 更加靈活。開發迭代模式決定的,傳統公司需求迭代速度慢,專案改動小,hibernate可以幫他們做到一勞永逸;而網際網路公司追求快速迭代,需求快速變更,靈活的 mybatis 修改起來更加方便,而且一般每一次的改動不會帶來效能上的下降,hibernate經常因為新增關聯關係或者開發者不瞭解優化導致專案越來越糟糕(本來開始也是效能很好的)

1、mybatis官方文件就說了他是一個半自動化的持久層框架,相對於全自動化的 hibernate 他更加的靈活、可控
2、mybatis 的學習成本低於 hibernate。hibernate 使用需要對他有深入的理解,尤其是快取方面,作為一個持久層框架,效能依然是第一位的。

hibernate 它有著三級快取,一級快取是預設開啟的,二級快取需要手動開啟以及配置優化,三級快取可以整合業界流行的快取技術 redis,ecache 等等一起去實現
hibernate 使用中的優化點:
1、快取的優化
2、關聯查詢的懶載入(在開發中,還是不建議過多使用外來鍵去關聯操作)

jpa(Java Persistence API) 與 hibernate 的關係:
Jpa是一種規範,hibernate 也是遵從他的規範的。
springDataJpa 是對 repository 的封裝,簡化了 repository 的操作

第四

  • 資料分析型的OLAP應用適合用MyBatis,事務處理型OLTP應用適合用JPA。
  • 越是複雜的業務,越需要領域建模,建模用JPA實現最方便靈活。但是JPA想用好,門檻比較高,不懂DDD的話,就會淪為增刪改查了。
  • 複雜的查詢應該是通過CQRS模式,通過非同步佇列建立合適查詢的檢視,通過檢視避免複雜的Join,而不是直接查詢領域模型。
  • 從目前的趨勢來看OLAP交給NoSQL資料庫可能更合適

第五

使用了一段時間jpa,而mybatis是之前一直在用的,不說區別是啥,因為有很多人比較這兩個框架了!
從國內開源的應用框架來看,國內使用jpa做orm的人還是比較少,如果換成hibernate還會多一些,所以面臨的風險可能就是你會用,和你合作的人不一定會用,如果要多方協作,肯定要考慮這個問題!
靈活性方面,jpa更靈活,包括基本的增刪改查、資料關係以及資料庫的切換上都比mybatis靈活,但是jpa門檻較高,另外就是更新資料需要先將資料查出來才能進行更新,資料量大的時候,jpa效率會低一些,這時候需要做一些額外的工作去處理!
現在結合Springboot有Springdata jpa給到,很多東西都簡化了,感興趣並且有能力可以考慮在公司內部和圈子裡推廣!我的部落格裡有一些簡單使用jpa的示例,https://github.com/icnws/spring-data-jpa-demo

第六

1.相對來說,jpa的學習成本比mybatis略高
2.公司業務需求頻繁變更導致表結構複雜,此處使用mybatis比jpa更靈活

3.就方言來講,一般公司選定資料庫後再變更微乎其微,所以此處方言的優勢可以忽略

轉載於:http://www.spring4all.com/article/391