Bevezetés a DAO-ba
Amikor egy adatbázissal JDBC-n vagy akár Hibernate-n keresztül dolgozunk, a kód gyakran körülményesebbnek bizonyul, mint szeretnénk. Egy adatbázis-lekérdezés gyakran a következőket tartalmazza:
- adatérvényesítés
- kérési paraméterek beállítása
- HQL lekérdezés kiválasztása a lekérdezés paramétereitől függően
- lekérdezés összeállítása a Criteria API használatával
- gyorsítótárazási beállítások
- kezdeti hibakezelés stb.
Ezért az általános gyakorlat az, hogy speciális osztályokat hoznak létre az adatbázissal való munkához. Az ilyen osztályokat DAO-nak, Data Access Object-nek nevezik. Feladatuk, hogy elrejtse az adatbázissal való munka minden bonyolultságát, és gyönyörű és kényelmes felületet biztosítson a külső számára.
Példa:
public class EmployeeDAO {
public List<Employee> getEmployeeList(int from, int count) {
String hqlQuery = “from Employee”;
Query<Employee> query = session.createQuery(hqlQuery, Employee.class);
query.setFirstResult(from);
query.setMaxResults(count);
return query.getResultList();
}
public int getEmployeeCount() {
String hqlQuery = “select count(*) from Employee”;
Query<Integer> query = session.createQuery(hqlQuery, Integer.class);
return query.getSingleResult();
}
public Employee getEmployeeByUniqName(String name) {
String hqlQuery = “from Employee where name = :name”;
Query<Integer> query = session.createQuery(hqlQuery, Employee.class);
query.setParameterr(“name”, name);
return query.getSingleResult();
}
}
Van egy EmployeeDAO osztályunk , melynek segítségével Employee típusú objektumokat kapunk az adatbázisból. Maga az osztály, bár tele van megjegyzésekkel, nem tartalmaz metódusokat az adatbázisba való mentésre.
A DAO előnyei
Ennek a megközelítésnek számos előnye van:
Először is teljesen elrejtettük az adatbázissal végzett munkát a DAO osztályban. Ha a jövőben úgy dönt, hogy az összes lekérdezést átírja a HQL-ről a Criteria API-ra vagy a Native Query-re, ez semmilyen módon nem befolyásolja az ezen az osztályon kívüli kódot.
Másodszor, bonyolíthatja ezeknek a módszereknek a viselkedését. Hozzáadhat gyorsítótárat, eseményeket, paraméterellenőrzést. Mindez rejtve lesz a külső kód elől.
Harmadszor, ha olyan módszerre van szüksége, amely még nem létezik, egyszerűen adja hozzá ide. Például szükségem van egy metódusra, amely visszaadja az összes már lejárt felhasználói feladatot. Akkor csak ezt csinálom:
public class EmployeeDAO {
public List<Task> getExpiredTasks(int userId, int from, int count) {
String hqlQuery = “from Task where task.user.id = :id and deadline < curdate()”;
Query<Task> query = session.createQuery(hqlQuery, Task.class);
query.setFirstResult(from);
query.setMaxResults(count);
return query.getResultList();
}
public int getExpiredTasksCount(int userId) {
String hqlQuery = “select count(*) from Task where task.user.id = :id and deadline < curdate()”;
Query<Integer> query = session.createQuery(hqlQuery, Integer.class);
return query.getSingleResult();
}
}
Két módszert adtam az osztályhoz:
- getExpiredTasksCount() – a felhasználó lejárt feladatainak számát adja vissza
- getExpiredTasks() – a lejárt feladatok listáját adja vissza a felhasználó számára
Módszerek kellenek – tettem hozzá. És azonnal használhatom. Később optimalizálom őket.
Sőt, ezeket a módszereket átírás és optimalizálás előtt egységtesztekkel is lefedhetjük, így tudni fogjuk, hogy az adatbázissal végzett munka a régiben maradt.
Szabványos megközelítés
Nagyon gyakran a DAO osztályoknak ugyanazok a metódusai vannak. Például ezek:
T getById (végső hosszú azonosító) | Szerezzen be egy objektumot az azonosítójával |
List<T> getItems (int from, int count) | Szerezzen listát az adott tartományon belüli objektumokról |
List<T> get All () | Adott típusú összes objektum lekérése |
int getCount () | Állapítsa meg az objektumok számát |
T mentés (végső T entitás) | Objektum mentése adatbázisba |
T frissítés (végső T entitás) | Objektum frissítése az adatbázisban |
érvénytelen törlés (végső T entitás) | Töröljön egy objektumot az adatbázisból |
void deleteById (végső hosszú entityId) | Objektum törlése az adatbázisból azonosítóval |
Ezek a módszerek a világ szinte minden DAO osztályában megtalálhatók. Nos, ha van valamilyen DAO osztály, akkor 90% valószínűséggel lesznek ilyen metódusai.
Igen, lehetnek mások, de lesznek azok is. Mert nagyon kényelmes. És lehetővé teszi, hogy ne lépjen kapcsolatba közvetlenül az alappal vagy a hibernálással.
És ha vannak azonos módszerek, akkor mire van szükségük? Így van, tedd az alaposztályba.
Valahogy így néz ki:
public abstract class AbstractHibernateDao<T > {
private final Class<T> clazz;
private SessionFactory sessionFactory;
public AbstractHibernateDao(final Class<T> clazzToSet) {
this.clazz = clazzToSet;
}
public T getById(final long id) {
return (T) getCurrentSession().get(clazz, id);
}
public List<T> getItems(int from, int count) {
Query query = getCurrentSession().createQuery(clazz , "from " + clazz.getName())
query.setFirstResult(offset);
query.setMaxResults(count);
return query.singleResult();
}
public List<T> findAll() {
return getCurrentSession().createQuery(clazz, "from " + clazz.getName()).list();
}
public T create(final T entity) {
getCurrentSession().saveOrUpdate(entity);
return entity;
}
public T update(final T entity) {
return (T) getCurrentSession().merge(entity);
}
public void delete(final T entity) {
getCurrentSession().delete(entity);
}
public void deleteById(final long entityId) {
final T entity = getById(entityId);
delete(entity);
}
protected Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
}
És akkor az EmployeeDAO- nk így fog kinézni:
public class EmployeeDAO extends AbstractHibernateDAO<Employee> {
public EmployeeDAO (){
super(Employee.class );
}
}
A TaskDAO pedig ilyen:
public class TaskDAO extends AbstractHibernateDAO<Task> {
public TaskDAO (){
super(Task.class );
}
}
És mindkét osztály rendelkezik mindazzal a metódussal, amelyet az AbstractHibernateDAO -n deklaráltunk . Az egységesítés nagyon kényelmes és praktikus.
GO TO FULL VERSION