国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - Hibernate的Session_flush與隔離級別代碼詳解

Hibernate的Session_flush與隔離級別代碼詳解

2021-04-02 15:43lavimer Java教程

這篇文章主要介紹了Hibernate的Session_flush與隔離級別代碼詳解,分享了相關(guān)代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下

本文研究的主要是hibernate的session_flush與隔離級別,具體介紹和實例如下。

概念介紹

 

我們先來看一些概念:

1.臟讀:臟讀又稱為無效數(shù)據(jù)的讀出,是指在數(shù)據(jù)庫訪問中,事物t1將某一值修改,然后事物t2讀取該值,此后t1因為某種原因撤銷對該值的修改,這就導(dǎo)致了t2所讀取的數(shù)據(jù)是無效的。臟讀就是指當(dāng)一個事物正在訪問數(shù)據(jù),并且對數(shù)據(jù)進(jìn)行了修改,而這種修改還沒有提交到數(shù)據(jù)庫中,這時,另外一個事物也訪問這個數(shù)據(jù),然后使用了這個數(shù)據(jù)。因為這個數(shù)據(jù)還是沒有提交的數(shù)據(jù),那么另外一個事物讀到的這個數(shù)據(jù)就是臟數(shù)據(jù),依據(jù)臟數(shù)據(jù)所做的操作是不正確的。

2.不可重復(fù)讀:比如我在讀一個帖子,我查出來的數(shù)據(jù)是張三、李四,然后我一刷新發(fā)現(xiàn)最開始的張三變成了張八,這就是所謂的不可重復(fù)讀,因為我讀出的數(shù)據(jù)沒重復(fù)了嘛。

3.幻讀:我在查數(shù)據(jù)的時候,開始查出來的記錄為3條,我一刷新,發(fā)現(xiàn)記錄變?yōu)榱?條,這就是幻讀。

4.提交讀:提交了之后才可以讀取,oracle默認(rèn)就是這個,這種方式是不存在臟讀的。

5.可重復(fù)度:很顯然是和不可重復(fù)讀相反的,它可以避免不可重復(fù)讀,但是這個不能避免幻讀。

6.序列化:這種方式非常嚴(yán)格,通俗的說就是,當(dāng)我在做一件事情的時候,其他任何人都不能做,非常安全,但是效率極低。

隔離級別

 

Hibernate的Session_flush與隔離級別代碼詳解

下面我們通過實際的例子來體會hibernate清除緩存的應(yīng)用。

hibernate映射數(shù)據(jù)庫和主鍵的生成策略有關(guān)。

案例一

 

uuid的方式生成主鍵的例子:

java" id="highlighter_463825">
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class user {
    private string uid;
    private string uname;
    private date birthday;
    public string getuid() {
        return uid;
    }
    public void setuid(string uid) {
        this.uid = uid;
    }
    public string getuname() {
        return uname;
    }
    public void setuname(string uname) {
        this.uname = uname;
    }
    public date getbirthday() {
        return birthday;
    }
    public void setbirthday(date birthday) {
        this.birthday = birthday;
    }
}

user.hbm.xml:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0"?>
<!doctype hibernate-mapping public
  "-//hibernate/hibernate mapping dtd 3.0//en"
  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- package表示實體類的包名 -->  
<hibernate-mapping package="com.lixue.bean">
 <!-- class結(jié)點(diǎn)的name表示實體的類名,table表示實體映射到數(shù)據(jù)庫中table的名稱 -->
 <class name="user" table="t_user">
  <id name="uid">
   <!-- 通過uuid的方式生成 -->
   <generator class="uuid"/>
  </id>
  <property name="uname"/>
  <property name="birthday"/>
 </class>
</hibernate-mapping>

測試方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/**
  * 測試uuid主鍵生成策略
  */
 public void testsave1(){
  /*定義的session和事物*/
  session session = null;
  transaction transaction = null;
   
  try {
   /*獲取session和事物*/
   session = hibernateutils.getsession();
   transaction = session.begintransaction();
    
   /*創(chuàng)建用戶*/
   user user = new user();
   user.setuname("習(xí)近平");
   user.setbirthday(new date());
    
   /**
    * 因為user的主鍵生成策略為uuid,所以調(diào)用完save之后,只是將user納入到session管理
    * 不會發(fā)出insert語句,但是id已經(jīng)生成,persistencecontext中的existsindatebase狀態(tài)為false
    */
   session.save(user);
    
   /**
    * 調(diào)用flush,hibernate會清理緩存(將session->insertions中臨時集合中的對象插入數(shù)據(jù)庫,在清空臨時集合)
    * 此時并不能在數(shù)據(jù)庫中看到數(shù)據(jù),但是如果數(shù)據(jù)庫的隔離級別設(shè)置為未提交讀,
    * 那么我們可以看到flush過的數(shù)據(jù),并且persistencecontext中existsindatabase狀態(tài)為true
    */
   session.flush();
    
   /**
    * 提交事物
    * 默認(rèn)情況下,commit操作會執(zhí)行flush清理緩存,
    * 所以不用顯示的調(diào)用flush
    * commit后數(shù)據(jù)是無法回滾的
    */
   transaction.commit();
  } catch (exception e) {
   e.printstacktrace();
   transaction.rollback();
  } finally{
   hibernateutils.closesession(session);
  }
 }

我們可以通過斷點(diǎn)調(diào)試程序:

1.由于user的主鍵生成側(cè)率為uuid,調(diào)用save()方法之后,只能將user對象納入session管理,不會發(fā)出insert語句,但是id已經(jīng)生成了(注:save之后又兩個地方很重要,首先是session->actionqueue->insertions->elementdata數(shù)組中有某個元素存儲了我們的對象,這是一個臨時集合對象,另外還有一個就是persistencecontext->entityentries->map->table->某個數(shù)組元素->value存儲了該對象,value下面還有一個屬性那就是existsindatabase代表數(shù)據(jù)庫中是否有對應(yīng)的數(shù)據(jù))。如圖:

Hibernate的Session_flush與隔離級別代碼詳解

Hibernate的Session_flush與隔離級別代碼詳解

2.調(diào)用完flush()方法之后,會清空session中的actionqueue的臨時存儲的值,然后將persistencecontext中的existsindatabase的值設(shè)為true,表示此時,數(shù)據(jù)庫中有對應(yīng)的數(shù)據(jù),但是此時打開數(shù)據(jù)庫打開表是看不到數(shù)據(jù)的,因為我們mysql數(shù)據(jù)庫默認(rèn)的隔離級別為提交讀,即,必須提交才能讀取數(shù)據(jù),調(diào)用commit()方法之后,數(shù)據(jù)庫中有數(shù)據(jù)。

案例二

 

native方式生成主鍵的例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class user1 {
    private integer uid;
    private string uname;
    private date birthday;
    public integer getuid() {
        return uid;
    }
    public void setuid(integer uid) {
        this.uid = uid;
    }
    public string getuname() {
        return uname;
    }
    public void setuname(string uname) {
        this.uname = uname;
    }
    public date getbirthday() {
        return birthday;
    }
    public void setbirthday(date birthday) {
        this.birthday = birthday;
    }
}

user1.hbm.xml:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0"?>
<!doctype hibernate-mapping public
  "-//hibernate/hibernate mapping dtd 3.0//en"
  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- package表示實體類的包名 -->  
<hibernate-mapping package="com.lixue.bean">
 <!-- class結(jié)點(diǎn)的name表示實體的類名(賦值映射文件的時候要記得修改類名,否則會出現(xiàn)bug),table表示實體映射到數(shù)據(jù)庫中table的名稱 -->
 <class name="user1" table="t_user1">
  <id name="uid">
   <!-- 自增長 -->
   <generator class="native"/>
  </id>
  <property name="uname"/>
  <property name="birthday"/>
 </class>
</hibernate-mapping>

測試方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
  * 測試native主鍵生成策略
  */
 public void testsave2(){
  /*定義的session和事物*/
  session session = null;
  transaction transaction = null;
   
  try {
   /*獲取session和事物*/
   session = hibernateutils.getsession();
   transaction = session.begintransaction();
    
   /*創(chuàng)建用戶*/
   user1 user = new user1();
   user.setuname("李克強(qiáng)");
   user.setbirthday(new date());
    
   /**
    * 因為user1的主鍵生成策略是native,所以調(diào)用session.save()后,將執(zhí)行insert語句,并且會清空臨時集合對象
    * 返回由數(shù)據(jù)庫生成的id,納入session的管理,修改了session中existsindatabase狀態(tài)為true,
    * 如果數(shù)據(jù)庫的隔離級別設(shè)置為未提交讀,那么我們可以看到save過的數(shù)據(jù)
    */
   session.save(user);
    
   transaction.commit();
  } catch (exception e) {
   e.printstacktrace();
   transaction.rollback();
  } finally{
   hibernateutils.closesession(session);
  }
 }

通過斷點(diǎn)調(diào)試程序:

1.由于主鍵的生成策略為native,所以調(diào)用save()方法之后,將執(zhí)行insert語句,并且會清空臨時集合對象中的數(shù)據(jù),返回由數(shù)據(jù)庫生成的id。

2.將對象納入session管理,修改了persistencecontext中的existsindatabase屬性為true(表示數(shù)據(jù)庫中有對應(yīng)的數(shù)據(jù),但是看不到,因為隔離界別的原因)

案例三

 

我們再來測試一下hibernate的另一個方法,那就是evict(),表示將對象從session逐出。

針對uuid主鍵生成策略的程序,在來一個測試方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/**
  * 測試uuid主鍵生成策略
  */
 public void testsave3(){
  /*定義的session和事物*/
  session session = null;
  transaction transaction = null;
   
  try {
   /*獲取session和事物*/
   session = hibernateutils.getsession();
   transaction = session.begintransaction();
    
   /*創(chuàng)建用戶*/
   user user = new user();
   user.setuname("胡錦濤");
   user.setbirthday(new date());
    
   /**
    * 因為user的主鍵生成策略為uuid,所以調(diào)用完save之后,只是將user納入到session管理
    * 不會發(fā)出insert語句,但是id已經(jīng)生成。session中的existsindatebase狀態(tài)為false
    */
   session.save(user);
    
   /*將user對象從session中逐出,即從persistencecontext的entityentries屬性中逐出*/
   session.evict(user);
    
   /**
    * 無法成功提交,因為hibernate在清理緩存時,在session的insertions臨時集合中取出user對象進(jìn)行insert
    * 操作后,需要更新entityentries屬性中的existsindatabase為true,而我們調(diào)用了evict方法
    * 將user從session的entityentries中逐出了,所以找不到existsindatabase屬性,無法更新,拋出異常
    */
   transaction.commit();
    
  } catch (exception e) {
   e.printstacktrace();
   transaction.rollback();
  } finally{
   hibernateutils.closesession(session);
  }
 }

通過斷點(diǎn)調(diào)試:

1.由于使用的是uuid的主鍵生成策略,所以調(diào)用save()方法之后,不會發(fā)送insert語句,只是將對象納入了session管理,id已經(jīng)生成,數(shù)據(jù)庫中沒有與之對應(yīng)的數(shù)據(jù)(即existsindatabase屬性值為false)。

2.調(diào)用evict()之后,將user對象從session中逐出,即從persistencecontext的entityentries屬性中逐出。

3.當(dāng)我再調(diào)用commit()方法時,我們會發(fā)現(xiàn),我們的數(shù)據(jù)保存不了,因為一開始我們的existsindatabase屬性為false,即數(shù)據(jù)庫中不存在對應(yīng)數(shù)據(jù),緊接著我們又調(diào)用了evict()將persistencecontext中的對象屬性(existsindatabase屬性也包括在內(nèi))全刪除了,但是actionqueue中的臨時存儲數(shù)據(jù)還沒被刪除。我們只調(diào)用commit()方法時會先隱式的調(diào)用flush()方法,這個方法的作用之前也講過,它會將actionqueue中的臨時對象進(jìn)行insert操作,然后將persistencecontext中的existsindatabase屬性值設(shè)為true,但很遺憾,persistencecontext中并沒有existsindatabase屬性,所以會出現(xiàn)錯誤,導(dǎo)致無法保存。

為此,我們改進(jìn)上述程序:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/**
  * 測試uuid主鍵生成策略
  */
 public void testsave4(){
  /*定義的session和事物*/
  session session = null;
  transaction transaction = null;
   
  try {
   /*獲取session和事物*/
   session = hibernateutils.getsession();
   transaction = session.begintransaction();
    
   /*創(chuàng)建用戶*/
   user user = new user();
   user.setuname("胡錦濤");
   user.setbirthday(new date());
    
   /**
    * 因為user的主鍵生成策略為uuid,所以調(diào)用完save之后,只是將user納入到session管理
    * 不會發(fā)出insert語句,但是id已經(jīng)生成。persistencecontext中的existsindatebase狀態(tài)為false
    */
   session.save(user);
   /**
    * flush后hibernate會清理緩存,會將user對象保存到數(shù)據(jù)庫中,將session中的insertions中的user對象
    * 清除,并且設(shè)置persistencecontext中existsindatabase的狀態(tài)為true
    */
   session.flush();
   /*將user對象從session中逐出,即從persistencecontext的entityentries屬性中逐出*/
   session.evict(user);
    
   /**
    * 可以成功提交,因為hibernate在清理緩存時,在session的insertions集合中無法
    * 找到user對象(調(diào)用flush時清空了),所以就不會發(fā)出insert語句,也不會更新session中的existsindatabase的狀態(tài)
    */
   transaction.commit();
    
  } catch (exception e) {
   e.printstacktrace();
   transaction.rollback();
  } finally{
   hibernateutils.closesession(session);
  }
 }

注:修改后的程序我們在save之后顯示的調(diào)用了flush()方法,再調(diào)用evict()方法。

通過斷點(diǎn)調(diào)試:

1.因為還是uuid的生成策略,所以在調(diào)用save之后,不會發(fā)出insert語句,只是將對象納入session管理,persistencecontext中的existsindatabase屬性為false。

2.調(diào)用完save()之后,我們又調(diào)用了flush()方法,這個方法的作用是清理緩存,即發(fā)出insert語句,將session中的insertions中的臨時對象插入到數(shù)據(jù)庫,然后清空該臨時集合,并且將persistencecontext中的existsindatabase屬性設(shè)置為true。

3.調(diào)用完flush()之后又調(diào)用evict()方法,它的作用是將user對象從session中清除,即清除persistencecontext的entityentries屬性。

4.調(diào)用完evict()方法之后又調(diào)用commit()方法,它的會隱式的先調(diào)用flush()方法,而flush的作用是清除緩存,即將session->insertions臨時集合中的對象insert到數(shù)據(jù)庫中,但是我們之前就調(diào)用了flush()方法(注:調(diào)用完這個方法之后會清空臨時集合),所以臨時集合根本就沒有對象,所以不會發(fā)出insert語句。也不會去更新persistencecontext中的existsindatabase狀態(tài)。可以成功提交。

案例四

 

我們再來考慮下native方式的主鍵生成策略中使用evict()方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/**
  * 測試native主鍵生成策略
  */
 public void testsave5(){
  /*定義的session和事物*/
  session session = null;
  transaction transaction = null;
   
  try {
   /*獲取session和事物*/
   session = hibernateutils.getsession();
   transaction = session.begintransaction();
    
   /*創(chuàng)建用戶*/
   user1 user = new user1();
   user.setuname("馬英九");
   user.setbirthday(new date());
    
   /**
    * 因為user1的主鍵生成策略是native,所以調(diào)用session.save()后,將執(zhí)行insert語句,
    * 返回由數(shù)據(jù)庫生成的id,納入session的管理,修改了session中existsindatabase狀態(tài)為true,并且清空了臨時集合
    * 如果數(shù)據(jù)庫的隔離級別設(shè)置為未提交讀,那么我們可以看到save過的數(shù)據(jù)
    */
   session.save(user);
    
   /*將user對象從session中逐出,即從persistencecontext的entityentries屬性中逐出*/
   session.evict(user);
    
   /**
    * 可以成功提交,因為hibernate在清理緩存的時候在session的insertions集合中
    * 無法找到user對象,所以就不會發(fā)出insert語句,也不會更新session中的existtsindatabase的狀態(tài)
    */
   transaction.commit();
    
  } catch (exception e) {
   e.printstacktrace();
   transaction.rollback();
  } finally{
   hibernateutils.closesession(session);
  }
 }

通過調(diào)試:

1.由于主鍵生成策略為native,所以調(diào)用完save方法之后,馬上就會發(fā)出insert語句,返回由數(shù)據(jù)庫生成的id,將對象納入session管理,修改persistencecontext中的existsindatabase屬性為true即數(shù)據(jù)庫中有與之對應(yīng)的數(shù)據(jù),并且會清空臨時集合中的對象。但是由于mysql隔離級別的原因我們在沒有提交之前是看不到數(shù)據(jù)的。

2.調(diào)用完save之后又調(diào)用evict()方法,將對象從session中逐出,即從persistencecontext中的entityentries中逐出。

3.調(diào)用完evict()方法之后又調(diào)用commit()方法,此時是可以成功保存提交的,因為調(diào)用commit()之前會隱式調(diào)用flush()方法,即清理緩存,去臨時集合中找對象insert到數(shù)據(jù)庫,但是會發(fā)現(xiàn)臨時集合中已經(jīng)沒有數(shù)據(jù)了,所以不會發(fā)出insert語句,也就不會去更新persistencecontext中的existsindatabase屬性。

通過上述幾個案例,我們可以看出,有時候我們需要顯示的調(diào)用flush()方法,去清理緩存。另外,從上面我們也發(fā)現(xiàn)了一個問題,那就是當(dāng)我們save()了數(shù)據(jù),沒提交之前是看不到數(shù)據(jù)的,即數(shù)據(jù)庫的隔離界別限制了,現(xiàn)在我們來說說mysql的隔離級別:

1.查看mysql數(shù)據(jù)庫當(dāng)前的隔離級別:

select @@tx_isolation;

Hibernate的Session_flush與隔離級別代碼詳解

注:從圖中,我們可以看出,mysql數(shù)據(jù)庫默認(rèn)的隔離級別為可重復(fù)讀,也就是說不會出現(xiàn)不可重復(fù)讀,即必須提交之后才能讀。

2.修改mysql當(dāng)前的隔離級別(假設(shè)修改為未提交讀,即沒有提交就可以讀):

set transaction isolation level read uncommited;

Hibernate的Session_flush與隔離級別代碼詳解

總結(jié)

以上就是本文關(guān)于hibernate的session_flush與隔離級別代碼詳解的全部內(nèi)容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!

原文鏈接:http://blog.csdn.net/lzm1340458776/article/details/32729127

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 国产一区二区影院 | 国产精品高清一区二区 | 一级大片av | 午夜免费影视 | 欧美高清一区 | 高清中文字幕 | 日韩在线观看中文字幕 | 日韩中文字幕在线视频 | 狠狠综合久久 | 日韩精品日韩激情日韩综合 | 91小视频 | 日本一区二区三区精品视频 | av在线成人| 久久久久久久久久久亚洲 | 黄色片免费观看 | 久久久一区二区 | 欧美精品影院 | 成人在线小视频 | 久久久精品播放 | 国产成人a亚洲精品 | 欧美黄色一区二区 | 91精品久久久久久9s密挑 | 国产成年人电影在线观看 | 最新日韩免费 | 国产大学生一区 | 免费观看国产精品 | 亚洲xx视频 | 国产精品久久久久久久久久久久久 | 久久综合中文字幕 | 深夜视频在线观看 | 欧美成人精品在线视频 | 国产高清视频一区二区 | 91久草视频 | 在线中文| 欧美精品一区视频 | 狠狠狠狠狠狠 | 免费黄色电影在线观看 | av片免费看 | 韩日av片 | 老女肥熟av免费观看 | 色婷婷国产精品综合在线观看 |