使用CriteriaBuilder选择refTable引用的实体

时间:2013-06-23 18:36:59

标签: jpa eclipselink

我对JPA很新(基于eclipselink)所以请耐心等待我和我的问题。我发现JPA是处理简单DB语句的一种优雅方式。但是,现在我想做一些更复杂的任务 所以让我解释一下我想要的东西:我有一张表拿着人的数据(比如人名)。在另一张表中,我想保留地址列表。因为一个人的方式是几个地址列表和一个地址列表的一部分可能会保留几个人,我需要一个ref-table jo加入这些集合。

所以我的数据库表看起来像这样:
SQL (不是精确的DDL语法,但它有助于理解!) - 没有约束等      - 该人保存人员数据     创建表a_person     (       oid serial PrimaryKey NOT NULL,       vorname字符各不相同(50),       nachname字符变化(50)NOT NULL        -     )

--the adresslist is quite simple: just a name of the list is storred
CREATE TABLE a_adressliste (
(
  oid serial PrimaryKey NOT NULL,
  label character varying(25) NOT NULL
  --<more collumns here>
)

    --the table refering the list the the containing persons
CREATE TABLE a_listen_person
(
  fk_adressliste bigint PrimaryKey NOT NULL,    --ref to a_person.oid
  fk_person bigint PrimaryKey NOT NULL,     --ref to a_adressliste.oid
)

在数据库中使用此结构和一些数据,可以使用以下SQL语句轻松选择地址列表:

  select * from a_person p where p.oid in (
    select
        lp.fk_person 
    from 
        a_listen_person lp, a_adresssliste al 
    where 
        lp.fk_adressliste = al.oid AND al.label = {LISTE_LABEL}
  )

现在,根据数据库中的结构,我已经在这些表中得到了相应的JAVA POJO(我已经跳过了注释以保持我的代码更短)

JAVA

 public class Person implements Serializable {
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     @Basic(optional = false)
     @Column(name = "oid")
     private Integer oid;
     private String vornmae;
     private String nachname;

     //getter; setter and the other missing stuff...
 }

public class Adressliste implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "oid")
    private Integer oid;

    private String label;
}

public class ListenPerson implements Serializable {
    @EmbeddedId
    private ListenPersonPK listenPerson;//build from Person.oid and Adressliste.oid
    private Person person;
    private Adressliste adresssliste;

    //getter; setter and the other missing stuff...
}

现在我在 JAVA 中编写了一个finder方法,我使用CriteriaBuilder按几个属性过滤实体(根据Person POJO)。但我没有设法根据给定的列表名称选择Person。 到现在为止,我的方法看起来像这样:

  public TypedQuery<Person> prepareQueryFiltered(Filter filter) {
    TypedQuery<Person> retVal;
    EntityManager em = this.getEntityManager();

    CriteriaBuilder builder = em.getCriteriaBuilder();
    CriteriaQuery<Person> query = builder.createQuery(Person.class);
    Root<Person> cust = query.from(Person.class);
    query.select(cust);

    List<Predicate> predicateList = new ArrayList<Predicate>();

    Predicate predicate;

    if (null != filter.getVorname()) {
        predicate = builder.like(
                builder.lower(cust.<String>get("vorname")),
                "%" + filter.getVorname().toLowerCase() + "%");
        predicateList.add(predicate);
    }
    if (null != filter.getNachname()) {
        predicate = builder.like(
                builder.lower(cust.<String>get("nachname")),
                "%" + filter.getNachname().toLowerCase() + "%");
        predicateList.add(predicate);
    }
    //some more filtered attributes ...

    query.where(predicateList.toArray(new Predicate[predicateList.size()]));

    retVal = em.createQuery(query);

    return retVal;
}

您可以想象,filter属性会保留所有数据以过滤我的实体。但是,如果我想获得属于给定列表名称的所有人物实体,代码如何? 我开始使用'子查询',但我没有得到正确的语法。你能给我一些提示吗?

1 个答案:

答案 0 :(得分:0)

有关Criteria API中子查询的示例,请参阅

http://en.wikibooks.org/wiki/Java_Persistence/Criteria#Subquery

另外,我认为你不需要子查询,简单的连接应该可以工作。

Select p from Person p, ListenPerson l where l.person = p and l.adresssliste.label  = :label