如何使用CriteriaBuilder API进行链式连接

时间:2018-09-19 14:59:35

标签: java sql hibernate jpa join

我得到了这个SQL查询,并且可以正常工作(在数据库上进行了测试,结果符合预期)

select n.name, s.id, pn.name
from structure s
     join node n on n.id = s.node_id                      
     left join structure ps on ps.id = s.parent_id        
     left join node pn on pn.id = ps.node_id 

如何使用条件构建器API重新创建此查询? 我想不明白.. 类是:

class node {
  String id;
  String name;
}

class Structure {
  String id;
  Node node;
  String parentId; // Structure id
}

我可以像这样从结构到节点进行连接

Root<Structure> structureRoot = criteriaQuery.from(Structure.class);
Join<Structure, Node> firstJoin = structureRoot.join("node");

这使我从Structure转到Node,如何使用此第一个联接将其作为String parentId(而不是关系)联接回Structure上的父结构?

编辑


在结构之间建立关系时 课程已更新:

class node {
  String id;
  String name;
}

class Structure {
  String id;
  @ManyToOne
  @JoinColumn(name = "node_id")
  Node node;
  @ManyToOne
  @JoinColumn(name = "parent_id")
  Structure parent;
}

我收到此错误:

o.h.engine.jdbc.spi.SqlExceptionHelper   : Column "STRUCTURE2_.ID" not 
found; SQL statement:
select structure0_.id as col_0_0_, node3_.name as col_1_0_, 
structure0_.id as id1_2_, structure0_.node_id as node_id3_2_, 
structure0_.parent_id as parent_i4_2_, structure0_.source_id as 
source_i2_2_ from structure structure0_ inner join node node4_ on 
structure0_.node_id=node4_.id and (node1_.id=structure0_.node_id) left 
outer join structure structure5_ on 
structure0_.parent_id=structure5_.id and 
(structure2_.id=structure0_.parent_id) left outer join node node6_ on 
structure0_.node_id=node6_.id and (node3_.id=structure2_.node_id) 
cross 
join node node1_ cross join structure structure2_ cross join node 
node3_ where lower(node1_.name) like ? order by node1_.name desc limit 
? [42122-197]
2018-09-20 12:13:49.447 ERROR 4599 --- [           main] c . 
.t.assets.service.SortToOrderMapper     : 
org.hibernate.exception.SQLGrammarException: could not prepare 
statement

如果我运行此查询:

CriteriaQuery<Object[]> criteriaQuery = 
criteriaBuilder.createQuery(Object[].class);
Root<Structure> s = criteriaQuery.from(Structure.class);
Root<Node> n = criteriaQuery.from(Node.class);
Root<Structure> ps = criteriaQuery.from(Structure.class);
Root<Node> pn = criteriaQuery.from(Node.class);

Join one = s.join("node");
one.on(criteriaBuilder.equal(n.get("id"), s.get("node")));
Join two = ps.join("parent", JoinType.LEFT);
two.on(criteriaBuilder.equal(s.get("parent"),ps.get("id")));
Join three = s.join("node",JoinType.LEFT);
three.on(criteriaBuilder.equal(pn.get("id"),ps.get("node")));

return criteriaQuery.select(criteriaBuilder.array(s,three.get("name"))).where(
            criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()])));

2 个答案:

答案 0 :(得分:0)

parentId类中需要一个Structure字段来代表父结构,而不是字符串Structure

class Structure {
    String id;
    Node node;
    @ManyToOne
    @JoinColumn(name = "parent_id", nullable = true)
    Structure parentStructure;
}

然后,您可以这样编写条件查询:

Root<Structure> structureRoot = criteriaQuery.from(Structure.class);
Join<Structure, Node> firstJoin = structureRoot.join("node");
Join<Structure, Structure> parentJoin = structureRoot.join("parentStructure");
Join<Structure, Node> secondJoin = parentJoin.join("node");

答案 1 :(得分:0)

自从我添加

@ManyToOne
@JoinColumn(name = "parent_id")
private Structure parent;

我不需要进行连接。.我正在做很多事情,同时也在做。清理了我的select子句并删除了联接,它起作用了!