Részleges adatfrissítés tavaszi adatokkal

1. Bemutatkozás

Tavaszi adatok CrudRespository # mentés kétségtelenül egyszerű, de az egyik funkció hátrány lehet: A táblázat minden oszlopát frissíti. Ilyen az U szemantikája a CRUD-ban, de Mi van, ha PATCH-ot akarunk csinálni helyette?

Ebben az oktatóanyagban a teljes frissítés helyett részleges végrehajtás technikáival és megközelítéseivel foglalkozunk.

2. Probléma

Amint azt korábban mentés() felülír minden egyező entitást a megadott adatokkal, vagyis részleges adatokat nem tudunk megadni. Ez kellemetlenné válhat, különösen nagyobb, sok mezővel rendelkező objektumok esetében.

Ha megnéznénk egy ORM-et, léteznek néhány javítások, például:

  • Hibernáltak @DynamicUpdatannotáció, amely dinamikusan újraírja a frissítési lekérdezést
  • JPA-k @Oszlop megjegyzés, mivel a frissíthető paraméter

De a következőkben konkrét szándékkal fogunk megközelíteni ezt a problémát: Célunk, hogy felkészítsük entitásainkat a mentés módszer nélkül ORM-re támaszkodva.

3. Esetünk

Először építsünk egy Vevő entitás:

@Entity public class Customer {@Id @GeneratedValue (strategy = GenerationType.AUTO) public long id; public String név; nyilvános vonós telefon; } 

Ezután meghatározunk egy egyszerű CRUD adattárat:

@Repository nyilvános felület Az CustomerRepository kiterjeszti a CrudRepository {Customer findById (hosszú id); }

Végül elkészítjük a Vevőszolgálat:

@Service public class CustomerService {@Autowired CustomerRepository repo; public void addCustomer (Karakterlánc neve) {Ügyfél c = új Ügyfél (); c.név = név; repo.save (c); }}

4. Betöltés és mentés megközelítés

Először nézzünk meg egy valószínűleg ismerős megközelítést: az entitásaink betöltése az adatbázisból, majd csak a szükséges mezők frissítése.

Noha ez egyszerű és kézenfekvő, a legegyszerűbb megközelítéseket alkalmazhatjuk.

Vegyünk fel egy módszert a szolgáltatásunkba, hogy frissítsük ügyfeleink elérhetőségi adatait.

public void updateCustomerContacts (hosszú id, String telefon) {Ügyfél myCustomer = repo.findById (id); myCustomer.phone = telefon; repo.save (myCustomer); }

Felhívjuk a findById metódust és beolvassa az egyező entitást, majd folytatjuk és frissítjük a szükséges mezőket, és megőrizzük az adatokat.

Ez az alapvető technika akkor hatékony, ha a frissítendő mezők száma viszonylag kicsi, és entitásaink meglehetősen egyszerűek.

Mi történne több tucat frissítendő mezővel?

4.1. Térképezési stratégia

Amikor az objektumainknak nagyszámú, különböző hozzáférési szintű mezője van, elég gyakori a DTO-minta megvalósítása.

Tegyük fel, hogy több mint százunk van telefon mezők az objektumunkban. Olyan módszer megírása, amely az adatokat a DTO-ból önti az entitásunkhoz, ahogy korábban tettük, zavaró és eléggé fenntarthatatlan lehet.

Ennek ellenére leképezhetjük ezt a kérdést egy leképezési stratégia és különösen a MapStruct végrehajtás.

Hozzunk létre egy CustomerDto:

public class CustomerDto {private long id; public String név; nyilvános vonós telefon; // ... privát karakterlánc telefon99; }

És a CustomerMapper:

@Mapper (componentModel = "spring") nyilvános felület CustomerMapper {void updateCustomerFromDto (CustomerDto dto, @MappingTarget Customer entitás); }

A @MappingTarget az annotáció lehetővé teszi egy meglévő objektum frissítését, ezzel megmentve a sok kód megírásától.

MapStruct van egy @BeanMapping metódekorátor, amelynek segítségével meghatározhatunk egy szabályt, amelyet kihagyunk nulla értékek a leképezési folyamat során. Tegyük hozzá a sajátunkhoz updateCustomerFromDto módszer interfész:

@BeanMapping (nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)

Ezzel be tudjuk tölteni a tárolt entitásokat, és egyesíthetjük őket egy DTO-val, mielőtt felhívnánk a JPA-t mentés módszer: valójában csak a módosított értékeket frissítjük.

Tehát adjunk hozzá egy módszert a szolgáltatásunkhoz, amely felhívja a térképészünket:

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

Ennek a megközelítésnek az a hátránya, hogy nem léphetünk át nulla értékeket az adatbázisnak egy frissítés során.

4.2. Egyszerűbb entitások

Végül ne feledje, hogy ezt a problémát az alkalmazás tervezési szakaszától kezdve megközelíthetjük.

Alapvető fontosságú meghatározni entitásainkat, hogy a lehető legkisebbek legyenek.

Vessünk egy pillantást a mi Vevő entitás. Mi van, ha egy kicsit strukturáljuk, és kibontjuk az összes telefon mezők a ContactPhone entitások és egy-a-sokhoz viszonyban áll?

@Entity public class CustomerStructured {@Id @GeneratedValue (strategy = GenerationType.AUTO) public Long id; public String név; @OneToMany (fetch = FetchType.EAGER, targetEntity = ContactPhone.class, mappedBy = "customerId") privát lista contactPhones; }

A kód tiszta, és ami még fontosabb, valamit elértünk. Mostantól frissíthetjük entitásainkat anélkül, hogy az összeset be kellene töltenünk és kitöltenünk telefon adat.

Kis és korlátozott entitások kezelése csak a szükséges mezők frissítését teszi lehetővé.

E megközelítés egyetlen kellemetlensége, hogy tudatossággal kell megterveznünk entitásainkat, anélkül, hogy a túlmérnöki csapdába esnénk.

5. Egyéni lekérdezés

Egy másik megközelítés, amelyet megvalósíthatunk, egy egyedi lekérdezés meghatározása a részleges frissítésekhez.

Valójában a JPA két annotációt határoz meg, @ Módosító és @Lekérdezés, amelyek lehetővé teszik számunkra, hogy kifejezetten megírjuk frissítési nyilatkozatunkat.

Most elmondhatjuk alkalmazásunknak, hogyan kell viselkedni egy frissítés során, anélkül, hogy az ORM-re hárítanánk a terhet.

Vegyük fel az egyéni frissítési módszerünket a lerakatba:

@Modifying @Query ("update customer u set u.phone =: phone where u.id =: id") void updatePhone (@Param (value = "id") long id, @Param (value = "phone") String telefon); 

Most átírhatjuk a frissítési módszerünket:

public void updateCustomerContacts (hosszú id, String telefon) {repo.updatePhone (id, telefon); } 

Most részleges frissítést tudunk végrehajtani: csupán néhány kódsorral és entitásaink megváltoztatása nélkül elértük célunkat.

Ennek a technikának az a hátránya, hogy meg kell határoznunk egy módszert az objektumunk minden lehetséges részleges frissítésére.

6. Következtetés

A részleges adatfrissítés meglehetősen alapvető művelet; bár rendelkezhetünk ORM-mel a kezelésére, néha nyereséges lehet a teljes irányítás megszerzése.

Amint láttuk, előre betölthetjük adatainkat, majd frissíthetjük őket, vagy meghatározhatjuk az egyéni utasításokat, de ne felejtsük el, hogy tisztában kell lennünk a hátrányokkal, amelyeket ezek a megközelítések jelentenek, és azok leküzdésére.

Szokás szerint a cikk forráskódja elérhető a GitHubon.


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