Inleiding tot DAO

Bij het werken met een database via JDBC of zelfs via Hibernate, blijkt de code vaak omslachtiger dan we zouden willen. Een databasequery bevat vaak:

  • gegevensvalidatie
  • verzoekparameters instellen
  • Selectie HQL-query afhankelijk van queryparameters
  • een query maken met behulp van de Criteria API
  • cache instellingen
  • initiële foutafhandeling, enz.

Daarom is het gebruikelijk om speciale klassen te maken voor het werken met de database. Dergelijke klassen worden DAO, Data Access Object, genoemd. Hun taak is om alle complexiteit van het werken met de database te verbergen en een mooie en handige interface naar buiten te bieden.

Voorbeeld:

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();
   }
}

We hebben een klasse EmployeeDAO , met behulp waarvan we objecten van het type Employee uit de database halen. De klasse zelf, hoewel gevuld met annotaties, bevat geen methoden om zichzelf op te slaan in de database.

Voordelen van DAO

Er zijn veel voordelen aan deze aanpak:

Ten eerste hebben we het werk met de database volledig verborgen in de DAO-klasse. Als u in de toekomst besluit om alle query's van HQL naar Criteria API of Native Query te herschrijven, heeft dit op geen enkele manier invloed op de code buiten deze klasse.

Ten tweede kunt u het gedrag van deze methoden bemoeilijken. U kunt caching, gebeurtenissen en parametervalidatie toevoegen. Dit wordt allemaal verborgen voor de externe code.

Ten derde, als je een methode nodig hebt die nog niet bestaat, voeg je die gewoon hier toe. Ik heb bijvoorbeeld een methode nodig die alle gebruikerstaken retourneert die al zijn verlopen. Dan doe ik gewoon dit:

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();
  }
}

Ik heb twee methoden aan de klasse toegevoegd:

  • getExpiredTasksCount() - retourneert het aantal verlopen taken voor de gebruiker
  • getExpiredTasks() - retourneert een lijst met verlopen taken voor de gebruiker

Ik heb methoden nodig - ik heb ze toegevoegd. En ik kan het meteen gebruiken. Ik zal ze later optimaliseren.

Bovendien kunnen deze methoden worden behandeld met unit-tests vóór herschrijven en optimalisaties, zodat we weten dat het werk met de database hetzelfde is gebleven zoals het was.

Standaard aanpak

Heel vaak hebben DAO-klassen methoden die hetzelfde zijn. Deze bijvoorbeeld:

T getById (laatste lange id) Krijg een object door zijn id
Lijst<T> getItems (int van, int aantal) Krijg een lijst met objecten binnen een bepaald bereik
Lijst<T> getAll () Verkrijg alle objecten van een bepaald type
int getCount () Ontdek het aantal objecten
T save (laatste T-entiteit) Object opslaan in database
T- update (definitieve T-entiteit) Object in database bijwerken
nietig verwijderen (laatste T-entiteit) Verwijder een object uit de database
void deleteById (laatste lange entityId) Verwijder object uit database op id

Deze methoden zijn te vinden in bijna elke DAO-klasse ter wereld. Nu, als er een soort DAO-klasse is, dan zal het met een waarschijnlijkheid van 90% dergelijke methoden hebben.

Ja, er kunnen anderen zijn, maar die zullen er ook zijn. Omdat het erg handig is. En het stelt u in staat om niet rechtstreeks met de basis of Hibernate te communiceren.

En als er identieke methoden zijn, wat hebben ze dan nodig? Dat klopt, zet het in de basisklasse.

Het ziet er ongeveer zo uit:

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();
    }
}

En dan ziet onze EmployeeDAO er zo uit:

public class EmployeeDAO extends AbstractHibernateDAO<Employee> {

   public EmployeeDAO (){
  	super(Employee.class );
   }
}

En TaskDAO is als volgt:

public class TaskDAO extends AbstractHibernateDAO<Task> {

   public TaskDAO (){
  	super(Task.class );
   }
}

En beide klassen hebben alle methoden die we op AbstractHibernateDAO hebben gedeclareerd . Unificatie is erg handig en praktisch.