El uso de Java genéricos para JPA findAll() consulta con la cláusula where

Así que, Después de 10 años de descanso estoy volviendo a Java y probando cosas con JPA y Java generics. He creado un genéricos basados en findAll(other) JPA consulta que básicamente hace

SELECT * FROM source WHERE other_id = other.id;

Este es de donde yo soy. Funciona, pero me pregunto si hay una mejor, más limpia de hacerlo. El uso de ManagedType fue duro, y no hay mucho que complete la documentación o ejemplos sencillos alrededor.

He decidido mantener mi código lo más genérico posible (sin juego de palabras), así que uso JPA2.

Esta es la raíz de todas las Clases de Entidad. Yo probablemente no lo necesita, pero que me impide tener errores básicos.

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

}

Este es el resumen de DAO clase. Extiendo la presente, para la implementación de las clases que necesitan para ser más específicos, haciendo otras actividades – sobre todo asegurarse de perezoso sets están cargados.

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

Alguna sugerencia? Si cualquier cosa, quiero que este ahí para que otros puedan hacer uso de ella.

Por qué reinventar la rueda? Spring Data JPA ya hace todo eso y más. Y para la Primavera de los haters Spring Data JPA funciona bien en una llanura JEE medio ambiente también sin Muelle (aparte de la de uso interno de la Primavera de Datos JPA) necesarios.
Estoy usando la Primavera para mi la capa de presentación, pero no estoy listo para leer más de 10,000 páginas de documentación todavía a trabajar fuera de Spring DATA JPA (y he leído mucho en los últimos pocos meses ya). Estoy seguro de Spring DATA JPA puede hacer – y yo estaría encantado de publicar ejemplos/enlaces. Pero esto funciona, es no-estándar de Java libre y teniendo en cuenta hace 2 meses yo no tenía ninguna idea acerca de este … de todos modos, si quiero saber la forma de una rueda que funciona, voy a construir uno no comprar.
Este debe ser publicado en codereview.stackexchange.com. Que dijo. ¿Qué pasa si un Niño tiene un padre y una madre, tanto de tipo Humano?
Sí, no funciona cuando hay más de un Atributo del mismo tipo. He encontrado esto con mi Subject Entity tener String username' y String password;.

OriginalEl autor jim.richards | 2014-07-04

4 Kommentare

  1. 17

    Sombrero de punta a Adán Bien si usted no desea utilizar createQuery con un String y quiere que tipo de seguridad:

     @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

    OriginalEl autor Adam

  2. 6

    Encontré esta página muy útil

    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();
        }
    }
    Estoy tratando de evitar el uso de SQL en la consulta. Es sólo mi preferencia, de lo contrario me acababa el uso puro de SQL en las transacciones, y entonces termina de escribir su propia versión de JPA.
    Es, de hecho, JPQL (Java Persistencia Query Language), es el núcleo de JPA. Mientras que Java no tiene consultas Linq como .NET es necesario tener algunos JPQL donde el núcleo JPA no hacemos lo que queremos. Si usted echa un vistazo a lo que realmente sucede cuando usted hace una búsqueda(MyClass.class, id) es que se traduce en SQL y el dialecto que está utilizando en su peristance.xml. Cuando se utiliza JPQL se hace lo mismo con su consulta. Usted no hará su propia versión de la app, usted tendrá que añadir a la funcionalidad básica, como Miclase extends Object

    OriginalEl autor R. Gulbrandsen

  3. 1

    también puede utilizar un namedQuery nombre findAll para todas sus entidades, y se llama en su genérico FindAll con entityManager.createNamedQuery(persistentClass.getSimpleName()+"findAll").getResultList();
    }

    `

    OriginalEl autor vvs

  4. 0

    Este trabajo, y si usted necesita donde declaración puede agregarlo como parámetro.

    class GenericDAOWithJPA<T, ID extends Serializable> {

    …….

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

    OriginalEl autor Eduard

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea