001package model.repository;
002
003import org.hibernate.Session;
004import org.hibernate.SimpleNaturalIdLoadAccess;
005
006import javax.persistence.EntityManager;
007import javax.persistence.LockModeType;
008import javax.persistence.PersistenceContext;
009import javax.persistence.criteria.CriteriaQuery;
010import java.io.Serializable;
011import java.util.List;
012
013/**
014 * Classe che incapsula la logica CRUD di base per tutte le entità persistenti
015 * @see javax.persistence.EntityManager
016 */
017public class GenericRepository implements Serializable {
018
019    @PersistenceContext
020    protected EntityManager em;
021
022    /**
023     *  Trova per chiave primaria
024     * @return L'entità trovata o null se l'entità non esiste
025     * @throws IllegalArgumentException se la chiave primaria fornita è null o non valida per l'entità da cercare
026     * @see javax.persistence.EntityManager#find(Class, Object)
027     */
028    public <T> T findById(Class<T> entityClass, Object primaryKey, boolean loadLazily) {
029        return loadLazily ? em.getReference(entityClass, primaryKey) :
030                            em.find(entityClass, primaryKey, LockModeType.NONE);
031    }
032
033    /**
034     * Trova per chiave primaria, restituendo un'entità caricata pigramente (lazy-loaded). L'entità restituita viene
035     * caricata al primo accesso effettuato. Se l'istanza non esiste, viene lanciato {@link javax.persistence.EntityNotFoundException}
036     * quando l'istanza viene acceduta per la prima volta.
037     * @return L'entità caricata pigramente
038     * @throws IllegalArgumentException se la chiave primaria fornita è null o non valida per l'entità da cercare
039     * @throws javax.persistence.EntityNotFoundException se l'entità non può essere acceduta
040     * @see javax.persistence.EntityManager#getReference(Class, Object)
041     */
042    public <T> T findById(Class<T> entityClass, Object primaryKey){
043        return findById(entityClass,primaryKey,false);
044    }
045
046    public <T> T findByNaturalId(Class<T> entityClass, Object naturalKey) {
047        return findByNaturalId(entityClass,naturalKey,false);
048    }
049
050    public <T> T findByNaturalId(Class<T> entityClass, Object naturalKey, boolean getReference) {
051        SimpleNaturalIdLoadAccess<T> entity = em.unwrap(Session.class).bySimpleNaturalId(entityClass);
052        return getReference ? entity.getReference(naturalKey) : entity.load(naturalKey);
053    }
054
055    /**
056     * Restituisce una lista tipata contenente tutte le istanze di una determinata entità di persistenza
057     * @return La lista dei risultati
058     * @throws javax.persistence.QueryTimeoutException In caso di timeout raggiunto
059     * @throws javax.persistence.PersistenceException
060     */
061    public <T> List<T> findAll(Class<T> entityClass) {
062        CriteriaQuery<T> c = em.getCriteriaBuilder().createQuery(entityClass);
063        c.select(c.from(entityClass));
064        return em.createQuery(c).getResultList();
065    }
066
067    /**
068     * Restituisce il numero indicante la quantità di istanze di una determinata entità di persistenza
069     * @return La quantità di istanze
070     * @throws javax.persistence.QueryTimeoutException In caso di timeout raggiunto
071     * @throws javax.persistence.PersistenceException
072     */
073    public <T> Long getCount(Class<T> entityClass) {
074        CriteriaQuery<Long> c =
075                em.getCriteriaBuilder().createQuery(Long.class);
076        c.select(em.getCriteriaBuilder().count(c.from(entityClass)));
077        return em.createQuery(c).getSingleResult();
078    }
079
080    /**
081     * Crea un'istanza persistente e gestita (managed entity)
082     * @param entity L'istanza di entità
083     * @return L'istanza passata come parametro
084     * @throws javax.persistence.EntityExistsException se l'entità esiste già
085     * @see javax.persistence.EntityManager#persist(Object)
086     */
087    public <T> T insert(T entity) {
088        em.persist(entity);
089        em.flush();
090        return entity;
091    }
092
093    /**
094     * Unisce lo stato di una data entità allo stato nel contesto di persistenza
095     * @param entity
096     * @return Una copia <i>managed</i> dell'entità passata come parametro
097     * @see javax.persistence.EntityManager#merge(Object)
098     */
099    public <T> T merge(T entity) {
100        return em.merge(entity);
101    }
102
103    /**
104     * Rimuove l'istanza dal contesto di persistenza
105     * @param entity L'entità managed da rimuovere
106     * @throws IllegalArgumentException se l'entità passata non è managed
107     */
108    public <T> void remove(T entity) {
109        em.remove(entity);
110    }
111}