成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

說實話,Hibernate和MyBatis哪個更好用?

數據庫 其他數據庫
當前流行的方案有Hibernate與myBatis。兩者各有優劣。競爭激烈,其中一個比較重要的考慮的地方就是性能。因此筆者通過各種實驗,測出兩個在相同情景下的性能相關的指數,供大家參考。

 [[356297]]

前言

由于編程思想與數據庫的設計模式不同,生出了一些ORM框架。核心都是將關系型數據庫和數據轉成對象型。當前流行的方案有Hibernate與myBatis。兩者各有優劣。競爭激烈,其中一個比較重要的考慮的地方就是性能。因此筆者通過各種實驗,測出兩個在相同情景下的性能相關的指數,供大家參考。

測試目標

以下測試需要確定幾點內容:

性能差異的場景;

性能不在同場景下差異比;

找出各架框優劣,各種情況下的表現,適用場景。

測試思路

測試總體分成:單表插入,關聯插入,單表查詢,多表查詢。

測試分兩輪,同場景下默認參數做一輪,調優做強一輪,橫縱對比分析了。

測試中盡保證輸入輸出的一致性。

樣本量盡可能大,達到10萬級別以上,減少統計誤差。

測試提綱

具體的場景情況下

插入測試1:10萬條記錄插入。

查詢測試1:100萬數據中單表通過id查詢100000次,無關聯字段。

查詢測試2:100萬數據中單表通過id查詢100000次,輸出關聯對象字段。

查詢測試3:100萬*50萬關聯數據中查詢100000次,兩者輸出相同字段。

準備

數據庫:mysql 5.6

表格設計:

twitter:推特 

  1. CREATE TABLE `twitter` (  
  2.   `id` bigint(20) NOT NULL AUTO_INCREMENT, 
  3.   `add_date` datetime DEFAULT NULL,  
  4.   `modify_date` datetime DEFAULT NULL,  
  5.   `ctx` varchar(255) NOT NULL,  
  6.   `add_user_id` bigint(20) DEFAULT NULL,  
  7.   `modify_user_id` bigint(20) DEFAULT NULL,  
  8.   PRIMARY KEY (`id`),  
  9.   KEY `UPDATE_USER_FORI` (`modify_user_id`), 
  10.   KEY `ADD_USER_FORI` (`add_user_id`), 
  11.   CONSTRAINT `ADD_USER_FORI` FOREIGN KEY (`add_user_id`) REFERENCES `user` (`id`) ON DELETE SET NULL,  
  12.   CONSTRAINT `UPDATE_USER_FORI` FOREIGN KEY (`modify_user_id`) REFERENCES `user` (`id`) ON DELETE SET NULL  
  13. ENGINE=InnoDB AUTO_INCREMENT=1048561 DEFAULT CHARSET=utf8 

user: 用戶 

  1. CREATE TABLE `user` (  
  2.   `id` bigint(20) NOT NULL AUTO_INCREMENT,  
  3.   `name` varchar(255) DEFAULT NULL,  
  4.   PRIMARY KEY (`id`)  
  5. ENGINE=InnoDB AUTO_INCREMENT=524281 DEFAULT CHARSET=utf8 

測試數據準備:

表一:twitter

無數據。

表二:user

50萬個隨機的用戶名。

隨機內容推特表(material_twitter)

無id,僅有隨機字符串內容,共10萬條。

用于插入控推特表。

生成數據代碼,關聯100個用戶: 

  1. insert into twitter(ctx,add_user_id,modify_user_id,add_date,modify_date)  
  2. SELECT name,ROUND(RAND()*100)+1,ROUND(RAND()*100)+1,'2016-12-31','2016-12-31'  
  3. from MATERIAL 

生成數據代碼,關聯500000個用戶: 

  1. insert into twitter(ctx,add_user_id,modify_user_id,add_date,modify_date)  
  2. SELECT name,ROUND(RAND()*500000)+1,ROUND(RAND()*500000)+1,'2016-12-31','2016-12-31'  
  3. from MATERIAL 

實體代碼 

  1. @Entity  
  2. @Table(name = "twitter" 
  3. public class Twitter implements java.io.Serializable{  
  4.   private Long id;  
  5.   private Date add_date;  
  6.   private Date modify_date;  
  7.   private String ctx;  
  8.   private User add_user;  
  9.   private User modify_user; 
  10.   private String createUserName; 
  11.   @Id  
  12.   @GeneratedValue(strategy = IDENTITY 
  13.   @Column(name = "id"unique = truenullable = false 
  14.   public Long getId() {  
  15.     return id;  
  16.   }  
  17.   public void setId(Long id) {  
  18.     this.id = id;  
  19.   }  
  20.   @Temporal(TemporalType.DATE)  
  21.   @Column(name = "add_date" 
  22.   public Date getAddDate() {  
  23.     return add_date;  
  24.   }  
  25.   public void setAddDate(Date add_date) {  
  26.     this.add_date = add_date;  
  27.   }  
  28.   @Temporal(TemporalType.DATE)  
  29.   @Column(name = "modify_date" 
  30.   public Date getModifyDate() {  
  31.     return modify_date;  
  32.   }  
  33.   public void setModifyDate(Date modify_date) {  
  34.     this.modify_date = modify_date;  
  35.   }  
  36.   @Column(name = "ctx" 
  37.   public String getCtx() {  
  38.     return ctx;  
  39.   }  
  40.   public void setCtx(String ctx) {  
  41.     this.ctx = ctx;  
  42.   }  
  43.   @ManyToOne(fetch = FetchType.LAZY)  
  44.   @JoinColumn(name = "add_user_id" 
  45.   public User getAddUser() { 
  46.      return add_user; 
  47.   }  
  48.   public void setAddUser(User add_user) {  
  49.     this.add_user = add_user;  
  50.   }  
  51.   @ManyToOne(fetch = FetchType.LAZY)  
  52.   @JoinColumn(name = "modify_user_id" 
  53.   public User getModifyUser() {  
  54.     return modify_user;  
  55.   }  
  56.   public void setModifyUser(User modify_user) {  
  57.     this.modify_user = modify_user;  
  58.   } 
  59.   @Transient  
  60.   public String getCreateUserName() {  
  61.     return createUserName;  
  62.   }  
  63.   public void setCreateUserName(String createUserName) {  
  64.     this.createUserName = createUserName;  
  65.   }   

開始

插入測試1

代碼操作:

將隨機內容推特表的數據加載到內存中,然后一條條加入到推特表中,共10萬條。

關鍵代碼:

hibernate: 

  1. Session session = factory.openSession();  
  2.     session.beginTransaction();  
  3.     Twitter t = null 
  4.     Date now = new Date();  
  5.     for(String materialTwitter : materialTwitters){  
  6. // System.out.println("materialTwitter="+materialTwitter);  
  7.            t = new Twitter();  
  8.         t.setCtx(materialTwitter);  
  9.            t.setAddDate(now);  
  10.            t.setModifyDate(now);  
  11.            t.setAddUser(null);  
  12.            t.setModifyUser(null);  
  13.            session.save(t);  
  14.       } 
  15.      session.getTransaction().commit(); 

mybatis: 

  1. Twitter t = null 
  2.     Date now = new Date();  
  3.     for(String materialTwitter : materialTwitters){  
  4. // System.out.println("materialTwitter="+materialTwitter);  
  5.            t = new Twitter();  
  6.            t.setCtx(materialTwitter);  
  7.            t.setAddDate(now);  
  8.            t.setModifyDate(now);  
  9.            t.setAddUser(null);  
  10.            t.setModifyUser(null);  
  11.            msession.insert("insertTwitter", t);  
  12.       }  
  13.     msession.commit(); 

TwitterMapper.xml,插入代碼片段: 

  1. <insert id="insertTwitter" keyProperty="id" parameterType="org.pushio.test.show1.entity.Twitter" useGeneratedKeys="true">  
  2.         insert into twitter(ctx, add_date,modify_date) values (#{ctx},#{add_date},#{modify_date})  
  3.     </insert> 

查詢測試1

通過id從1遞增到10萬依次進行查詢推特內容,僅輸出微博內容。

關鍵代碼:

hibernate: 

  1. long cnt = 100000 
  2.     for(long i = 1; i <= cnt; ++i){  
  3.       Twitter t = (Twitter)session.get(Twitter.class, i);  
  4.       //System.out.println("t.getCtx="+ t.getCtx() + " t.getUser.getName=" + t.getAddUser().getName());  
  5.     } 

mybatis: 

  1. long cnt = 100000 
  2.     for(long i = 1; i <= cnt; ++i){  
  3.       Twitter t = (Twitter)msession.selectOne("getTwitter", i);  
  4.       //System.out.println("t.getCtx="+ t.getCtx() + " t.getUser.getName=" + t.getAddUser().getName());  
  5.     } 

查詢測試2

與查詢測試1總體一樣,增加微博的創建人名稱字段,此處需要關聯。

其中微博對應有10萬個用戶。可能一部份用戶重復。這里對應的用戶數可能與hibernate配懶加載的情況有影響。

此處體現了hibernate的一個方便處,可以直接通過getAddUser()可以取得user相關的字段。

然而myBatis則需要編寫新的vo,因此在測試batis時則直接在Twitter實體中增加創建人員名字成員(createUserName)。

此處hibernate則會分別測試有懶加載,無懶加載。

mybatis會測有默認與有緩存兩者情況。

其中mybatis的緩存機制比較難有效配置,不適用于真實業務(可能會有臟數據),在此僅供參考。

測試時,對推特關聯的用戶數做了兩種情況,一種是推特共關聯了100個用戶,也就是不同的推特也就是在100個用戶內,這里的關聯關系隨機生成。

另外一種是推特共關聯了50萬個用戶,基本上50個用戶的信息都會被查詢出來。

在上文“準備”中可以看到關聯數據生成方式。

關鍵代碼:

hibernate: 

  1. long cnt = 100000 
  2. for(long i = 1; i <= cnt; ++i){  
  3.       Twitter t = (Twitter)session.get(Twitter.class, i);  
  4.       t.getAddUser().getName();//加載相應字段  
  5.       //System.out.println("t.getCtx="+ t.getCtx() + " t.getUser.getName=" + t.getAddUser().getName());  
  6.     } 

急懶加載配置更改處,Twitter.java: 

  1. @ManyToOne(fetch = FetchType.EAGER)//急加載  
  2.       //@ManyToOne(fetch = FetchType.LAZY)//懶加載  
  3.   @JoinColumn(name = "add_user_id" 
  4.   public User getAddUser() {  
  5.     return add_user;  
  6.   } 

mybatis: 

  1. for(long i = 1; i <= cnt; ++i){  
  2.       Twitter t = (Twitter)msession.selectOne("getTwitterHasUser", i);  
  3.       //System.out.println("t.getCtx="+ t.getCtx() + " t.getUser.getName=" + t.getCreateUserName());  
  4.     } 

TwitterMapper.xml配置: 

  1. <select id="getTwitterHasUser" parameterType="long"   
  2.          resultType="org.pushio.test.show1.entity.Twitter">  
  3.          select twitter.*,user.name as creteUserName from twitter,user  
  4.          where twitter.id=#{id}  
  5.            AND twitter.add_user_id=user.id   
  6.      </select> 

測試結果

測試分析

測試分成了插入,單表查詢,關聯查詢。關聯查詢中hibernate分成三種情況進行配置。其中在關聯字段查詢中,hibernate在兩種情況下,性能差異比較大。都是在懶加載的情況下,如果推特對應的用戶比較多時,則性能會比僅映射100個用戶的情況要差很多。

換而言之,如果用戶數量少(關聯的總用戶數)時,也就是會重復查詢同一個用戶的情況下,則不需要對用戶表做太多的查詢。其中通過查詢文檔后,證明使用懶加載時,對象會以id為key做緩存,也就是查詢了100個用戶后,后續的用戶信息使用了緩存,使性能有根本性的提高。甚至要比myBatis更高。

如果是關聯50萬用戶的情況下,則hibernate需要去查詢50萬次用戶信息,并組裝這50萬個用戶,此時性能要比myBatis性能要差,不過差異不算大,小于1ms,表示可以接受。其中hibernate非懶加載情況下與myBatis性能差異也是相對其他測試較大,平均值小于1ms。

這個差異的原因主要在于,myBatis加載的字段很干凈,沒有太多多余的字段,直接映身入關聯中。反觀hibernate則將整個表的字都會加載到對象中,其中還包括關聯的user字段。

hibernate這種情況下有好有壞,要看具體的場景,對于管理平臺,需要展現的信息較多,并發要求不高時,hibernate比較有優勢。

然而在一些小活動,互聯網網站,高并發情況下,hibernate的方案太不太適合,myBatis+VO則是首選。

測試總結

總體初觀,myBatis在所有情況下,特別是插入與單表查詢,都會微微優于hibernate。不過差異情況并不明顯,可以基本忽略差異。差異比較大的是關聯查詢時,hibernate為了保證POJO的數據完整性,需要將關聯的數據加載,需要額外地查詢更多的數據。這里hibernate并沒有提供相應的靈活性。

關聯時一個差異比較大的地方則是懶加載特性。其中hibernate可以特別地利用POJO完整性來進行緩存,可以在一級與二級緩存上保存對象,如果對單一個對象查詢比較多的話,會有很明顯的性能效益。以后關于單對象關聯時,可以通過懶加載加二級緩存的方式來提升性能。

最后,數據查詢的性能與orm框架關無太大的關系,因為orm主要幫助開發人員將關系數據轉化成對象型數據模型,對代碼的深析上來看,hibernate設計得比較重量級,對開發來說可以算是重新開發了一個數據庫,不讓開發去過多關心數據庫的特性,直接在hibernate基礎上進行開發,執行上分為了sql生成,數據封裝等過程,這里花了大量的時間。

然而myBatis則比直接,主要是做關聯與輸出字段之間的一個映射。其中sql基本是已經寫好,直接做替換則可,不需要像hibernate那樣去動態生成整條sql語句。

好在hibernate在這階段已經優化得比較好,沒有比myBatis在性能上差異太多,但是在開發效率上,可擴展性上相對myBatis來說好太多。最后的最后,關于myBatis緩存,hibernate查詢緩等,后續會再專門做一篇測試。

關于緩存配置

myBatis相對Hibernate 等封裝較為嚴密的ORM 實現而言,因為hibernate對數據對象的操作實現了較為嚴密的封裝,可以保證其作用范圍內的緩存同步,而ibatis 提供的是半封閉的封裝實現,因此對緩存的操作難以做到完全的自動化同步。以上的緩存配置測試僅為性能上的分析,沒有加入可用性上的情況,因為myBatis直接配置緩存的話,可能會出現臟數據。

在關聯查詢數據的情況下,hiberntae的懶加載配二級緩存是個比較好的方案(無臟數據),也是與myBatis相比有比較明顯的優勢。此情景下,性能與myBatis持平。

在真實情況下,myBatis可能不會在這個地方上配置緩存,會出現臟數據的情況,因而很有可能在此hibernate性能會更好。 

 

責任編輯:龐桂玉 來源: Java編程
相關推薦

2024-01-26 08:41:55

Fluent工具包高并發

2019-07-27 09:40:56

MySQLPG數據庫

2020-06-08 11:30:04

PGMySQL數據庫

2022-08-03 13:56:10

互聯網跳槽

2024-01-22 15:55:15

2024-07-09 10:20:05

VueJSX函數

2017-03-02 14:52:46

2021-06-28 11:17:14

CoutPrintf接口

2023-04-14 07:49:26

iOS安卓

2022-09-02 08:28:44

AWS多云云提供商

2016-08-05 14:23:15

系統

2022-04-20 12:17:50

命令Batcat

2022-04-25 10:04:56

df命令Linux

2018-04-12 10:02:57

大數據領域工具

2020-08-18 16:10:44

ManjaroArch LinuxLinux

2023-09-05 07:32:22

vscode開源故障

2021-04-12 08:01:21

GridFlexbox網格

2018-12-11 12:38:23

UbuntuMint發行版

2023-12-12 10:11:41

2022-05-22 07:32:36

RPython分析工具
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 一级在线视频 | 亚洲91精品| 午夜专区 | 日本一区二区三区四区 | 国产精品一区二区视频 | 成人超碰 | 国产精品日韩欧美一区二区 | 国产美女在线看 | 蜜桃视频在线观看免费视频网站www | 久久中文免费视频 | 午夜资源 | 精品久久久久久久久久 | 日韩一区二区在线视频 | 日韩成人在线播放 | 久久一区二区视频 | 国产精品视频网 | 中文在线a在线 | 西西裸体做爰视频 | 97精品国产97久久久久久免费 | 日本亚洲一区 | 日韩三区| 亚洲成人毛片 | 色噜噜狠狠色综合中国 | 欧美日韩视频一区二区 | 亚洲国产中文字幕 | 成人aaa视频 | 久久久精彩视频 | 欧美成人免费 | 国产日韩精品久久 | 天天曰夜夜 | 欧美黄色网 | 九九99九九精彩46 | 欧美片网站免费 | 午夜日韩 | 9久久精品 | 久久久久九九九女人毛片 | 日韩在线不卡视频 | 精品久久99 | 久久一区| 精品国产91亚洲一区二区三区www | 欧美自拍第一页 |