web-dev-qa-db-fra.com

Utilisation de génériques Java pour les requêtes JPA findAll () avec la clause WHERE

Donc, après une pause de plus de 10 ans, je reviens en Java et j'essaye des trucs avec des génériques JPA et Java. J'ai créé une requête JPA findAll(other) à base de génériques

SELECT * FROM source WHERE other_id = other.id;

C'est là que je suis en train de faire. Cela fonctionne, mais je me demande s’il existe une méthode plus efficace et plus propre. Utiliser ManagedType était difficile, et il n’ya pas beaucoup de documentation complète ou d’exemples simples.

J'ai décidé de garder mon code aussi générique que possible (sans jeu de mots) donc j'utilise JPA2.

C'est la racine de toutes les classes d'entité. Je n'en ai probablement pas besoin, mais cela m'empêche d'avoir des erreurs élémentaires.

import Java.io.Serializable;

public abstract class DomainObject implements Serializable {

    private static final long serialVersionUID = 1L;

    public abstract void setId(Long id);
    public abstract Long getId();

}

C'est la classe abstraite DAO. J'étends cela pour les classes d'implémentation car j'ai besoin d'être plus spécifique pour faire d'autres activités - en m'assurant surtout que les jeux paresseux sont chargés.

public abstract class GenericDAOImpl<T extends DomainObject, T2 extends DomainObject> implements GenericDAO<T, T2> {

private Class<T> type;

@PersistenceContext
protected EntityManager entityManager;

public GenericDAOImpl(Class<T> type) {
    super();
    this.type = type;
}

... save and delete classes go here

@Override
public List<T> findAll(T2 where) {

    CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
    CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(type);
    Root<T> rootQuery = criteriaQuery.from(type);
    if (where != null) {

        EntityType<T> entity = entityManager.getMetamodel().entity(type);

        SingularAttribute<? super T, ?> attribute = null;
        for (SingularAttribute<? super T, ?> singleAttribute: entity.getSingularAttributes()) {
            // loop through all attributes that match this class
            if (singleAttribute.getJavaType().equals(where.getClass())) {
                // winner!
                attribute = singleAttribute;
                break;
            }
        }
        // where t.object = object.getID()
        criteriaQuery.where(criteriaBuilder.equal(rootQuery.get(attribute), where));
    }
    criteriaQuery.select(rootQuery);
    TypedQuery<T> query = entityManager.createQuery(criteriaQuery);

    // need this to make sure we have a clean list?
    // entityManager.clear();
    return query.getResultList();
}

Aucune suggestion? Si quelque chose, je veux ceci dehors là afin que d'autres personnes puissent l'utiliser.

15
jim.richards

Chapeau bas à Adam Bien si vous ne voulez pas utiliser createQuery avec un String et que vous voulez un type de sécurité:

 @PersistenceContext
 EntityManager em;

 public List<ConfigurationEntry> allEntries() {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<ConfigurationEntry> cq = cb.createQuery(ConfigurationEntry.class);
        Root<ConfigurationEntry> rootEntry = cq.from(ConfigurationEntry.class);
        CriteriaQuery<ConfigurationEntry> all = cq.select(rootEntry);
        TypedQuery<ConfigurationEntry> allQuery = em.createQuery(all);
        return allQuery.getResultList();
 }

http://www.adam-bien.com/roller/abien/entry/selecting_all_jpa_entities_as

17
Adam

J'ai trouvé cette page très utile

https://code.google.com/p/spring-finance-manager/source/browse/trunk/src/main/Java/net/stsmedia/financemanager/dao/GenericDAOWithJPA.java?r=2

public abstract class GenericDAOWithJPA<T, ID extends Serializable> {

    private Class<T> persistentClass;

    //This you might want to get injected by the container
    protected EntityManager entityManager;

    @SuppressWarnings("unchecked")
    public GenericDAOWithJPA() {
            this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    @SuppressWarnings("unchecked")
    public List<T> findAll() {
            return entityManager.createQuery("Select t from " + persistentClass.getSimpleName() + " t").getResultList();
    }
}
6
R. Gulbrandsen

vous pouvez également utiliser une requête nommée findAll nommée findAll pour toutes vos entités et l'appeler dans votre FindAll générique avec entityManager.createNamedQuery(persistentClass.getSimpleName()+"findAll").getResultList(); } `

1
vvs

Cela fonctionnera et si vous avez besoin de l'instruction where, vous pouvez l'ajouter comme paramètre.

class GenericDAOWithJPA<T, ID extends Serializable> {

.......

public List<T> findAll() {
            return entityManager.createQuery("Select t from " + persistentClass.getSimpleName() + " t").getResultList();
    }
}
0
Eduard