0

我对 JPA(基于 eclipselink)非常陌生,所以请耐心等待我和我的问题。我发现 JPA 是一种处理简单 DB 语句的优雅方式。但是,现在我想做一些更复杂的任务。
所以让我解释一下我想要什么:我有一个保存人员数据的表(让我们说人名)。在另一个表中,我想保留地址列表。因为一个人是几个地址列表和一个地址列表的一部分可能会保留几个人,所以我需要一个参考表来加入这些集合。

所以我的数据库表看起来像这样:
SQL(不是精确的 DDL 语法,但它有助于理解!) -- 没有约束等
-- 人保存人员的数据 CREATE TABLE a_person ( oid serial PrimaryKey NOT NULL, vorname character varying(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中编写了一个查找器方法,其中我使用 CriteriaBuilder 按多个属性过滤实体(根据 Person POJO)。但我没有设法根据给定的列表名称选择人。现在我的方法是这样的:

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

正如您可以想象的那样,过滤器属性保留了所有数据来过滤我的实体。但是,如果我想获取属于给定列表名称的所有人员实体,代码会是什么样子?
我开始使用“子查询”,但没有得到正确的语法。你能给我一些提示吗?

4

1 回答 1

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
于 2013-06-24T13:55:23.613 回答