使用Java泛型进行JPA findAll()查询和WHERE子句

jim*_*rds 16 java generics jpa criteria-api

因此,经过10年多的休整,我将回到Java并尝试使用JPA和Java泛型.我已经创建了一个基于泛型的findAll(other)JPA查询

SELECT * FROM source WHERE other_id = other.id;
Run Code Online (Sandbox Code Playgroud)

这是我要去的地方.它有效,但我想知道是否有更好,更清洁的方法来做到这一点.使用ManagedType很难,并没有太多完整的文档或简单的例子.

我决定尽可能保持我的代码通用(没有双关语),所以我使用JPA2.

这是所有实体类的根.我可能不需要它,但它阻止我有基本的错误.

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

}
Run Code Online (Sandbox Code Playgroud)

这是抽象的DAO类.我为实现类扩展了这个,因为我需要更具体地做其他活动 - 主要是确保加载延迟集.

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();
}
Run Code Online (Sandbox Code Playgroud)

有什么建议?如果有的话,我想要这个,所以其他人可以利用它.

Ada*_*dam 21

帽尖到亚当边,如果你不希望使用createQueryString和希望的类型安全:

 @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();
 }
Run Code Online (Sandbox Code Playgroud)

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


R. *_*sen 8

我发现这个页面非常有用

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 它实际上是JPQL(Java Persistance Query Language),它是JPA的核心.只要Java没有像.NET这样的Linq查询,你需要有一些JPQL,其中核心JPA不能做你想要的.如果您查看执行查找时实际发生的事情(MyClass.class,id),它会将其转换为SQL和您在peristance.xml中使用的方言.当您使用JPQL时,它会对您的查询执行相同的操作.你不会制作自己的JPA版本,你将添加到核心功能,如MyClass extends Object (2认同)

Edu*_*ard 2

这将起作用,如果您需要 where 语句,您可以将其添加为参数。

class GenericDAOWithJPA<T, ID extends Serializable> {
Run Code Online (Sandbox Code Playgroud)

…………

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