簡體   English   中英

將 Java 泛型用於帶有 WHERE 子句的 JPA findAll() 查詢

[英]Using Java generics for JPA findAll() query with WHERE clause

所以,在 10 多年的休息之后,我又回到 Java 並嘗試使用 JPA 和 Java 泛型的東西。 我創建了一個基於泛型的findAll(other) JPA 查詢,它基本上可以

SELECT * FROM source WHERE other_id = other.id;

這就是我要做的。 它有效,但我想知道是否有更好,更清潔的方法來做到這一點。 使用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();

}

這是抽象的 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();
}

有什么建議? 如果有的話,我希望它在那里,以便其他人可以使用它。

如果您不想將createQueryString一起使用並希望類型安全,請向 Adam Bien 提示:

 @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

我發現這個頁面非常有用

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

您還可以對所有實體使用名為 findAll 的 namedQuery 並在通用 FindAll 中調用它

entityManager.createNamedQuery(persistentClass.getSimpleName()+"findAll").getResultList();

這將起作用,如果您需要 where 語句,您可以將其添加為參數。

class GenericDAOWithJPA<T, ID extends Serializable> {

......

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM