2015-10-06 39 views
1

我有一個只有幾行變量的表。此行中的一行鏈接到另一個具有更多行的表。查詢使用查詢生成器從另一個表進行鏈接的表中的所有行

要說清楚,1個表稱爲連接。變量是:

name, groupname, etc. 

groupname應鏈接到第二個名爲ConnectionGroup的表。變量是:

name, id. 

我的想法是按名稱查詢到ConnectionGroup表。對於連接和ConnectionGroup抽象類是這樣的:

public abstract class Connection_ { 

    public static volatile SingularAttribute<Connection, String>name; 
    public static volatile SingularAttribute<Connection, String>host; 
    public static volatile SetAttribute<Connection, ConnectionGroup>connectionGroups; 
} 

public abstract class ConnectionGroup_ { 

    public static volatile SingularAttribute<ConnectionGroup, String> name; 
    public static volatile SingularAttribute<ConnectionGroup, Long> id; 

} 

查詢這個,我想我也來加入這兩個表,然後只對它們進行查詢。這是我曾嘗試代碼:

@PersistenceContext 
private EntityManager em; 

public List<Connection> retrieveAll(String groupFilter, int start, int length) { 
    ServiceUtil.requireAdmin(); 
    CriteriaBuilder cb = em.getCriteriaBuilder(); 
    CriteriaQuery<Connection> q = cb.createQuery(Connection.class); 
    Root<Connection> c = q.from(Connection.class); 
    Join<Connection, ConnectionGroup> join = c.join(Connection_.connectionGroups); 
    q.select(c); 

    c.fetch(Connection_.connectionGroups).fetch(ConnectionGroup_.id); 
    Predicate groupPredicate = cb.equal(
    c.get(Connection_.connectionGroups), "%" + groupFilter + "%"); 
    q.where(groupPredicate); 

    List<Connection> results = em.createQuery(q).setFirstResult(start) 
      .setMaxResults(length).getResultList(); 
    for (Connection conn : results) { 
     logger.info("getconnectionGroups =["+ conn.getConnectionGroups() + "]"); 
     for (ConnectionGroup conngroup : conn.getConnectionGroups()) { 
      logger.info("connectiongroups = [" + conngroup.getName() + "]"); 
     } 
    } 
} 

的事情,我都試過了,改變這個:

Predicate groupPredicate = cb.equal(
    c.get(Connection_.connectionGroups), "%" + groupFilter + "%"); 

這樣:

Predicate groupPredicate = cb.equal(join.get(ConnectionGroup_.name), 
      "%" + groupFilter + "%"); 

更改此:

Join<Connection, ConnectionGroup> join = c 
      .join(Connection_.connectionGroups); 

對此:

Join<Connection, ConnectionGroup> join = c.join("connectionGroups"); 

當我嘗試這些方法,我不斷收到一個例外Cannot join to attribute of basic type

我也試圖改變代碼到這個:

CriteriaBuilder cb = em.getCriteriaBuilder(); 
CriteriaQuery<Connection> q = cb.createQuery(Connection.class); 
Root<Connection> c = q.from(Connection.class); 
Join<Connection, ConnectionGroup> join = (Join<Connection, ConnectionGroup>) c.fetch(Connection_.connectionGroups); 
q.select(c); 

Predicate groupPredicate = cb.equal(join.get(ConnectionGroup_.name), "%" + groupFilter + "%"); 
q.where(groupPredicate); 
List<Connection> results = em.createQuery(q).setFirstResult(start) 
      .setMaxResults(length).getResultList(); 

它會返回一個例外:

query specified join fetching, but the owner of the fetched association was not present in the select list

我使用這些網站作爲參考編寫鱈魚E:

JPA CriteriaBuilder using fetch joins and result objects

JPA 2 Criteria Fetch Path Navigation

wiki.eclipse.org

developer.com

我如何可以查詢從ConnectionGroup表的名字嗎?我的方法錯了嗎?

+2

在JPA表之間的關係被稱爲關係,'@ OneToMany'和它的朋友。爲了更快提供更好的幫助,請說明這些關係是如何定義的。 – perissf

回答

1

如果您想通過字符串匹配使用名稱過濾,CriteriaBuilder.like()比CriteriaBuilder.equal()更適合使用。

要實現您要查詢的內容,您可以使用ff。JP QL查詢:

SELECT DISTINCT conn FROM Connection conn JOIN conn.connectionGroups connGrp 
WHERE connGrp.name LIKE :groupFilter 

翻譯JP QL到CriteriaQuery中,你必須:

CriteriaBuilder cb = em.getCriteriaBuilder(); 
CriteriaQuery<Connection> q = cb.createQuery(Connection.class); 
Root<Connection> conn = q.from(Connection.class); 
Join<Connection, ConnectionGroup> connGrp = conn.join(Connection_.connectionGroups); 
q.select(conn).distinct(true); 
ParameterExpression<String> param = cb.parameter(String.class, "%"+ groupFilter + "%"); 
q.where(cb.like(connGrp.get(ConnectionGroup_name), param)); 
相關問題