搜尋

搜尋結果

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

Presist and Casecade 前次的文章,講了一些Spring Data最基本的關聯概念,但當要正式儲存或刪除,就有些考慮完整性問題。平常我們在處理資料庫的關聯表格時,也需要面Foreign Key的正確性問題。同樣地,Spring Data也有這方面的考量,但它有提份一個很方便的CascadeType選項,可以簡化一些流程。 假設你只能存取Parent Repo,那你需要在Parent中,加入CascadeType.All。當repo.save(parent)時,它就會順多把所有child的也一併進行Save,你也不需要有Child Repo的存在。 @OneToMany(mappedBy="parent", 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,也有類似效果。 @OneToMany(mappedBy="parent", cascade = CascadeType.REMOVE) List children = new ArrayList(); // or @OneToMany(mappedBy="parent", orphanRemoval = true) List children = new ArrayList(); // or @OneToMany(mappedBy="parent", 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.persist(entity); entityManager.remove(entity); entityManager.detach(entity); entityManager.merge(entity); 其實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的狀態操作是否有傳遞關係。亦即是,persist(parent)時,要不要連同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 entity-lifecycle-model spring boot data deletion

【日本。京都自駕】清水寺
走遍世界
80後愛旅行✈️・2023-05-21

把車停在「京都市清水坂觀光駐車場」, 一般私家車是1,000円一次, 在這繁忙的遊客區可說是非常便宜了, 而位置就在五条坂和清水坂上。 停車時工作人員跟我們說只能停2小時(應該是車太多要做管制吧), 最後我們停了多於2小時工作人員也沒有為難我們, 都直接給我們離開 停車場有兩邊的出入口, 一個是在五条坂上, 而另一個是在繁忙的清水坂上 我們由「五条坂」出來, 這邊比起附近的二年坂、三年坂和清水坂實在清靜太多太多了, 五條坂主要以賣清水燒的商舖和藝廊居多, 感覺這邊沒什麼遊客, 店舖內都沒有人的... 我們就在五条坂上吃了午餐(穿著和服吃午餐真的不是簡單的事, 腰不能彎, 又怕弄髒衣服.....累死寶寶了) 然而我不太建議大家走這條「五条坂」, 這條路的坡度太大, 加上旁邊沒什麼店好看, 走起來有點吃力! 往清水寺的路上實在太多「坂」, 當時我都只是往清水寺的方向一直走, 很難分清自己到底走在什麼「坂 」上~ 走著走著就轉往人流比較多的「坂」上, 無論是「伏見稻荷大社」還是「清水寺」都是穿和服來逛的最熱門地點! 「清水寺」 清水寺是一座位於日本京都府京都市東山區清水的寺院, 清水寺全名為音羽山清水寺, 是著名的賞楓及賞櫻景點。 與北山鹿苑寺(金閣寺)、嵐山天龍寺、二條城等同為京都境內最著名的名勝古蹟, 1994年被列入世界文化遺產名錄。 這就是我們由市營停車場走到清水寺的路線, 旁邊的二年坂、清水新道等很多我們都沒走到呢! 來到清水寺的大門 「仁王門」 在1467年到1477年間被戰爭摧毀, 但在16世紀初重建並於2003年被拆除和修復。 約10米寬, 約5米深, 約14米高, 是重要文化財產。 從「仁王門」上往回看, 能看到眼下滿滿都是人的「清水坂」 這是我們在清水寺內的行走路線 「三重塔」 高約31米, 從古代起就是清水寺的象徵, 也是全日本最大的三重塔。 鮮艷的顏色真的可以遠遠就看到這座塔了! 繼續順著往「本堂」的路線 旁邊可以看到12月上旬還有紅葉的庭園 「隨求堂」 奉有佛祖, 供奉婚姻、安全交付、育兒等的神社。 另一個角度看到的「三重塔」, 真的非常宏偉, 果然是日本第一。 進入「本堂」及以後的範圍是要買票的, 這票必須買, 因為在這之後的地方才是最美! 入場費: 300円 門票也是以「三重塔」為圖呢~! 進到「清水本堂」 最為人熟悉和喜愛的一定是「清水舞台」, 是一個可以遠眺外面美景的一個好地方! 在遠處的紅色塔是「子安塔」 「清水本堂」和「清水舞台」是連為一體的, 可以說「清水舞台」是「清水本堂」的「露台」。 清水寺的本堂建在奧山的懸崖上, 是1633年重建的一座木製建築。 它是以日本古代傳統建築方式為基礎的堅固結構, 能夠支撐著眾多朝聖者擁擠的舞台, 是國寶級的建築。 這是「清水本堂」和「清水舞台」的結構 (官網照片) 眺望到清水寺內美麗的庭園 「清水本堂」內供奉的十一面千手觀音像還是能夠保佑財運的文化遺產。 冬天被白雪包圍的「清水本堂」實在太美了~ 好想冬天的時候再來一次! 走過「清水本堂」出來 這是被紅葉包圍下的「阿彌陀堂」, 真的很美! 繼續往「音羽の滝」的方向走~ 清水寺配上紅葉, 真的拍到不想離開!!

Spring Data 關聯型態 01
科技新知
MacauYeah・2024-07-16

筆者身邊的朋友,首次接觸 ORM 的關聯型態時都會覺得很難,筆者自己也是。但在好好地理順它的設計時,就會覺得其實很簡單。 因為篇輻很長,我們先以Code First的角度,先體驗一下ORM程式讀取的便捷性,以及解決一個常見的序列化問題。 雙向存取 例如一個Parent,有好幾個Child @Entity public class Parent { // ... Parent Primay Key @OneToMany(mappedBy="parent") List children = new ArrayList(); // TODO add remove } @Entity public class Child { // ... Child Primay Key @ManyToOne Parent parent; } 上述的寫法很簡潔,ORM會為你自動加入join column,處理關聯的載入。在讀取Parent時,它的所有Children就可以直接在Java層面讀取,在讀取Child時,它的Parent也隨時取得。也就是,開發人員只要經SQL準備其中一方的資料,另一方並不需要手動準備,它就可以自動按需載入。 RESTFul API 坑-雙向存取 Spring Data在Java層面的雙向存取,已經做到很方便。但經常坑到我們的是Spring Data與RESTFul API的混合應用。當我們嘗試經API回傳我們的Parent Json時,API會很聰明地把關聯的Children也變成Json回傳。但他也會把child中的parent不斷重複變成json,變成無限輪迴。 坊間有兩種不同的解決方案,可以防止無限輪迴。 讓Json可以認得已經序列化的元素。@JsonIdentityInfo 讓Json只可以單向序列化(serialization)。@JsonManagedReference, @JsonBackReference, @JsonIgnore 筆者兩個方向都試過,但首個方法並不通用,至少它不能算是一般常見的無腦Json結構。它需要伺服器、客戶端都懂這如何經IdentityInfo認得重複出現的元素。 而單向序列化,是筆者現時的通用解。在設計RESTFul READ API時,筆者就會決定到底是Parent自動回傳Child,還是Child自動回傳Parent。決策的考慮因素,主要在於是否可以簡化Client的API調用次數。通常從Parent出發,自動回傳Child,可以節省API調用。但如果是選項性的結果(List of Value),就倒過來。有時候,遇著API需要雙向設計,就只好自己設計DTO資料傳輸對象 (Data transfer object, DTO)。 例如Parent API,就原封不動回傳原本的元素 @Entity public class Parent{ // ... Parent Primay Key @OneToMany(mappedBy="parent") List children = new ArrayList(); } @Entity public class Child { // ... Child Primay Key @ManyToOne @JsonIgnore Parent parent; } Child API,就反過來引用。 public class ParentDTO { // ... Parent Other fields except children } public class ChildDTO { ParentDTO parent; // ... Child Other fields } 這種DTO,看起來很麻煩。但其實Spring有提供一個簡便的複制DTO功能,它可以把自動複制兩個class中有同一名稱、同一型別的欄位到另一個class上,不需要逐個欄位明文寫出來。 BeanUtils.copy(child, childDTO); BeanUtils.copy(parent, parentDTO); childDTO.setParent(parentDTO) // 因為child、childDTO中的parent欄位型別不同,BeanUtils.copy會自動忽略,其他欄位就會自動複制。 註: 其實古早的網頁系統設計,DTO的概念一直存取。只是現在RESTFul API的流行,很多框架已經提向便捷的Json轉換。若然平時只需Json單向存取,筆者還是省略DTO的建立。

動作遊戲天尊Capcom也做不好的事:打擊感與互動機制
手機‧電玩
MacauYeah・2023-04-14

好多朋友都知道,Capcom出名善於制作動作遊戲,而且它的動作打擊感極好。Monster Hunter,Devil May Cry系列,都是把公認的動作遊戲王者,聲、畫、特效、節奏、打擊感發揮到極致的遊戲。但筆者始終都覺得,它們欠缺了一份重要的東西,它們所謂的打擊感怎好,都像是打空氣一樣。而且萬年不變,代代也是少了一點。然而,筆者玩過Capcom的Street Fighter V,明明就可以把打擊感做到更完美,為何Monster Hunter/Devil May Cry就怪怪的呢?直到,筆者玩過Sekiro: Shadows Die Twice/SIFU等遊戲,才恍然大悟,所以趁機會好好來聊一聊。 傳統上的打擊感 我們先來講講,傳統上的打擊感是什麼?首先,打擊感是通過角色動作、畫面特效、音效等多種元素來實現的。通過對不同狀況下調整視覺和聽覺感覺,讓玩家感受到攻擊/打擊動作在不同物件時的合理性,來模擬打擊的感覺。例如:角色在攻擊揮空時,配上劃過的風聲,給人一種動作凌厲的感覺;角色攻擊命中時,動作稍為卡頓,並配上敲打或切割音效,讓人感覺到切實地打中了。更加詳細的,就是角色在受擊時,因應不同的打點,有不同的受擊動作,讓一切都顯示的因為玩家的操作而且互動。 在格鬥遊戲中Street Fighter V中,就完美演繹了上述的各點,所以筆者就覺得很完美。但Monster Hunter/Devil May Cry,其實都有相應的特效,為何打擊感就差了那麼多? 廣義上的打擊感:互動機制 Monster Hunter/Devil May Cry,對動作、特效、音效,都制作得很好。但唯獨遊戲的互動機制設計得很差。Monster Hunter系列,每隻怪物都存在霸體機制。需要玩家長期地命中某些攻擊,才會出現倒地或氣絕等狀態。筆者玩下去,就是一種長期打牆的感覺:對對對,你打中了,但感覺像是打空氣。換個角度就是說,但你有你打,它有它存在。你以為自己在玩Monster Hunter,其實你在玩Rockman。而Devil May Cry也差不多,每次Boss戰就霸體連連,連人型Boss戰(例如:DMC5 M20的Vergil)也沒有很好修釋,真的有合理性的只有小兵戰。 Sekiro: Shadows Die Twice/SIFU又有何不同?最不一樣的就是敵人會正面防禦。你的攻擊對敵人來說都會被擋著,只有在互相搶攻時才可能被Counter,或是被長期施壓時出現破防(架勢條被打滿而破防)。反過來,你也可以防禦敵人的攻擊,但也會被Counter或破防。敵人要反擊時,通常會先前幾招格檔,然後突然躲掉你的攻擊讓你揮空,又或是直接招架(Parry)你的攻擊後,才來打你。同樣的,你也可以同相同機制來對付敵人。即使在這種情況下,Boss設計上,它的招式上還是可以保持強勢,依然有很多不一樣的花招、更強的範圍判定。敵我雙方的機制相同,但Boss的設計亦不失霸氣。 兩類遊戲,本質上的差別就在於,Sekiro: Shadows Die Twice/SIFU會以格擋和血條以外的機制來處理互動。而Monster Hunter/Devil May Cry就以霸體、累計暈眩值來處理。 結論:互動要合理 雖然原則上遊戲AI早就掌管好一切,玩家所作的事情也是「被互動」。但在Sekiro: Shadows Die Twice/SIFU這種「被互動」制,就明顯地合理很多。你不會覺得在打空氣,頂多是覺得對方AI太強,會更加逼使自己使不同的策略來應對。SIFU在最終Boss設計更顯高明,最終Boss的首階段,會使用與主角一模一樣的招式。與玩家的分別,就只有出招時機和預判。初次遊玩的玩家,一定會很驚訝,原來自己的那一套,還可以這樣用(而且通常都被Boss打得很慘)。 還沒玩過SIFU的朋友,真的可以去一試,Sekiro: Shadows Die Twice可能難度更高一些。不過也很值得大家去試。

星宇航空與台灣聯合報推出夏令營
旅遊情報
OHChance 旅遊誌・2021-04-07

星宇航空與台灣的聯合報旗下的 ”有.行旅” 推出夏令營,分別針對初中、高中生及大學生、研究生分別於7月中及下旬推出一營。 為期8日7夜的營期將由星宇航空帶領團員由航空業到航空公司的前、中、後端運作進行了解。亦會介紹航空業相關科系的選科及升學資訊。 這次營隊主打八個賣點: 星宇航空董事長 "K董" 張國煒親自授課 全程星宇航空運籌中心集訓 由飛行員、簽派員、塔台控制人員解密航空安全 進入管制區第一身近距離一窺地面操作詳細 8月1日霸氣獨包航機於空中舉行結業典禮 星宇傳統極具創意結業禮物及結業證書 八天七夜創夏令營全記錄 絕版星宇A321 Neo飛行夾克 相關營隊8天7夜總費用為新台幣128,000元(約合港幣35000元),包含上課費用、7晚住宿林口亞昕福朋喜來登酒店、餐食費用、結業航班等。如有興趣了解報名的請至 ”有.行旅” 查詢。 國中、高中組:https://utravel.udn.com/activities/travel_intro.jsp?type=new&cate=7&aid=968 大學、研究所組:https://utravel.udn.com/activities/travel_intro.jsp?type=new&cate=7&aid=969 相關活動章程:https://s3-ap-northeast-1.amazonaws.com/uts.udn.com.tw/html/att/action/969/atta/969_20210401182531.pdf === 睇完覺得OK ge,不妨like 埋我地 Facebook, IG, 同埋 sub 我地 Youtube 啦: https://fb.com/ohchance @ohchance_travel https://youtube.com/c/OHChanceTravel