Zjednodušte DAO pomocou Spring a Java Generics

1. Prehľad

Tento článok sa zameria na zjednodušenie vrstvy DAO použitím jediného generovaného objektu prístupu k údajom pre všetky entity v systéme, čo povedie k elegantnému prístupu k údajom bez zbytočného neporiadku alebo výrečnosti.

Budeme stavať na triede Abstract DAO, ktorú sme videli v našom predchádzajúcom článku o Spring and Hibernate, a pridáme všeobecnú podporu.

2. Režimy dlhodobého spánku a DAO pre režim spánku

Väčšina produkčných kódových báz má nejaký druh vrstvy DAO. Implementácia sa zvyčajne pohybuje od viacerých tried bez abstraktnej základnej triedy až po nejaký druh generifikovanej triedy. Jedna vec je však konzistentná - existuje vždy viac ako jeden. S najväčšou pravdepodobnosťou existuje vzájomný vzťah medzi DAO a entitami v systéme.

V závislosti od úrovne použitých generík sa môžu skutočné implementácie líšiť od výrazne duplikovaného kódu po takmer prázdny, pričom logika je zoskupená do základnej abstraktnej triedy.

Tieto viaceré implementácie je možné obvykle nahradiť jedným parametrizovaným DAO. Môžeme to implementovať tak, aby sa nestratila žiadna funkcionalita, a to tak, že naplno využijeme bezpečnosť typu poskytovanú programom Java Generics.

Ďalej si ukážeme dve implementácie tohto konceptu, jednu pre vrstvu centrického pretrvávania Hibernate a druhú so zameraním na JPA. Tieto implementácie nie sú v žiadnom prípade úplné, ale môžeme ľahko pridať ďalšie metódy prístupu k údajom, ktoré sú zahrnuté.

2.1. Abstraktný zimný spánok - DAO

Poďme sa rýchlo pozrieť na AbstractHibernateDao trieda:

verejná abstraktná trieda AbstractHibernateDao {private Class clazz; @Autowired SessionFactory sessionFactory; public void setClazz (Class clazzToSet) {this.clazz = clazzToSet; } public T findOne (long id) {return (T) getCurrentSession (). get (clazz, id); } verejný zoznam findAll () {return getCurrentSession (). createQuery ("from" + clazz.getName ()). list (); } verejné T vytvoriť (entita T) {getCurrentSession (). saveOrUpdate (entita); návratový subjekt; } verejná aktualizácia T (entita T) {return (T) getCurrentSession (). merge (entita); } public void delete (entita T) {getCurrentSession (). delete (entita); } public void deleteById (long entityId) {T entity = findOne (entityId); vymazať (entita); } chránená relácia getCurrentSession () {návrat sessionFactory.getCurrentSession (); }}

Toto je abstraktná trieda s niekoľkými metódami prístupu k dátam, ktorá používa SessionFactory pre manipuláciu s entitami.

2.2. Generický režim dlhodobého spánku DAO

Teraz, keď máme abstraktnú triedu DAO, môžeme ju rozšíriť iba raz. Generická implementácia DAO sa stane jedinou implementáciou potrebujeme:

@Repository @Scope (BeanDefinition.SCOPE_PROTOTYPE) verejná trieda GenericHibernateDao rozširuje AbstractHibernateDao implementuje IGenericDao {//}

Najprv, Všimnite si, že samotná generická implementácia je parametrizovaná, čo klientovi umožňuje zvoliť správny parameter od prípadu k prípadu. To bude znamenať, že klienti získajú všetky výhody bezpečnosti typov bez toho, aby museli pre každú entitu vytvárať viac artefaktov.

Po druhé, všimnite si rozsah prototypu tejto generickej implementácie DAO. Použitie tohto rozsahu znamená, že kontajner Spring vytvorí novú inštanciu DAO zakaždým, keď je to potrebné (vrátane automatického napájania). To umožní službe podľa potreby používať viac DAO s rôznymi parametrami pre rôzne entity.

Dôvod, prečo je tento rozsah taký dôležitý, je spôsobený tým, ako Spring inicializuje fazuľa v kontajneri. Ponechanie generického DAO bez rozsahu by znamenalo použitie predvolený rozsah singletonov, ktorý by viedol k jednej inštancii DAO žijúcej v kontajneri. To by zjavne malo zásadné obmedzenie pre akýkoľvek druh zložitejšieho scenára.

The IGenericDao je jednoducho rozhranie pre všetky metódy DAO, aby sme mohli vložiť implementáciu, ktorú potrebujeme:

verejné rozhranie IGenericDao {T findOne (konečné dlhé ID); Zoznam findAll (); void create (konečná entita T); Aktualizácia T (konečná entita T); void delete (konečná entita T); void deleteById (posledná dlhá entitaId); }

2.3. Abstraktné JPA DAO

The AbstractJpaDao je veľmi podobný AbstractHibernateDao:

verejná abstraktná trieda AbstractJpaDao {private Class clazz; @PersistenceContext EntityManager entityManager; public void setClazz (Class clazzToSet) {this.clazz = clazzToSet; } public T findOne (Long id) {return entityManager.find (clazz, id); } public List findAll () {return entityManager.createQuery ("from" + clazz.getName ()) .getResultList (); } public void save (entita T) {entityManager.persist (entita); } public void update (entita T) {entityManager.merge (entita); } public void delete (entita T) {entityManager.remove (entita); } public void deleteById (Long entityId) {T entity = getById (entityId); vymazať (entita); }}

Podobne ako v implementácii Hibernate DAO, aj my priamo používame rozhranie Java Persistence API bez toho, aby sme sa spoliehali na dnes už zastaranú jar JpaTemplate.

2.4. Všeobecné JPA DAO

Podobne ako v prípade implementácie dlhodobého spánku je aj objekt prístupu k údajom JPA jednoduchý:

@Repository @Scope (BeanDefinition.SCOPE_PROTOTYPE) verejná trieda GenericJpaDao rozširuje AbstractJpaDao implementuje IGenericDao {//}

3. Injekcia tohto DAO

Teraz máme jediné rozhranie DAO, ktoré môžeme vložiť. Musíme tiež špecifikovať Trieda:

@Service trieda FooService implementuje IFooService {IGenericDao dao; @Autowired public void setDao (IGenericDao daoToSet) {dao = daoToSet; dao.setClazz (Foo.class); } // ...}

Jar autowires novú inštanciu DAO pomocou vstrekovania setra aby bolo možné implementáciu prispôsobiť pomocou Trieda objekt. Po tomto bode je DAO plne parametrizovaný a pripravený na použitie službou.

Existujú samozrejme aj iné spôsoby, ako je možné určiť triedu pre DAO - pomocou reflexie alebo dokonca v XML. Preferujem toto jednoduchšie riešenie z dôvodu lepšej čitateľnosti a transparentnosti v porovnaní s použitím odrazu.

4. Záver

Tento článok pojednával o zjednodušenie vrstvy prístupu k údajom poskytnutím jedinej, opakovane použiteľnej implementácie generického DAO. Ukázali sme implementáciu v prostredí Hibernate aj JPA. Výsledkom je efektívna vrstva perzistencie bez zbytočných neporiadkov.

Podrobný úvod o nastavení jarného kontextu pomocou konfigurácie založenej na prostredí Java a základnej pomôcke Maven pre projekt nájdete v tomto článku.

Nakoniec kód tohto článku nájdete v projekte GitHub.


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