使用查询构建器

时间:2015-10-06 02:49:20

标签: java jpa criteria-api criteriaquery

我有一个几行变量的表。其中一行指向另一个包含更多行的表。

说清楚,1表叫做Connection。变量是:

name, groupname, etc.

groupname应链接到名为ConnectionGroup的第二个表。变量是:

name, id.

我的想法是按名称查询ConnectionGroup表。 Connection和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

我正在使用这些网站作为参考来编写代码:

JPA CriteriaBuilder using fetch joins and result objects

JPA 2 Criteria Fetch Path Navigation

wiki.eclipse.org

developer.com

如何从ConnectionGroup表中查询名称?我的方法有误吗?

1 个答案:

答案 0 :(得分: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));