JPA實(shí)體關(guān)系映射補(bǔ)遺:有關(guān)mappedBy的思考

本文閱讀時(shí)間3分鐘。由作者三汪首發(fā)于簡(jiǎn)書(shū)饮六。


幾個(gè)月前寫(xiě)了一篇《JPA實(shí)體關(guān)系映射:@ManyToMany多對(duì)多關(guān)系、@OneToMany@ManyToOne一對(duì)多多對(duì)一關(guān)系和@OneToOne的深度實(shí)例解析》,簡(jiǎn)要闡述了我對(duì)JPA的幾個(gè)實(shí)體關(guān)系映射的理解。
其中有關(guān)mappedBy的部分是這樣寫(xiě)的:

mappedBy聲明于關(guān)系的被維護(hù)方歇终,聲明的值為關(guān)系的維護(hù)方的關(guān)系對(duì)象屬性名。
在實(shí)例中逼龟,mappedBy被聲明于Course類(lèi)中评凝,其值為Student類(lèi)中的Set對(duì)象"courses"。即腺律,Student為關(guān)系維護(hù)方奕短,Course為被維護(hù)方。

這個(gè)表述其實(shí)是沒(méi)錯(cuò)的匀钧。但是我后面又補(bǔ)充了一句:

但是在實(shí)際操作中翎碑,我發(fā)現(xiàn)其實(shí)被維護(hù)方于維護(hù)方的概念并不那么重要。被維護(hù)方也可以對(duì)雙方關(guān)系進(jìn)行維護(hù)之斯。下面通過(guò)一組測(cè)試用例來(lái)進(jìn)行說(shuō)明日杈。

然而今天測(cè)試小哥給我提了個(gè)bug,讓我發(fā)現(xiàn)到其實(shí)mappedBy其實(shí)并非不重要的。


和測(cè)試小哥的對(duì)話

事實(shí)上這是一個(gè)很簡(jiǎn)單的bug莉擒。
通過(guò)查看日志酿炸,發(fā)現(xiàn)hibernate打印出來(lái)的sql中,不僅有update語(yǔ)句涨冀,還出現(xiàn)了delete語(yǔ)句梁沧。
這是因?yàn)榍岸藗鬟^(guò)來(lái)的數(shù)據(jù)里是不帶關(guān)聯(lián)對(duì)象的。
所以只要從數(shù)據(jù)庫(kù)里把關(guān)聯(lián)找出來(lái)然后賦給編輯的對(duì)象就解決了蝇裤。

像這樣:
修改前

    @Override
    @Transactional
    public void saveLabelDict(LabelDictDomain labelDictDomain) {
        if (labelDictDomain.getLabelType().equals(TYPE_UNIFORM)) {          
            if (StringUtil.isEmpty(labelDictDomain.getLabelGroup())) {
                throw new BizException("統(tǒng)一標(biāo)簽標(biāo)簽分組不能為空廷支!");
            }           
        }else if(!labelDictDomain.getLabelType().equals(TYPE_PERSONAL)){
            throw new BizException("標(biāo)簽類(lèi)型非法!");
        }
        repository.save(labelDictDomain);
    }

修改后

    @Override
    @Transactional
    public void saveLabelDict(LabelDictDomain labelDictDomain) {
        if (labelDictDomain.getLabelType().equals(TYPE_UNIFORM)) {          
            if (StringUtil.isEmpty(labelDictDomain.getLabelGroup())) {
                throw new BizException("統(tǒng)一標(biāo)簽標(biāo)簽分組不能為空栓辜!");
            }           
        }else if(!labelDictDomain.getLabelType().equals(TYPE_PERSONAL)){
            throw new BizException("標(biāo)簽類(lèi)型非法恋拍!");
        }
        if (StringUtil.isNotEmpty(labelDictDomain.getId())) {
            LabelDictDomain domain = repository.findOne(labelDictDomain.getId());
            labelDictDomain.getMemberDomains().addAll(domain.getMemberDomains());
        }
        repository.save(labelDictDomain);
    }

這個(gè)修改引發(fā)了我對(duì)于關(guān)系映射的思考。
因?yàn)樵谂c之相關(guān)的另外一個(gè)實(shí)體編輯時(shí)藕甩,并不需要這樣子手動(dòng)去配置關(guān)聯(lián)關(guān)系施敢。
相關(guān)代碼如下

      @Override
    @Transactional
    public MemberDomain addMember(MemberDomain memberDomain) {
        
        //無(wú)關(guān)代碼略

        memberDomain.getBonusPointDomains().clear();
        memberDomain.getFavoriteInfoDomains().clear();
        memberDomain.getLabelDictDomains().clear();
        memberDomain.setPointTotal(null);

        memberDomain = repository.save(memberDomain);   
        return memberDomain;

    }

在這里我不僅沒(méi)有手動(dòng)配置關(guān)聯(lián)關(guān)系,還為了維護(hù)數(shù)據(jù)安全狭莱,把其他實(shí)體關(guān)聯(lián)給清空了僵娃。
但是這里卻不會(huì)產(chǎn)生delete語(yǔ)句影響數(shù)據(jù)庫(kù)里的內(nèi)容。
這是為什么呢腋妙。

在看了一眼實(shí)體中的關(guān)聯(lián)配置以后默怨,我突然恍然大悟。
其實(shí)都是因?yàn)檫@個(gè)小小的沒(méi)有被注意到的mappedBy啊骤素。
因?yàn)?code>LabelDictDomain中的memberDomains對(duì)象在MemberDomain中被配置為了關(guān)系的維護(hù)方匙睹。
所以labelDictDomains可以為空,而memberDomains一定不能為空。
否則就會(huì)出現(xiàn)關(guān)聯(lián)關(guān)系被清空的情況济竹。
也就是說(shuō)痕檬,被維護(hù)方不會(huì)主動(dòng)去維護(hù)關(guān)聯(lián)關(guān)系。
真正的關(guān)系維護(hù)送浊,掌握在維護(hù)方的手中梦谜。

關(guān)聯(lián)配置代碼如下
被維護(hù)方:

        @ManyToMany(mappedBy = "memberDomains", cascade={CascadeType.MERGE,CascadeType.DETACH} , fetch =  FetchType.EAGER)
        private Set<LabelDictDomain> labelDictDomains = new HashSet<>();

維護(hù)方:


         @ManyToMany(cascade={CascadeType.DETACH} , fetch =  FetchType.LAZY)
         @JoinTable(name="member_label",joinColumns = { @JoinColumn(name="LABEL_ID")},inverseJoinColumns = @JoinColumn(name="MEMBER_ID"))
         private Set<MemberDomain> memberDomains = new HashSet<>();

以上。
希望我的文章對(duì)你能有所幫助袭景。
我不能保證文中所有說(shuō)法的百分百正確唁桩,但我能保證它們都是我的理解和感悟以及拒絕復(fù)制黏貼。
有什么意見(jiàn)浴讯、見(jiàn)解或疑惑朵夏,歡迎留言討論。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末榆纽,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌奈籽,老刑警劉巖饥侵,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異衣屏,居然都是意外死亡躏升,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)狼忱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)膨疏,“玉大人,你說(shuō)我怎么就攤上這事钻弄〉枞矗” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵窘俺,是天一觀的道長(zhǎng)饲帅。 經(jīng)常有香客問(wèn)我,道長(zhǎng)瘤泪,這世上最難降的妖魔是什么灶泵? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮对途,結(jié)果婚禮上赦邻,老公的妹妹穿的比我還像新娘。我一直安慰自己实檀,他們只是感情好深纲,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著劲妙,像睡著了一般湃鹊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上镣奋,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天币呵,我揣著相機(jī)與錄音,去河邊找鬼侨颈。 笑死余赢,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的哈垢。 我是一名探鬼主播妻柒,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼耘分!你這毒婦竟也來(lái)了举塔?” 一聲冷哼從身側(cè)響起绑警,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎央渣,沒(méi)想到半個(gè)月后计盒,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡芽丹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年北启,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拔第。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡咕村,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蚊俺,到底是詐尸還是另有隱情懈涛,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布春叫,位于F島的核電站肩钠,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏暂殖。R本人自食惡果不足惜价匠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望呛每。 院中可真熱鬧踩窖,春花似錦、人聲如沸晨横。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)手形。三九已至啥供,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間库糠,已是汗流浹背伙狐。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瞬欧,地道東北人贷屎。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像艘虎,于是被迫代替她去往敵國(guó)和親唉侄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容