自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Hibernate實(shí)踐—持久態(tài)對象的變化與入庫機(jī)制

數(shù)據(jù)庫 其他數(shù)據(jù)庫
在持久態(tài)下,任何對 userInfo? 和 userPassword? 對象的屬性的修改都將被監(jiān)測到,并在適當(dāng)?shù)臅r(shí)候同步到數(shù)據(jù)庫中。在測試方法的最后,我們對 userPassword? 的 password? 屬性和 userInfo? 的 user_name? 屬性進(jìn)行了修改。

持久化后修改屬性,會(huì)發(fā)生什么

@Test
    public void demo3(){
        UserInfo userInfo = new UserInfo();
        userInfo.user_name = "demo123";
        userInfo.user_sex = 1;
        userInfo.user_age = 18;
        UserPassword userPassword = new UserPassword();
        userPassword.password = "demo-password";
        userInfo.userPassword = userPassword;
        userPassword.UserPassword_userInfo = userInfo;
        BaseEntityUtils.save(userInfo);
        System.out.println(userInfo.user_name);
        userInfo.user_name = "demo1234";
        userPassword.password = "demo1234-password";
        UserInfo new1 = BaseEntityUtils.findById(userInfo.id,UserInfo.class);
        System.out.println(new1.user_name);
    }

在提供的代碼中,在執(zhí)行 BaseEntityUtils.saveAndFlush(userInfo) 之后,userInfo 和 userPassword 對象處于持久態(tài)(Persistent State)。

userInfo 對象的狀態(tài)

  • 由于使用了 BaseEntityUtils.saveAndFlush(userInfo) 方法,userInfo 對象被保存到數(shù)據(jù)庫,并且通過 flush 操作將其狀態(tài)同步到數(shù)據(jù)庫中。
  • 因此,userInfo 對象現(xiàn)在處于持久態(tài),它受到 Hibernate Session 的管理。

userPassword 對象的狀態(tài)

  • userPassword 對象與 userInfo 之間存在一對一的關(guān)聯(lián)關(guān)系,由于級聯(lián)關(guān)系的存在,userPassword 對象也被保存到數(shù)據(jù)庫中。
  • userPassword 對象的狀態(tài)也是持久態(tài),它同樣受到 Hibernate Session 的管理。

在持久態(tài)下,任何對 userInfo 和 userPassword 對象的屬性的修改都將被監(jiān)測到,并在適當(dāng)?shù)臅r(shí)候同步到數(shù)據(jù)庫中。在測試方法的最后,我們對 userPassword 的 password 屬性和 userInfo 的 user_name 屬性進(jìn)行了修改。這些修改將在 Hibernate Session 中被跟蹤,但由于在測試方法中并沒有進(jìn)行事務(wù)的提交或刷新,這些變化可能尚未同步到數(shù)據(jù)庫。如果我們想要確保變化及時(shí)更新到數(shù)據(jù)庫中,我們可以在測試方法的最后添加 BaseEntityUtils.flush() 或者使用 Spring 的 @Transactional 注解,以確保事務(wù)的正確提交和刷新。這樣,持久態(tài)下的對象變化將會(huì)及時(shí)同步到數(shù)據(jù)庫。

什么時(shí)候會(huì)刷新到數(shù)據(jù)庫

在 Hibernate 中,對于持久態(tài)的實(shí)體對象,屬性的修改會(huì)被監(jiān)測到,并且會(huì)在以下情況下被同步到數(shù)據(jù)庫

事務(wù)提交時(shí)

當(dāng)事務(wù)被提交時(shí),Hibernate 會(huì)檢查事務(wù)中所有持久態(tài)對象的變化,并將這些變化同步到數(shù)據(jù)庫。這是最常見的觸發(fā)時(shí)機(jī)。

顯式調(diào)用 flush() 方法時(shí)

我們可以顯式調(diào)用 Hibernate Session 的 flush() 方法,強(qiáng)制將所有掛起的 SQL 語句發(fā)送到數(shù)據(jù)庫。這樣可以在事務(wù)未提交的情況下將變化同步到數(shù)據(jù)庫。

在查詢時(shí)自動(dòng)執(zhí)行 flush

Hibernate 在執(zhí)行一些查詢操作(例如執(zhí)行查詢語句之前)時(shí),會(huì)自動(dòng)執(zhí)行 flush 操作,以確保最新的數(shù)據(jù)被加載。這種情況通常涉及到緩存和查詢的一致性。所以,當(dāng)我們在持久態(tài)的對象上進(jìn)行屬性的修改后,如果我們正在一個(gè)事務(wù)中,通常會(huì)在事務(wù)提交時(shí)或在顯式調(diào)用 flush() 方法時(shí)將變化同步到數(shù)據(jù)庫。在我們提供的測試方法中,如果沒有顯式調(diào)用 BaseEntityUtils.flush(),并且也沒有使用 Spring 的事務(wù)管理(例如,使用 @Transactional 注解),那么在測試方法執(zhí)行完畢時(shí),可能并沒有執(zhí)行事務(wù)提交和 flush 操作,因此對 userInfo 和 userPassword 的屬性修改可能尚未同步到數(shù)據(jù)庫。在實(shí)際應(yīng)用中,確保在需要同步變化時(shí)執(zhí)行事務(wù)提交或顯式調(diào)用 flush 方法。

持久態(tài)的前提是什么

需要在同一個(gè)EntityManager中才能被自動(dòng)更新到數(shù)據(jù)庫中。

持久態(tài)的前提是實(shí)體對象必須處于同一個(gè)持久化上下文(Persistence Context)中,而持久化上下文通常對應(yīng)于一個(gè) EntityManager。持久態(tài)實(shí)體對象是通過 EntityManager 進(jìn)行管理和跟蹤的。具體來說,以下是實(shí)體對象變?yōu)槌志脩B(tài)的前提條件

通過 EntityManager 進(jìn)行持久化操作

持久態(tài)的實(shí)體對象通常是通過 EntityManager 的 persist、merge、find 等方法從數(shù)據(jù)庫中加載或保存得到的。在這些操作中,實(shí)體對象會(huì)被添加到 EntityManager 的持久化上下文中,從而成為持久態(tài)。

EntityManager entityManager = // 獲取 EntityManager 的方式
UserInfo userInfo = new UserInfo();
entityManager.persist(userInfo); // 將實(shí)體對象變?yōu)槌志脩B(tài)

通過查詢操作獲取的實(shí)體對象

當(dāng)通過查詢操作從數(shù)據(jù)庫中獲取實(shí)體對象時(shí),這些對象也會(huì)成為持久態(tài)。例如,通過 find 方法獲取對象

EntityManager entityManager = // 獲取 EntityManager 的方式
UserInfo userInfo = entityManager.find(UserInfo.class, 1L); // 獲取持久態(tài)對象

在這種情況下,userInfo 對象會(huì)被添加到 EntityManager 的持久化上下文中。

級聯(lián)關(guān)系的影響

如果實(shí)體對象之間存在級聯(lián)關(guān)系,并且級聯(lián)操作的范圍包括持久化操作,那么在級聯(lián)操作中涉及到的對象也會(huì)變?yōu)槌志脩B(tài)。

UserInfo userInfo = new UserInfo();
UserPassword userPassword = new UserPassword();
userInfo.setUserPassword(userPassword); // 設(shè)置級聯(lián)關(guān)系

在這個(gè)例子中,如果級聯(lián)關(guān)系包括 CascadeType.PERSIST,那么當(dāng) userInfo 被保存時(shí),userPassword 也會(huì)成為持久態(tài)??傮w而言,持久態(tài)的前提是實(shí)體對象必須由 EntityManager 進(jìn)行管理,且這些實(shí)體對象需要處于同一個(gè)持久化上下文中。這確保了對實(shí)體對象的任何修改都能被 EntityManager 跟蹤并在適當(dāng)?shù)臅r(shí)候同步到數(shù)據(jù)庫。

問題分析

@Test
    public void demo3(){
        UserInfo userInfo = new UserInfo();
        userInfo.user_name = "demo123";
        userInfo.user_sex = 1;
        userInfo.user_age = 18;
        UserPassword userPassword = new UserPassword();
        userPassword.password = "demo-password";
        userInfo.userPassword = userPassword;
        userPassword.UserPassword_userInfo = userInfo;
        BaseEntityUtils.save(userInfo);
        System.out.println(userInfo.user_name);
        userInfo.user_name = "demo1234";
        userPassword.password = "demo1234-password";
        UserInfo new1 = BaseEntityUtils.findById(userInfo.id,UserInfo.class);
        System.out.println(new1.user_name);
    }

Alt textAlt text

在上面的代碼中,由于使用的是靜態(tài)方法去save,所以查詢方法和Save方法并不是使用的一個(gè)entityManager,所以此時(shí)這兩個(gè)對象的修改沒有被同步到數(shù)據(jù)庫中,兩次打印都是demo123。

在我們提供的代碼中,確實(shí)存在使用不同的 EntityManager 的情況,導(dǎo)致了持久態(tài)對象的狀態(tài)在不同的 EntityManager 中不同步。具體來說,在 BaseEntityUtils.save(userInfo) 方法中使用了一個(gè) EntityManager 對 userInfo 進(jìn)行了保存,而在查詢方法 BaseEntityUtils.findById(userInfo.id, UserInfo.class) 中使用了另一個(gè) EntityManager 進(jìn)行查詢。由于每個(gè) EntityManager 管理著自己的持久化上下文,所以在不同的 EntityManager 中,對相同的實(shí)體對象進(jìn)行的修改不會(huì)同步到數(shù)據(jù)庫。這就解釋了為什么在查詢方法中打印的 new1.user_name 仍然是 "demo123"。要解決這個(gè)問題,確保在同一個(gè) EntityManager 中進(jìn)行保存和查詢操作,以保持持久態(tài)對象在相同的上下文中。

改進(jìn)方案

@Test
    public void demo4(){
        UserInfo userInfo = new UserInfo();
        userInfo.user_name = "demo123";
        userInfo.user_sex = 1;
        userInfo.user_age = 18;
        UserPassword userPassword = new UserPassword();
        userPassword.password = "demo-password";
        userInfo.userPassword = userPassword;
        userPassword.UserPassword_userInfo = userInfo;
        UserInfoDomain userInfoDomain = new UserInfoDomain();
        userInfoDomain.setDomainEntity(userInfo);
        userInfoDomain.save();
        System.out.println(userInfo.user_name);
        userInfo.user_name = "demo1234";
        userPassword.password = "demo1234-password";
        userInfoDomain.flush();
        UserInfo new1 = userInfoDomain.findById(userInfo.id);
        System.out.println(new1.user_name);
    }

運(yùn)行結(jié)果為:

Alt textAlt text

在UserInfoDomain中,所有的操作都在一個(gè)EntityManager里面,所以這兩次打印分別是demo123和demo1234。

在我們提供的代碼中,UserInfoDomain 類的設(shè)計(jì)確保了所有的操作都在同一個(gè) EntityManager 中,這是非常好的實(shí)踐。由于 UserInfoDomain 中的 save() 方法內(nèi)部使用的是同一個(gè) EntityManager 進(jìn)行保存操作,保證了持久態(tài)對象在相同的上下文中。以下是對我們的代碼的解釋

保存操作
UserInfoDomain userInfoDomain = new UserInfoDomain();
userInfoDomain.setDomainEntity(userInfo);
userInfoDomain.save();

在這里,userInfoDomain.save() 方法內(nèi)部使用了相同的 EntityManager 進(jìn)行保存操作。因此,userInfo 對象及其關(guān)聯(lián)的 userPassword 對象都處于持久態(tài),保存到數(shù)據(jù)庫。

第一次打印
System.out.println(userInfo.user_name);

這里打印的是 userInfo 對象的 user_name 屬性,即 "demo123"。由于保存操作是在同一個(gè) EntityManager 中執(zhí)行的,所以在持久態(tài)下的 userInfo 對象的屬性是最新的。

修改操作
userInfo.user_name = "demo1234";
userPassword.password = "demo1234-password";

這里對 userInfo 對象進(jìn)行了屬性的修改。

查詢操作
UserInfo new1 = userInfoDomain.findById(userInfo.id);

在這里,findById 方法內(nèi)部也是使用了相同的 EntityManager 進(jìn)行查詢操作。因此,獲取的 new1 對象是 userInfo 對象在數(shù)據(jù)庫中的最新狀態(tài)。

第二次打印
System.out.println(new##### user_name);

這里打印的是經(jīng)過查詢操作后的 new1 對象的 user_name 屬性,即 "demo1234"。由于查詢操作也是在相同的 EntityManager 中執(zhí)行的,所以能夠獲取到最新的數(shù)據(jù)庫狀態(tài)??傮w來說,通過確保在同一個(gè) EntityManager 中進(jìn)行保存和查詢操作,我們有效地維持了一致的持久化上下文,確保對象的狀態(tài)能夠正確同步到數(shù)據(jù)庫。這是良好的實(shí)踐,可以有效避免對象狀態(tài)不同步的問題。

責(zé)任編輯:武曉燕 來源: 海燕技術(shù)棧
相關(guān)推薦

2009-09-24 15:42:44

Hibernate對象

2009-09-29 16:11:45

Hibernate實(shí)現(xiàn)

2009-09-23 17:00:07

Hibernate持久

2009-07-02 09:38:17

Hibernate延時(shí)

2009-09-25 14:41:15

Hibernate對象

2024-09-12 08:49:53

2009-09-23 16:30:01

Hibernate f

2012-06-02 00:55:44

HibernateflushJava

2009-09-21 17:46:34

Hibernate持久

2009-09-29 10:57:25

設(shè)置Hibernate

2009-09-29 10:37:29

Hibernate持久

2024-09-06 17:49:46

2014-08-07 09:48:40

2023-10-26 11:39:54

Linux系統(tǒng)CPU

2009-06-17 15:43:03

Hibernate緩存

2009-06-18 14:51:12

Hibernate緩存Hibernate

2009-06-29 08:50:20

Hibernate主鍵

2017-08-16 16:20:01

Linux內(nèi)核態(tài)搶占用戶態(tài)搶占

2009-09-24 16:39:20

Hibernate傳播

2009-06-16 14:11:36

Hibernate優(yōu)點(diǎn)Hibernate構(gòu)架
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號