Čiastočná aktualizácia údajov s jarnými údajmi

1. Úvod

Jarné údaje CrudRespository # uložiť je nepochybne jednoduchý, ale jednou vlastnosťou by mohla byť nevýhoda: Aktualizuje každý stĺpec v tabuľke. Taká je sémantika U v CRUD, ale čo ak chceme namiesto toho urobiť PATCH?

V tomto výučbe sa budeme venovať technikám a prístupom k vykonaniu čiastočnej namiesto úplnej aktualizácie.

2. Problém

Ako už bolo uvedené, uložiť () prepíše každú priradenú entitu poskytnutými údajmi, čo znamená, že nemôžeme poskytnúť čiastočné údaje. To sa môže stať nepohodlným, najmä pre väčšie objekty s veľkým počtom polí.

Keby sme sa pozreli na ORM, existujú nejaké opravy, napríklad:

  • Hibernácie @DynamicUpdatanotácia, ktorá dynamicky prepíše aktualizačný dotaz
  • JPA @ Stĺpec anotáciu, pretože pomocou. môžeme zakázať aktualizácie na konkrétnych stĺpcoch aktualizovateľné parameter

Ale v nasledujúcom budeme k tomuto problému pristupovať s konkrétnym zámerom: Naším cieľom je pripraviť naše subjekty na uložiť bez spoliehania sa na ORM.

3. Náš prípad

Najprv si postavme a Zákazník subjekt:

@Entity public class Customer {@Id @GeneratedValue (strategy = GenerationType.AUTO) public long id; verejné meno reťazca; verejný reťazcový telefón; } 

Potom definujeme jednoduché úložisko CRUD:

@Repository verejné rozhranie CustomerRepository rozširuje CrudRepository {Customer findById (dlhé ID); }

Nakoniec si pripravíme a Zákaznícka služba:

@ Verejná trieda služieb CustomerService {@Autowired Repozitár zákazníkov; public void addCustomer (názov reťazca) {Customer c = new Customer (); c.name = meno; repo.save (c); }}

4. Načítajte a uložte prístup

Najprv sa pozrime na prístup, ktorý je pravdepodobne známy: načítanie našich entít z databázy a potom aktualizácia iba tých polí, ktoré potrebujeme.

Aj keď je to jednoduché a zrejmé, jedná sa o najjednoduchší prístup, ktorý môžeme použiť.

Pridajme do našej služby metódu na aktualizáciu kontaktných údajov našich zákazníkov.

public void updateCustomerContacts (long id, String phone) {Customer myCustomer = repo.findById (id); myCustomer.phone = telefón; repo.save (myCustomer); }

Zavoláme findById metódu a načítať zodpovedajúcu entitu, potom pokračujeme a aktualizujeme požadované polia a údaje uchováme.

Táto základná technika je efektívna, keď je počet polí na aktualizáciu relatívne malý a naše entity sú pomerne jednoduché.

Čo by sa stalo s desiatkami polí, ktoré sa majú aktualizovať?

4.1. Stratégia mapovania

Keď majú naše objekty veľké množstvo polí s rôznymi úrovňami prístupu, je úplne bežné implementovať vzor DTO.

Teraz predpokladajme, že ich máme viac ako sto telefón polia v našom objekte. Napísať metódu, ktorá naleje dáta z DTO do našej entity, ako sme to už robili predtým, by mohlo byť obťažujúce a dosť neudržateľné.

Napriek tomu môžeme túto otázku prekonať pomocou mapovacej stratégie, konkrétne pomocou MapStruct implementácia.

Vytvorme a CustomerDto:

verejná trieda CustomerDto {private long id; verejné meno reťazca; verejný reťazcový telefón; // ... private String phone99; }

A tiež a CustomerMapper:

@Mapper (componentModel = "jar") verejné rozhranie CustomerMapper {void updateCustomerFromDto (CustomerDto dto, @MappingTarget entita zákazníka); }

The @MappingTarget anotácia nám umožňuje aktualizovať existujúci objekt a ušetrí nás to tak od bolesti pri písaní veľkého množstva kódu.

MapStruct@BeanMapping metóda dekoratér, ktorá nám umožňuje definovať pravidlo, ktoré sa má vynechať nulový hodnoty počas procesu mapovania. Pridajme to k nášmu updateCustomerFromDto rozhranie metódy:

@BeanMapping (nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)

Vďaka tomu môžeme načítať uložené entity a zlúčiť ich s DTO pred volaním na JPA uložiť metóda: v skutočnosti budeme aktualizovať iba upravené hodnoty.

Pridajme teda do našej služby metódu, ktorá bude volať nášho mapovača:

public void updateCustomer (CustomerDto dto) {Customer myCustomer = repo.findById (dto.id); mapper.updateCustomerFromDto (dto, myCustomer); repo.save (myCustomer); }

Nevýhodou tohto prístupu je, že nemôžeme obstáť nulový hodnoty do databázy počas aktualizácie.

4.2. Jednoduchšie entity

Na záver nezabudnite, že k tomuto problému môžeme pristupovať od fázy návrhu aplikácie.

Je nevyhnutné definovať naše entity tak, aby boli čo najmenšie.

Poďme sa pozrieť na naše Zákazník subjekt. Čo ak to trochu štruktúrujeme a všetko extrahujeme telefón polia do ContactPhone subjekty a byť vo vzťahu dvojstranný?

@Entity public class CustomerStructured {@Id @GeneratedValue (strategy = GenerationType.AUTO) public Long id; verejné meno reťazca; @OneToMany (fetch = FetchType.EAGER, targetEntity = ContactPhone.class, mappedBy = "customerId") súkromný zoznam contactPhones; }

Kód je čistý a čo je dôležitejšie, niečo sme dosiahli. Teraz môžeme aktualizovať naše entity bez toho, aby sme museli načítať a vyplniť všetky tieto položky telefón údaje.

Manipulácia s malými a ohraničenými entitami nám umožňuje aktualizovať iba potrebné polia.

Jedinou nepríjemnosťou tohto prístupu je, že by sme mali navrhovať svoje entity s vedomím, bez toho, aby sme padli do pasce nadmerného inžinierstva.

5. Vlastný dopyt

Ďalším prístupom, ktorý môžeme implementovať, je definovanie vlastného dotazu pre čiastočné aktualizácie.

V skutočnosti JPA definuje dve anotácie, @ Úpravy a @Dopyt, ktoré nám umožňujú výslovne napísať naše vyhlásenie o aktualizácii.

Teraz môžeme našej aplikácii povedať, ako sa má správať počas aktualizácie, bez zaťaženia ORM.

Pridajme našu vlastnú metódu aktualizácie do úložiska:

@Modifying @Query ("update Customer u set u.phone =: phone where u.id =: id") void updatePhone (@Param (value = "id") long id, @Param (value = "phone") String telefón); 

Teraz môžeme prepísať našu metódu aktualizácie:

public void updateCustomerContacts (long id, String phone) {repo.updatePhone (id, phone); } 

Teraz sme schopní vykonať čiastočnú aktualizáciu: iba s niekoľkými riadkami kódu a bez zmeny našich entít sme dosiahli náš cieľ.

Nevýhodou tejto techniky je, že budeme musieť definovať metódu pre každú možnú čiastočnú aktualizáciu nášho objektu.

6. Záver

Čiastočná aktualizácia údajov je dosť zásadná operácia; Aj keď môžeme mať svoj ORM, ktorý to zvládne, niekedy môže byť ziskové získať nad ním úplnú kontrolu.

Ako sme videli, môžeme predbežne načítať naše údaje a potom ich aktualizovať alebo definovať naše vlastné príkazy, ale nezabudnite na vedomie nevýhod, ktoré tieto prístupy znamenajú, a spôsobov, ako ich prekonať.

Ako obvykle je zdrojový kód tohto článku k dispozícii na GitHub.


$config[zx-auto] not found$config[zx-overlay] not found