潮流特區

焦點文章

最新文章

徐大俠,一路好走
宗教玄學
熊神進・2024-09-15

#徐少强死訊 徐少强先生是筆者的一位朋友,他曾經跟筆者笑談風月時,筆者對他說了一句ldquo;你是金虎,最忌青龍rdquo;,他說ldquo;睇下點那就走著瞧吧。rdquo; 徐大俠是80年代的中國香港有個性的影壇武俠片演員,當年他在「麗的電視」武俠劇《天蠶變》一劇飾演「雲飛揚」而聲名大噪,近年出演《維多利亞壹號 》後就開始轉戰拍攝網絡電影。筆者不是他的影迷,說實話,他的作品我還沒有看過,只知道他今年年頭還留在北京拍電影,對于一位74歲的資深老演員,筆者是尊重他,祝福他。 上星期筆者收到嚴小姐通知徐大俠已經辭世,當晚筆者爲他做了烟供,祝他一路好走。 徐大俠的八字庚寅年,丙戌月,甲申日,壬x時,命宮是丁亥,胎元是丁醜。日主「甲申」跟年支「庚寅」是天克地沖,日元無根,玄學上叫歲破日出生,按古書解釋,徐大俠的八字根基不鞏固,最忌走忌神大運。何謂忌神大運,就是大運中的五行干支跟八字四柱相沖的大運。 2023年後他走「戊寅」10年大運,戊屬土,寅屬木,木克土,而他是「甲申」日出生,從大運的結構來說,寅中藏甲丙戊,甲的主氣透天干,主氣有力,木想制約土,可是日主自坐申金,絕氣之地,甲木根本起不了克土作用,反而是土生金,金旺起來。今年立春之後,他遇上人生第4個死亡期「甲辰」。 這是一個龍來欺虎的格局,辰屬龍,藏戊乙癸,癸是水,濕土可以生金,人體裏屬金的器官有肺、大腸、鼻,屬土的有胃,甲辰一出現,辰屬青龍,他生肖屬金虎,虎屬木,龍屬土,木弱屬金,屬土,歲君無情沖月柱 ,月支是月堤,堤不可以缺,辰中藏戊乙癸,戌中藏戊辛丁,乙木被辛金克走了,木一點根都沒有了, 四柱寅申沖,戊寅大運也來沖, 而大俠離開我們是在戊辰日,又是土金日,又是辰沖月堤,一百個巧合都來了,這劫是壽終。在算命學來說,因食道是消化系統,消化系統五行屬土,土生金,金來克木,木沒力克土,木是他的元神,元氣大傷。 如果以八字來分析,徐大俠第3個死亡期是2003年的庚辰土金大運庚辰大運時筆者認識他,當年筆者說他的女兒八字中食傷星旺救輔了父親,這也是化了一個大劫。徐大俠的食道一直都是不好,當年我和他聊天,他的噯氣比正常人的次數多,他告訴我,他的腹部常常膨脹、便秘,而土金是他的忌神,我把提醒他每5年檢查身體一次。 筆者很感恩徐大俠爲觀衆的演藝生涯,願他在天堂走好,也祝福他的家人。阿彌陀佛。

感謝賢者模型工作室 - 修復那些年還沒建好就斷樁的模型
手機‧電玩
MacauYeah・2024-09-13

不知道80、90後的朋友們,今年年初有沒有留意Gundam電影 一向熱愛Gundam的朋友們,一定知道這套大熱作品Gundam Seed Freedom的出現。那是原本的Seed Destiny的後逐全身劇情,正因如此,玩具商也馬不停蹄地推出新模型。在電影加持的情況下,其實很多老模型,都推出重賣再販。筆者也不例外,在看過電影後的,不斷翻老模的格價。 不過,最佔上心頭的,並不是購買欲,而是筆者過去,有一台模型組裝到一半就斷臂的MG脈衝高達Impluse Gundam。 上網找模型群友求助,不外乎都是找補件或當殺肉即係給他人當補件或改件用。但這次勾起回憶,不如就來個修復吧,死馬當活馬醫,實在救不了,就當殺肉吧。 筆者的情況,是因為模型手臂連結點斷裂,用膠水是無法修復的。經一位網友的指點,這必需靠打樁修復。 打樁,基本上有三要素:手鑽連鑽頭、銅棒、萬能膠。萬能膠很易可以解決,在本澳各大超市及文具店均有售。手鑽連鑽頭、銅棒,就麻煩一點,五金店的都很大,不適合模型玩具用。當然,有何事,去萬能的淘寶就有售。 在淘寶購物車當下,筆者還是很猶豫。萬一買錯了怎辦?淘寶單價不貴,但運費可很要命。是不是找個懂修復的大師,幫忙看看情況,再由大師下單比較適合。 就是這樣,筆者就不斷在網路上找,到底澳門有沒有模型工作室。一找,還真有一家【賢者模型工作室】,主打噴塗裝備的工作室。當時筆者還厚顏地私信問店家,如果不噴塗只素組的話,有免費位置嗎?店家還很慷慨的回答,是的,素組不收費。收費部份,就是耗材購買、噴塗裝備租用。坐位上,只是租客優先。 所以筆者就在本年的八月份,去【賢者模型工作室】朝聖一下,順便帶著斷臂的脈衝,看看有沒有路過的大師幫忙指點一下。【賢者】就如當初對話中了解的一樣,主打噴塗。筆者雖然對噴塗了解不多,但見在場裝備,一定是專業級。賢者不單是提供上色工具,還解決了很多抽風問題,在家想要一個這樣安全的制作環境,一定價值不菲。因為家庭環境問題,放棄噴塗的朋友們,真的可以去【賢者】現場看一看,應該會有所得著。 說回筆者原本的脈衝高達,剛好當晚店長【賢者】在場,拿起筆者的模型細看了一翻,然後就講了一句:quot;簡單,我幫你修吧quot;。筆者原本還以為只是來取經,然後再逐一買工具,想不到熱心的店長,突然出手幫忙,實在喜出望外。 手鑽開孔 上銅樁,最後插入主體中 回家再組裝外肩甲,浴火重生 在整個修復過程中,慷慨的店長用的都是他自己的工具,只是他手中沒有已開封的銅樁,筆者就現場買一份吧,其餘一分錢都沒有收取筆者的。店長不但為筆者修復了模型,還省下了工具錢,還傳授了補樁的要點,筆者實在收穫巨大。想不到,澳門玩具業中,還有這麼良心的店存在,實在值得支持。 若然讀者們跟筆者一樣,因為任何原因,有一些未完成的作品模型、GK,不妨一齊帶上去【賢者】,看看模友們能不能為你帶來新的方向。店長不一定在店,有需要可以加入他們的交流群,打聽一下店長的駐店時間。交流群也不會有店家的推銷產品,不過群友們會推坑團購,大家要管好自己的心。 【賢者模型工作室】 官方專頁 httpswww.facebook.cominsmws

「蕉」與「招」的粵音相同,人人都想「招財」
宗教玄學
熊神進・2024-09-11

# 爲什麽不可以用蕉去拜神 圖中有二個亮眼的地方,一個是「香蕉」的擺放法,另一個是男性信士比較多,今天我和大家談談拜拜的時候「香蕉」的擺放法。 南方人喜歡拜神供佛的時候, 把「蕉」放在供桌上,因爲廣府話「蕉」與「招」相同,人人都想「招財」。北方商人的習俗比較喜歡在一梳蕉上放一隻橙,取其諧音是「成(橙)交(蕉)」。 近年南北二地的文化融合,筆者主持樓盤動土剪彩儀式,我都會在供桌上擺放香蕉,而香蕉上面放很多橙,就是「成交」。在中國臺灣,香蕉又稱爲「弓蕉kingtsio」(閩南語),它是有招來財富之意,是拜神祭品必備。 臺灣旗山地區被譽爲「香蕉之家」,每年中元普渡時,香蕉被視爲祭拜的重要水果,幷被稱爲「香蕉王爺」和「香蕉帝爺」。 在玄學上有二種說法,有師傅說農曆七月是鬼月,民間老百姓有中元節不能拜香蕉的傳言,因爲「蕉」諧音近似「招」,擔心會招來好兄弟。另一種說法是在中元普渡期間,民衆準備豐盛的香蕉祭品和水果,祭拜祖先和神明,是求平安和幸福。中元是孝親月、慈悲月, 農曆七月期間各寺廟都會準備豐盛祭品及水果祭拜超度好兄弟以求平安。 地方文化不同,南方地區的民衆不想犯忌諱,他們很少人在七月用「蕉」去拜拜,即使用了蕉,也是用來插香,幷不是供奉。 五行屬土的水果有芒果、菠蘿、香蕉、山竹、無花果、山桂、栗子、石榴等。香蕉五行屬土,從五行來看,土生金,所以香蕉在台語念起來是「金蕉」,在南方念「香蕉」。「蕉」能不能够招財這就不得而知,民衆普渡時用香蕉只是一種拜拜,這是對衆神或「好兄弟」的一種誠意。 大家在圖中看到拜臺上有二種香蕉的擺放法,二種都沒有對錯,要視乎情况而定: 香蕉頭分支向上,呈一條船的形狀。這種擺放法適合一些水上工作人員,因爲它像一條船,整把香蕉就像大船入港,表示平安,吉祥。 香蕉頭分支向下,呈一個倒扣的碗的形狀。把香蕉翻過來就像「捧財」一樣,這是做陸上,空中生意的民衆常用方法。 拜拜用不用香蕉,佛教和道教的經典中幷無相關記載,我們只耍誠心去拜,就可以。

排版之於文字創作者的重要性
手機‧電玩
MacauYeah・2024-09-05

筆者已經很少再買遊戲相關的書藉,一來因為筆者已漸漸遠離遊戲新作,二來發現某些紙媒的資訊瑕疵越來越多,所以就沒有再看。但因為家裏土地資源問題,筆者需要再斷捨離一些收藏,所以就再拿起舊的遊戲雜誌來重新審閱。 說實在,在過去、現在,很多傳媒的資訊都無法確認正確性,其資訊價值難似證明,但某些紙媒一直存在至今,一定是有些地方,很受市場歡迎。那些地方,大家也不妨去借鑑一下,或者對自己的作品會有幫助。 之前某一期,筆者也表明過,UCG的攻略有著抄襲問題,所以筆者已不再購買他們的新攻略。但重翻他們家的百期特輯,內容的確不錯。 主題的選擇 作為百期特輯,他們會選擇一些回顧的主題。而這些回顧也的確實表現出時間的演變。 排版 現時網絡資訊,品質好的,會配以圖文表示。但因為結構單一,所以新鮮感不足。最差的什至會滿頁廣告,閱讀感很差。但以百期特輯的雜誌式的排序,每頁配圖位置稍有不一,亦有主題轉變,風格相似又不盡相同,真的耐看。 匯整 雖然資訊不能保證百分百正確。但以匯整的角度來說,有一讀的價值。好比ChatGPT,它的資訊也不是完全正確,但它可以省略你在搜尋引擎中四處查看、逐一對比的過程。 對於各位文字創作者,有條件,當然可以嘗試以圖文方式豐富視覺內容。那怕沒有時間挑圖,也可以試試定制不同章節的排版風格,來讓故事文章變得比較有過程的變化或是段落感。 不過,說到尾,筆者並不是對抄襲問題作出認同,我們應對原創有更多的支持,抄襲只會讓原創更難生存。但某些二次整理,也有它的價值。就像筆者的知識分享一樣,重複以不同的方式,更易理解的角度,去重述一些議題,倒是不會嫌多。

推坑SFC的神作
手機‧電玩
MacauYeah・2024-09-03

因為年紀漸大,筆者玩遊戲的機會越來越少。一方面是因為家庭,一方面則是因為身體大不如前,腦袋開始跟不上3D遊戲的場境,常常不是玩一玩就累了,就是玩一玩就暈了,那怕連手遊都一樣。 所以筆者現在什少會再開新坑試新世代遊戲,反而專注在舊世代中,體驗一下過去的名著。值得一提的是,過去的遊戲體量通常比較少但完整,對於繁忙的生活節奏,是適合的。相比手遊,舊世代的遊戲更無抽蛋要素,更沒有那種玩個空虛的感覺。所以若然大家主機有買會員,趁會籍到期之前,快試一試那些年被你跳過的遊戲,應該有所收獲。 今日筆者就選了NS online會員的SFC舊遊戲,《薩爾達 眾神的三角力量》。只要大家有NSO,應該都可以順利重玩這個遊戲。 向大家推坑這遊戲的原因主要有幾個。 薩爾達 Switch 兩作稱霸天下。過去的作品,很值得一試。 眾神的三角力量是平面遊戲,不會暈,而且 Switch 隨時待機,玩玩停停沒有壓力。 玩後的優點 那個古早的年代,已經發展出到處鼓勵四處探索的玩法。那怕只是2D平面,都感覺到世界的大。 攻略好找好看。薩爾達在 Switch 中的最後兩,好玩歸好玩,但攻略真的難攪,難以用文字來表達。即使各大出版社如何編制圖文包,還不如直接看影片攻略來得直接。眾神的三角力量,那怕筆者不看圖,筆者也知道攻略制作人想表達的意思和方向。不知道下一步去哪?不用怕,看一看網上攻略就攪掂。 偏向動作遊戲,穿插少量劇情。筆者過去都是接觸以劇情量為主的JRPG,以現在的生活形態,要好好地讀完一個新的JRPG故事真的很難。 沒有壓力。這真的很重要。Switch 兩代,都有一個很麻煩的資源系統。武器、道具、盾,都是會快速消耗的。除非大家對操作很有信心,不然每次戰鬥,那怕打贏了,也會覺得消耗過多,選擇重讀存檔重打。這樣的遊戲玩下去很有壓力,跟魂系遊戲有得比。多磨幾次,人也會累。但SFC 舊作,只有副武器為消耗性。你的劍和盾,可以一直用,副武用光,誰怕誰。 參考連結 筆者遊玩時看的攻略httpslasjargon.blogspot.com201412legendofzeldalinktopastchapter01.htmlm=1,雖然覺得不全,但至少讀得懂 由 本封面圖像可由任天堂處取得。, Fair use, httpszh.wikipedia.orgwindex.phpcurid=7663843

為何Python這麼熱門?
科技新知
MacauYeah・2024-08-27

在資料處理、資料科學領域,什麼是最近的AI模型,Python都是做這些事的熱門選擇。對於以前從未用過Python來處理業務的筆者來講,實在不懂為何Python會那麼大熱。不過最近,筆者實戰過後,真心覺得它是提高生產力的重要工具,而且並不限於資料科學上面,一些簡單的腳本操作也是很有優勢的。 筆者前述有討論過 型別對程式語言的重要性,到現時這一刻,筆者都會覺得【型別】是有助於長期的程式開發。而Python這個語言,大部份人都會介紹它是動態語言,可以使用弱型別,然後,就沒有其他講法了。動態弱型別,筆者一直都不認為它的根本上的原因。就像Javascript一樣,它亦發展出類靜態強型別的Typescript版本,而且它亦不因此而被人棄用。所以Python的強大,動態語言並不一最重要的原因,它也可以模疑寫出有規有距的type hinting。 或者用另一個方向問,大家覺得 Excel SpreadSheet 好用嗎?它們可以很簡易地做出資料計算、篩選。而且可以一邊做,一邊調整公式。例如要大家做一個陣列的總和,大家會想打開一個Javascript,初始化陣列的每個數字,然後寫個For迴圈去計算總和嗎?還是打開 Excel SpreadSheet,打下一欄或一列的數字,然後叫出Sum函數?筆者一定會選擇後者,不單止因為寫函數比較方便,那怕之後要調整數字,也比較方便。 大家有感受到差異嗎?筆者想表達的是,在操作 Excel SpreadSheet 我們並不是整個程式重新執行一次,我們是修改完一部份,那上看到結果。但傳統的語言,例如C、Java、那怕是Javascript,我們都難以局部地更新或執行特定某一個區塊。那怕是現在我們有hot reload,但其實我們編寫的思維,都是讓我們完整執行起一個頁面,再人手輸入,看結果。如果我們只想運行某個單一Function函數,我們只能寫test case測試,但寫test case又是一個很大的入門門檻。 但大家如果看看Python,在古早的年代,Python已經有Python shell,那就像是Linux Shell或Window CMD一樣,可以一邊寫腳本,一邊看結果。寫了10行的程式,發現在第10行引用第5行的部份有問題,修正並執行第5行後,就可以回來馬上重跑第10行的語句,就馬上有結果了。第6至9行,因為沒有關聯性,就不需要逐一重新執行,那是多麼的方便阿。道理上,我們若沒有完整執行整個程式,可能還是有一些盲點,開發重要的,需要長期維護的程式,還是要像傳統一樣,有test case,有程式進入點,整個運行。但對於臨時性的操作,看看效果,我們實在無必要寫一個原整程式。 舉個例子,假如我們臨時有需要,要取得某個政府網站的即時數據,例如澳門的停車場資訊,空位的上下限是多少,我們絕對可以用python寫幾行就取得結果,然後順便做個資料運算。我們沒有必要很嚴僅地為考慮不同數據的出現情況,我們什至可以hard code 硬編碼地計算某個Array的元素。直到突然有一天,這個操作變得恆常化,我們還是有條件把之前的python程式碼,改寫成一個規規矩矩的完整腳本,包括異常處理,函數複用。其實Javascript在改用 NodeJs 作為引擎後,我們還是可以經過 Node.js REPL,來做互動操作,只是Python Shell出現得更早,也是官方支援的功能。 Python這個臨時操作的便利,對於資訊爆炸的年代來講,實在很幫得上忙。再加上現在除了Python Shell以前,還有Jupter Notebook,讓大家可以在Web頁面上,執行像Python Shell的互動操作,對於修過特定區域的程式碼,就更加方便。這些便利,都是不是因為動態語言來創造的優勢,而是實實在在的Coding Anywhere。

Github flow 沒有提及的發佈 - 佈署 | Release - Deployment
科技新知
MacauYeah・2024-08-23

不知道之前為大家介紹的github flow,大家覺得怎樣?好用嗎?今天,筆者又來講講筆者心中認為它沒有好好給出指引的地方。 我們的信心指數,其實沒有那麼高 在前文中,經過 pull request 、 code review 、 auto test ,道理上,開發者可以做的都已經做過了,然後就是等待發佈 Release。 對於單純的庫類型的程式碼,筆者認為,的確沒有事可以再做,實務上就是直接找人其他程多員試用最新版本,看看有沒有問題。只要 main master 上,明確的表示版本號的變更,就差不多等於直接發佈。有需要提供binary版本的,就還需要觸發上載binary的流程,但這個跟 pull request 觸發 auto test 差不多, auto test 成功後就上載。 對於服務類型的程式碼,例如 Web App 等,直接發佈到正式環境還是有些不妥吧?始終會即時影響到業務,我們至少有個測試場,經用戶做實際的業務操作去驗收。但這個時機,應該是在Github flow的什麼時候做? 在原始的git flow中,有一個叫做 develop 的相對穩定分支,僅次於 main 。它是功能開發完成後第一次pull request 的地方,我們可以用這個概念來做自動發佈到測試場。但若在github flow 中加入了這個 develop uat staging 分支,其實就等於複雜地回到過去傳統的 git flow中,對好多新手來講難以接受。Github flow 的成功簡化,其實很大依賴著自動化測試。現在的測試用例,並不再限於單元測試。就連整合測試,也可以經Docker等容器化技術去做,只要我們的自動化測試有足夠信心,就可以發佈。但反觀我們的 Web App 例子,我們認為自動化測試難似涵蓋所有情境,也難以開發。所以我們還在有個時間發佈到測試場,進行人工測試。 pull request 快速迭代 筆者結合自己的經驗,配上國外討論區 Stack overflow 的內容,筆者認為Github flow上進行 pull request 後,就是最好的發佈測試場時機。所以我們需要盡快進行驗收測試,完成後在Git commit上加上Tag,以示通過驗收測試,可以發佈正式環境的版本。 不過這個模式是有一個很重要的前題假設:快速迭代。當我們驗收完成後,盡可能快地發佈到正式環境,不然會阻礙下一個功能的pull request驗收,或是覆蓋了上一個pull request的驗收環境。 用反面的例子來說明,如果我們有很多功能需要驗收,或變化很多,或存在多輪的里程碑開發,我們就不適宜那上述模式。最保險的做法,還是回到傳統的 git flow ,引入 develop uat staging 分支。但如果大家還是那麼討厭傳統 git flow,筆者還是有另一個提議。 既不想回到傳統 git flow ,但又需要慬㥀的考慮驗收發佈流程 如果開發的功能變化比較大,需要多方面協調、測試、驗收,經歷多次里程碑後,才有一個對外發佈的版本,大家可以考慮分開 Repository 做開發。例如 v1,v2的 Repository 完全獨立。 v1 是已發佈的版本,有獨立的測試場,任何即時候需要修正,就在v1的 Repository 做 pull request。 v2 則是未發佈版本,亦有獨立的測試場。加入任何新功能後,就在v2的 Repository 做 pull request,用自己專用的測試場做驗收。到 v2 正式發佈後, v1 就封存處理,再開一個 v3 作為下一個大版本的開發。這個模式,那怕在庫類型的程式碼也用得上。 這樣做的好處是 git Repository 和歷史記錄都會獨立,自動發佈的腳本程也會簡單明確一些。壞處則是 v1 v2 難以做功能對比,我們只能靠人腦記著 v1 有沒有什麼後期加入的修正和功能,需要同步移植到 v2 中 相對的,著是同一個Repository,可以利用merge 功能確保 v1 有的,v2 都己處理,只是必需要很懂處理版本衝突問題。

Swarm Mode 上線番外篇:Ceph
科技新知
MacauYeah・2024-08-20

在預設Docker和K8s的容器主導世界裏面,其實一直都缺少了直觀的儲存空間。當你的程序需要讀寫故定的來源資料,該來源就必需是外部的穩定儲存空間,例如是資料庫、NFS。但資料庫、NFS等,要做到真的正穩定,其實就要走Cluster叢集模式,確保它們自己本身不是做成single point of failure 單點故障的元兇。 坊間,只要付得起錢,其實找個穩定的資料庫或NFS,也是有的。但如果你像筆者一樣,只有一塊或多塊【鐵】,就要試試開源的儲存引擎Ceph Storage。 Ceph Storage,有自己特有的CephFS格式,但也支援NFS httpsdocs.ceph.comenquincycephadminstall。也就是,只要我們有足夠多人力,道理上可以自己用實體機去模擬一個穩定的NFS。 因為只是試裝,筆者暫時只用VM來測試,完整的安裝script,可以在這裏找到。script使用Multipass VM,大家有條件的話,可以使用其他VM引擎來看重複。以下是一些官網上沒有提的重點 Ubuntu 24.04 還未能正式使用。在筆者做POC的當是,Ceph v18 在 Ubuntu 24.04上需要先解決,即使大家使用Curl base下載 binary,也未必能成功。 筆者成功測的版本是 Ubuntu 22.04 Ceph v17,全使用Ubuntu 發佈的內置版本。但大家也要留意自己的Ubuntu apt 有沒有更新到最新版,過去的 cephadm,引用的container image url也變更。記得更新到v17 的最新版,cephadm 指令才能成功取得image。 在官方說明文件的【Deploying a new Ceph cluster】中的【Adding Hosts】httpsdocs.ceph.comenreefcephadminstall#addinghosts 節章可能有些誤導,大家應該要看 【Host Management】中的【Adding Hosts】 httpsdocs.ceph.comenreefcephadmhostmanagement#cephadmaddinghosts 在每個節點內,可以直觀地連接地Ceph Dashboard,但若大家需要Port Forword,要注意你的Network Interface,筆者就只能經過預設的IPv4的public ip 進行ssh port forward,不能經過0.0.0.0。 Script 位置 httpsgithub.commacauyeahubuntuPackerImageblobmaininitCephCluster.sh

Spring Data 關聯型態 02
科技新知
MacauYeah・2024-08-09

Presist and Casecade 前次的文章,講了一些Spring Data最基本的關聯概念,但當要正式儲存或刪除,就有些考慮完整性問題。平常我們在處理資料庫的關聯表格時,也需要面Foreign Key的正確性問題。同樣地,Spring Data也有這方面的考量,但它有提份一個很方便的CascadeType選項,可以簡化一些流程。 假設你只能存取Parent Repo,那你需要在Parent中,加入CascadeType.All。當repo.saveparent時,它就會順多把所有child的也一併進行Save,你也不需要有Child Repo的存在。 @OneToManymappedBy=quot;parentquot;, cascade = CascadeType.All List children = new ArrayList; 但在複雜的狀況下,例如你不想在更新parent的情況下,不小心弄到child,特別是經過public web下的API操作,你對web client的資料正確性有存疑,就不要使用CascadeType了。這也是筆者認為在大多數情況下,我們都會把Parent和Child的CRUD分開操作,然後根據需要使用各自的repo save。 如果你一定要用CascadeType.ALL CascadeType.REMOVE,就要再留意刪除的問題。為什麼?因為刪除 parent,其實指的是某個parent不再存在,但不代表child也要一起刪除,child的parent連結可以變為null,也有重新連結其他parent的可能。 如果大家確定需要共同刪除,就可以用CascadeType.ALL 或 CascadeType.REMOVE。 還有一個新的選擇,orphanRemoval = true,也有類似效果。 @OneToManymappedBy=quot;parentquot;, cascade = CascadeType.REMOVE List children = new ArrayList; or @OneToManymappedBy=quot;parentquot;, orphanRemoval = true List children = new ArrayList; or @OneToManymappedBy=quot;parentquot;, cascade = CascadeType.REMOVE, orphanRemoval = true List children = new ArrayList; 筆者測試過,混著用也是可以的。若大家看過其他教程,可能會覺得orphanRemoval = true 和 CascadeType 總是一起出現,但它們其實是分別操作的。單獨使用orphanRemoval = true,有時候則是為了不會出現無主的child,但這不代表parent和child的想要同步更新。 JPA Entity 的生命週期 Spring Data跟傳統的資料庫Selete,Create,Update,Delete SQL 語句有所不同。也就是這個不同,它的CascadeType比資料庫的Cascade Update和Cascade Delete更強大。 Spring Data 預設其實是使用 jakarta.persistence.EntityManager,每個Entity主要分為四個狀態 Transient New 不在EntityManager的掌控中 Managed 在EntityManager的掌控中,將會在下次flush時,變成sql create或update statement Detached 脫離EntityManager的掌控,不受flush影響 Removed 在EntityManager的掌控中,將會在下次flush時,變成sql delete statement 在Spring Data Jpa 以前,我們若要直接操作Hibernate,經常見到persist, remove的寫法 entityManager.persistentity; entityManager.removeentity; entityManager.detachentity; entityManager.mergeentity; 其實persist就是把處於Transient、Removed的entity,改為Managed。而remove就是把Managed改為Removed。detach,merge也類似,就是Managed,Detached之間互換。 EntityManager最強大的是,它可以讓程序員不需要再為Managed狀態下的entity操心,它會自動判別下次flush,應該create還是update,如果完全沒有改動的,連update也不會執行。 註,flush和commit也有不同,flush就是從java寫到資料庫中,在資料庫commit前,還可以使用rollback放棄。 而Spring Data,則是進一步簡化,它把persist改為save,remove改為delete,然後自動選擇flush的時機。 CascadeType 在解釋完Entity 的生命週期後,終於可以回到CascadeType了。這裏的CascadeType不是資料庫的Cascade操作,其實它是指EntityManager的狀態操作是否有傳遞關係。亦即是,persistparent時,要不要連同child也一起操作 我們查看 CasecadeType 的原始碼,就可以發現可以被傳遞的操作共有以下這些 PERSIST MERGE REMOVE REFRESH DETACH ALL 以上全部 這裏的 CasecadeType.PERSIST ,跟資料庫的 Cascade Update 是不一樣的。資料庫裏的 Cascade Update,是指當 Parent 的 Primary Key 有變,對應child的 Foreign Key也一起變。但因為 JPA Entity 的機制, Parent 的 Primary Key 不可以改變,理論上不會發生類似資料庫的 Cascade Update,頂多有 Cascade Delete。 CasecadeType.PERSIST 就像之前述的生命週期解說一樣, 把 parent和 child 一起拉到受管理的狀態。 註 CascadeType.REMOVE有點尷尬,似乎有更特別的使用規範。筆者測試過,在某些情況下,CascadeType.REMOVE無法處理ForeignKey問題,又或者是,刪除的順序不對。詳見 spring boot data deletion Reference entitylifecyclemodel spring boot data deletion