Einführung in DAO
Bei der Arbeit mit einer Datenbank über JDBC oder sogar über Hibernate erweist sich der Code oft als umständlicher, als uns lieb ist. Eine Datenbankabfrage enthält häufig:
- Datenvalidierung
- Anforderungsparameter festlegen
- Auswahl der HQL-Abfrage abhängig von den Abfrageparametern
- Erstellen einer Abfrage mithilfe der Kriterien-API
- Caching-Einstellungen
- anfängliche Fehlerbehandlung usw.
Daher ist es üblich, spezielle Klassen für die Arbeit mit der Datenbank zu erstellen. Solche Klassen werden DAO (Data Access Object) genannt. Ihre Aufgabe besteht darin, alle Komplexitäten der Arbeit mit der Datenbank zu verbergen und eine schöne und praktische Schnittstelle nach außen bereitzustellen.
Beispiel:
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();
}
}
Wir haben eine Klasse EmployeeDAO , mit deren Hilfe wir Objekte vom Typ Employee aus der Datenbank holen. Die Klasse selbst ist zwar vollgestopft mit Anmerkungen, enthält aber keine Methoden, um sich selbst in der Datenbank zu speichern.
Vorteile von DAO
Dieser Ansatz bietet viele Vorteile:
Erstens haben wir die Arbeit mit der Datenbank vollständig in der DAO-Klasse versteckt. Wenn Sie sich in Zukunft dazu entschließen, alle Abfragen von HQL auf Criteria API oder Native Query umzuschreiben, hat dies keinerlei Auswirkungen auf den Code außerhalb dieser Klasse.
Zweitens können Sie das Verhalten dieser Methoden erschweren. Sie können Caching, Ereignisse und Parametervalidierung hinzufügen. Dies alles wird vor dem externen Code verborgen bleiben.
Drittens: Wenn Sie eine Methode benötigen, die noch nicht existiert, fügen Sie sie einfach hier hinzu. Ich benötige beispielsweise eine Methode, die alle bereits abgelaufenen Benutzeraufgaben zurückgibt. Dann mache ich einfach Folgendes:
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();
}
}
Ich habe der Klasse zwei Methoden hinzugefügt:
- getExpiredTasksCount() – gibt die Anzahl abgelaufener Aufgaben für den Benutzer zurück
- getExpiredTasks() – gibt eine Liste abgelaufener Aufgaben für den Benutzer zurück
Ich brauche Methoden – ich habe sie hinzugefügt. Und ich kann es sofort verwenden. Ich werde sie später optimieren.
Darüber hinaus können diese Methoden vor dem Umschreiben und Optimieren mit Unit-Tests abgedeckt werden, sodass wir wissen, dass die Arbeit mit der Datenbank gleich geblieben ist.
Standardansatz
Sehr oft haben DAO-Klassen dieselben Methoden. Zum Beispiel diese:
T getById (endgültige lange ID) | Holen Sie sich ein Objekt anhand seiner ID |
List<T> getItems (int from, int count) | Rufen Sie eine Liste von Objekten innerhalb eines bestimmten Bereichs ab |
List<T> getAll () | Holen Sie sich alle Objekte eines bestimmten Typs |
int getCount () | Ermitteln Sie die Anzahl der Objekte |
T save (endgültige T-Entität) | Objekt in Datenbank speichern |
T -Update (endgültige T-Entität) | Objekt in der Datenbank aktualisieren |
void delete (letzte T-Entität) | Löschen Sie ein Objekt aus der Datenbank |
void deleteById (endgültige lange EntityId) | Objekt anhand der ID aus der Datenbank löschen |
Diese Methoden sind in fast jeder DAO-Klasse auf der Welt zu finden. Wenn es nun eine Art DAO-Klasse gibt, dann verfügt sie mit einer Wahrscheinlichkeit von 90 % über solche Methoden.
Ja, es mag noch andere geben, aber es wird auch welche geben. Weil es sehr praktisch ist. Und es ermöglicht Ihnen, nicht direkt mit der Basis oder dem Ruhezustand zu interagieren.
Und wenn es identische Methoden gibt, was brauchen sie dann? Das ist richtig, fügen Sie es in die Basisklasse ein.
Es sieht ungefähr so aus:
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();
}
}
Und dann sieht unser EmployeeDAO so aus:
public class EmployeeDAO extends AbstractHibernateDAO<Employee> {
public EmployeeDAO (){
super(Employee.class );
}
}
Und TaskDAO ist so:
public class TaskDAO extends AbstractHibernateDAO<Task> {
public TaskDAO (){
super(Task.class );
}
}
Und beide Klassen verfügen über alle Methoden, die wir in AbstractHibernateDAO deklariert haben . Die Vereinheitlichung ist sehr bequem und praktisch.
GO TO FULL VERSION