[英]Criteria API with Unidirectional relationship
我有三個實體。 我需要構建標准 API 如果唯一用戶將超過 userCount 變量,我可以在其中進行 select 項目。
@Entity
@Table(name = "client")
public class Client {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Getter @Setter private Long id;
}
@Entity
@Table(name = "session")
public class Session {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Getter @Setter private Long id;
@ManyToOne
@JoinColumn(name = "client_id", referencedColumnName = "id")
@Getter @Setter private Client client;
@ManyToOne
@JoinColumn(name = "project_id", referencedColumnName = "id")
@Getter @Setter private Project project;
}
@Entity
@Table(name = "project")
public class Project {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Getter @Setter private Long id;
}
我想要 select 所有項目,其中唯一用戶> = userCount。 我在 jpql 中構造查詢
@Query("select p from Project p where (select distinct count(cli.id) from Client as cli
join Session sess on sess.client = cli
join Project as proj on proj = sess.project
where proj.id = p.id) >= :userCount")
我寫了標准:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Project> cq = cb.createQuery(Project.class);
Root<Project> projectRoot = cq.from(Project.class);
List<Predicate> predicates = new ArrayList<>();
Subquery<Long> sub = cq.subquery(Long.class);
Root<Client> subRoot = sub.from(Client.class);
Join<Client, Session> sessionClientJoin = subRoot.join("sessions");
Join<Session, Project> sessionProjectJoin = sessionClientJoin.join("project");
sub.select(cb.count(subRoot.get("id"))).distinct(true);
sub.where(cb.equal(projectRoot.get("id"), sessionProjectJoin.get("id")));
predicates.add(cb.greaterThanOrEqualTo(sub, DefaultParamsHolder.NUMBER_OF_USERS));
cq.select(projectRoot);
cq.where(predicates.toArray(new Predicate[0]));
List<Project> project = em.createQuery(cq).getResultList();
這工作正常,但此標准需要客戶端 class 中的會話。
@Entity
@Table(name = "client")
public class Client {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Getter @Setter private Long id;
@OneToMany(mappedBy = "client", fetch = FetchType.LAZY)
private List<Session> sessions;
}
這對我很不利。 我需要在客戶端 class 中構建沒有會話的標准 API。 我試過這個:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Project> cq = cb.createQuery(Project.class);
Root<Project> projectRoot = cq.from(Project.class);
List<Predicate> predicates = new ArrayList<>();
Subquery<Long> sub = cq.subquery(Long.class);
Root<Client> subRoot = sub.from(Client.class);
Join<Session, Client> sessionClientJoin = subRoot.join("client");
Join<Session, Project> sessionProjectJoin = sessionClientJoin.join("project");
sub.select(cb.count(subRoot.get("id"))).distinct(true);
sub.where(cb.equal(projectRoot.get("id"), sessionProjectJoin.get("id")));
predicates.add(cb.greaterThanOrEqualTo(sub, DefaultParamsHolder.NUMBER_OF_USERS));
cq.select(projectRoot);
cq.where(predicates.toArray(new Predicate[0]));
List<Project> project = em.createQuery(cq).getResultList();
這行不通。
java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [client] on this ManagedType [com.engage.domain.model.statisctic.Client]
如果沒有客戶端 class 中的會話,我怎么能做到這一點?
你有
Root<Client> subRoot = sub.from(Client.class);
Join<Session, Client> sessionClientJoin = subRoot.join("client");
此連接表示“加入綁定到客戶端屬性的客戶端 class 實體”。 Client
沒有屬性client
- 這就是錯誤所說的。
也許您想加入與客戶的會話
Join<Client, Session> sessionClientJoin = subRoot.join("sessions");
我的建議是開始使用 static 生成的元模型。 這將保證編譯時屬性的有效性和類型安全。
https://www.baeldung.com/hibernate-criteria-queries-metamodel
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.