Egyszerűsítse a DAO-t a Spring és a Java Generics segítségével

1. Áttekintés

Ez a cikk a következőkre fog összpontosítani a DAO réteg egyszerűsítése egyetlen, generált adatelérési objektum használatával a rendszer összes entitása számára, ami elegáns adatelérést eredményez, felesleges rendetlenség és bőbeszédűség nélkül.

Építeni fogunk az Absztrakt DAO osztályra, amelyet a tavaszról és a hibernált állapotról szóló korábbi cikkünkben láthattunk, és általános támogatást adunk hozzá.

2. A Hibernate és a JPA DAO-k

A legtöbb gyártási kódbázis valamilyen DAO réteggel rendelkezik. Általában a megvalósítás több absztrakt alaposztály nélküli osztálytól kezdve valamilyen generált osztályig terjed. Egy dolog azonban következetes - van mindig több, mint egy. Valószínűleg egy-egy kapcsolat van a DAO-k és a rendszerben lévő entitások között.

Továbbá, az érintett generikumok szintjétől függően, a tényleges megvalósítások az erősen duplikált kódtól a szinte üresig változhatnak, a logika nagy része egy absztrakt alaposztályba csoportosítva.

Ezeket a többszörös megvalósításokat általában egyetlen paraméterezett DAO-val lehet helyettesíteni. Ezt úgy valósíthatjuk meg, hogy a Java Generics által biztosított típusbiztonság teljes kihasználásával ne veszítsen el funkcionalitást.

Ezt követően ennek a koncepciónak két megvalósítását mutatjuk be, az egyiket a hibernált központú perzisztencia rétegre, a másikat a JPA-ra összpontosítva. Ezek a megvalósítások korántsem teljesek, de könnyen hozzáadhatunk további további adatelérési módszereket.

2.1. Az absztrakt hibernált DAO

Vessünk egy gyors pillantást a AbsztraktHibernateDao osztály:

public abstract class AbstractHibernateDao {private Class clazz; @Autowired SessionFactory sessionFactory; public void setClazz (Class clazzToSet) {this.clazz = clazzToSet; } public T findOne (hosszú id) {return (T) getCurrentSession (). get (clazz, id); } public List findAll () {return getCurrentSession (). createQuery ("from" + clazz.getName ()). list (); } public T create (T entitás) {getCurrentSession (). saveOrUpdate (entitás); visszatérési egység; } public T update (T entitás) {return (T) getCurrentSession (). egyesítés (entitás); } public void delete (T entitás) {getCurrentSession (). delete (entitás); } public void deleteById (hosszú entitásId) {T entitás = findOne (entitásId); törlés (entitás); } védett munkamenet getCurrentSession () {return sessionFactory.getCurrentSession (); }}

Ez egy absztrakt osztály, több adatelérési módszerrel, amely a SessionFactory entitások manipulálásáért.

2.2. Az általános hibernált DAO

Most, hogy megvan az elvont DAO osztály, csak egyszer kibővíthetjük. A DAO általános megvalósítása lesz az egyetlen megvalósítás szükségünk van:

@Repository @Scope (BeanDefinition.SCOPE_PROTOTYPE) public class GenericHibernateDao extends AbstractHibernateDao implementates IGenericDao {//}

Első, vegye figyelembe, hogy az általános megvalósítás maga is paraméterezett, lehetővé téve az ügyfél számára, hogy eseti alapon kiválassza a helyes paramétert. Ez azt jelenti, hogy az ügyfelek megkapják a típusbiztonság minden előnyét anélkül, hogy minden egyes entitáshoz több műterméket kellene létrehozniuk.

Másodszor, vegye észre a DAO általános megvalósításának prototípusa. Ennek a hatókörnek a használata azt jelenti, hogy a Spring tároló minden egyes alkalommal kéri a DAO új példányát (ideértve az automatikus vezetést is). Ez lehetővé teszi a szolgáltatás számára, hogy szükség esetén több DAO-t használjon, különböző paraméterekkel, különböző entitásokhoz.

Annak oka, hogy ez a hatókör olyan fontos, annak az oka, hogy a Spring inicializálja a babot a tartályban. Ha az általános DAO-t hatókör nélkül hagyja, az a felhasználást jelentené az alapértelmezett szingulett hatókör, ami a DAO egyetlen példányához vezetne a tárolóban. Ez nyilvánvalóan jelentősen korlátozna bármilyen bonyolultabb forgatókönyvet.

A IGenericDao egyszerűen egy interfész az összes DAO módszerhez, hogy beadhassuk a szükséges megvalósítást:

nyilvános felület IGenericDao {T findOne (végső hosszú id); List findAll (); void create (végső T entitás); T frissítés (végső T entitás); void delete (végső T entitás); void deleteById (végső hosszú entitásId); }

2.3. Az elvont JPA DAO

A AbsztraktJpaDao nagyon hasonlít a AbsztraktHibernateDao:

public abstract class AbstractJpaDao {private Class clazz; @PersistenceContext EntityManager entitásManager; public void setClazz (Class clazzToSet) {this.clazz = clazzToSet; } public T findOne (Long id) {return entitásManager.find (clazz, id); } public list findAll () {return entitásManager.createQuery ("from" + clazz.getName ()) .getResultList (); } public void save (T entitás) {entityManager.persist (entitás); } public void update (T entitás) {entitManager.merge (entitás); } public void delete (T entitás) {entityManager.remove (entitás); } public void deleteById (Hosszú entitásId) {T entitás = getById (entitásId); törlés (entitás); }}

A Hibernate DAO megvalósításához hasonlóan a Java Persistence API-t is közvetlenül használjuk, anélkül, hogy a most elavult tavaszra támaszkodnánk JpaTemplate.

2.4. Az általános JPA DAO

A hibernált megvalósításhoz hasonlóan a JPA Data Access Object is egyszerű:

@Repository @Scope (BeanDefinition.SCOPE_PROTOTYPE) public class GenericJpaDao kiterjeszti az AbstractJpaDao megvalósítja az IGenericDao {//}

3. A DAO beadása

Most már egyetlen DAO interfészünk van, amelyet injekciózhatunk. Meg kell adnunk a Osztály:

@Service osztály A FooService megvalósítja az IFooService {IGenericDao dao; @Autowired public void setDao (IGenericDao daoToSet) {dao = daoToSet; dao.setClazz (Foo.osztály); } // ...}

Tavaszi automatikusan beállítja az új DAO példányt szetter injekcióval hogy a megvalósítás testreszabható legyen a Osztály tárgy. Ezt követően a DAO teljesen paraméterezett és készen áll a szolgáltatás használatára.

Természetesen más módon is megadható az osztály a DAO számára - reflektálás útján, vagy akár XML-ben. Előnyben részesítem ezt az egyszerűbb megoldást, a jobb olvashatóság és átláthatóság miatt, mint a reflexió használata.

4. Következtetés

Ez a cikk a az adatelérési réteg egyszerűsítése egy általános DAO egyetlen, újrafelhasználható megvalósításának biztosításával. Megmutattuk a megvalósítást mind hibernált, mind JPA alapú környezetben. Az eredmény egy korszerű perzisztáló réteg, felesleges rendetlenség nélkül.

A Spring kontextus Java-alapú konfigurációval és az alap Maven pom használatával történő lépésről lépésre történő bemutatásához olvassa el ezt a cikket.

Végül a cikk kódja megtalálható a GitHub projektben.