使用Java泛型为JPA查找带有WHERE子句的findAll()查询 [英] Using Java generics for JPA findAll() query with WHERE clause

查看:2738
本文介绍了使用Java泛型为JPA查找带有WHERE子句的findAll()查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,经过10多年的休假后,我回到了Java,并试用了JPA和Java泛型的东西。我创建了基于

 <$ c的基于泛型的 findAll(other) JPA查询$ c> SELECT * FROM source WHERE other_id = other.id; 

这就是我要做的。它的工作原理,但我想知道是否有更好,更干净的方式来做到这一点。使用 ManagedType 很难,并且没有太多完整的文档或简单的例子。

我的代码尽可能通用(没有双关语意图),所以我使用JPA2。



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

  import java.io.Serializable; 

public abstract class DomainObject实现Serializable {

private static final long serialVersionUID = 1L;

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




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

 公共抽象类GenericDAOImpl< T扩展了DomainObject,T2扩展了DomainObject>实现GenericDAO< T,T2> {

私人课程< T>类型;

@PersistenceContext
受保护的EntityManager entityManager;

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

...保存并删除班级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()){
//循环所有与此类匹配的属性
if(singleAttribute.getJavaType()。 equals(where.getClass())){
//赢家!
attribute = singleAttribute;
休息;


//其中t.object = object.getID()
criteriaQuery.where(criteriaBuilder.equal(rootQuery.get(attribute),where));
}
criteriaQuery.select(rootQuery);
TypedQuery< T> query = entityManager.createQuery(criteriaQuery);

//需要这个来确保我们有一个干净的列表?
// entityManager.clear();
返回query.getResultList();
}

有什么建议吗?如果有的话,我希望这样做,以便其他人可以使用它。 解决方案

不想使用 createQuery 并使用字符串并希望输入安全性:


  @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);
返回allQuery.getResultList();
}


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


So, After a 10+ year break I'm coming back to Java and trying out stuff with JPA and Java generics. I've created a generics based findAll(other) JPA query that basically does

SELECT * FROM source WHERE other_id = other.id;

This is where I'm up to. It works, but I'm wondering if there's a better, cleaner way to do it. Using ManagedType was hard, and there's not much complete documentation or simple examples around.

I've decided to keep my code as generic as possible (no pun intended) so I use JPA2.

This is the root of all Entity Classes. I probably don't need it, but it stops me from having basic mistakes.

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

}

This is the abstract DAO class. I extend this for the implementation classes as I need to be more specific doing other activities - mostly making sure lazy sets are loaded.

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

Any suggestions? If anything, I want this out there so other people can make use of it.

解决方案

Hat tip to Adam Bien if you don't want to use createQuery with a String and want type safety:

 @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

这篇关于使用Java泛型为JPA查找带有WHERE子句的findAll()查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆