我是 Criteria 的新手,无法理解接下来的事情。
我有彼此之间有连接的实体
用户:
//...fields...
@OneToOne(fetch = FetchType.LAZY, mappedBy = "user")
private Document document;
文档:
//...fields...
@OneToOne(fetch = FetchType.LAZY)
@PrimaryKeyJoinColumn
private User user;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "doc_type_id", nullable = false)
private DocType docType;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "citizenship_id", nullable = false)
private Country country;
文档类型:
//...fields...
@Column(nullable = false, length = 5)
private String code;
国家/地区:
//...fields...
@Column(nullable = false, length = 5)
private String code;
我需要找到包含 docCode (DocType.code) 和 CitizenshipCode (Country.code) 的文档的用户。
道:
//private final EntityManager em;
public List<User> filterUser(UserView userView) {
List<User> userList;
List<Document> documentList;
Long officeId = userView.officeId;
String docCode = userView.docCode;
String citizenshipCode = userView.citizenshipCode;
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<User> userQuery = criteriaBuilder.createQuery(User.class);
Root<User> userRoot = userQuery.from(User.class);
userQuery.select(userRoot);
userQuery.where(criteriaBuilder.equal(userRoot.get("office"), officeId));
//find id of DocType
Long docTypeId = null;
if (docCode != null) {
CriteriaQuery<DocType> docTypeQuery = criteriaBuilder.createQuery(DocType.class);
Root<DocType> docTypeRoot = docTypeQuery.from(DocType.class);
docTypeQuery.select(docTypeRoot);
docTypeQuery.where(criteriaBuilder.equal(docTypeRoot.get("code"), docCode));
docTypeId = em.createQuery(docTypeQuery).getSingleResult().getId();
}
//find id of Country
Long countryId = null;
if (citizenshipCode != null) {
CriteriaQuery<Country> countryQuery = criteriaBuilder.createQuery(Country.class);
Root<Country> countryRoot = countryQuery.from(Country.class);
countryQuery.select(countryRoot);
countryQuery.where(criteriaBuilder.equal(countryRoot.get("code"), citizenshipCode));
countryId = em.createQuery(countryQuery).getSingleResult().getId();
}
if (docTypeId != null || countryId != null) {
CriteriaQuery<Document> documentQuery = criteriaBuilder.createQuery(Document.class);
Root<Document> documentRoot = documentQuery.from(Document.class);
documentQuery.select(documentRoot);
if (docTypeId != null) {
//filter for Document which contains docTypeId
documentQuery.where(criteriaBuilder.equal(documentRoot.get("docType"), docTypeId));
}
if (countryId != null) {
//filter for which contains countryId
documentQuery.where(criteriaBuilder.equal(documentRoot.get("country"), countryId));
}
documentList = em.createQuery(documentQuery).getResultList();
List<Integer> idDocuments = new ArrayList<>();
//find all of required documents
documentList.stream().forEach((d) -> idDocuments.add(Math.toIntExact(d.getId())));
userQuery.where(userRoot.get("document").in(idDocuments));
}
userList = em.createQuery(userQuery).getResultList();
return userList;
}
我对这些行很感兴趣
userQuery.where(criteriaBuilder.equal(userRoot.get("office"), officeId));
和
userQuery.where(userRoot.get("document").in(idDocuments));
为什么第一行的过滤器不执行?
我知道有嵌套子查询,但我无法正确理解。
最佳答案
我不知道您想用“Office”做什么,但您不应该将不属于问题一部分的内容放入帖子中。 @PrimaryKeyJoinColumn
给您带来了问题,它导致 user_id
被排除在 Document
之外。
@Entity
public class User {
@Id @GeneratedValue private int id;
@OneToOne(fetch = FetchType.LAZY, mappedBy = "user")
private Document document;
@Entity
public class Document {
@Id @GeneratedValue private int id;
@OneToOne(fetch = FetchType.LAZY)
private User user;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "doc_type_id", nullable = false)
private DocType docType;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "citizenship_id", nullable = false)
private Country country;
@Entity
public class DocType {
@Id @GeneratedValue private int id;
@Column(nullable = false, length = 5)
private String code;
@Entity
public class Country {
@Id @GeneratedValue private int id;
@Column(nullable = false, length = 5)
private String code;
并使用它:
tx.begin();
DocType docType = new DocType();
docType.setCode("TYPE");
em.persist(docType);
Country country = new Country();
country.setCode("US");
em.persist(country);
User user = new User();
em.persist(user);
Document document = new Document();
document.setCountry(country);
document.setDocType(docType);
document.setUser(user);
em.persist(document);
tx.commit();
em.clear();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<User> q = cb.createQuery(User.class);
Root<User> userRoot = q.distinct(true).from(User.class);
Join<User, Document> docJoin = userRoot.join("document");
Join<Document, DocType> docTypeJoin = docJoin.join("docType");
Join<Document, Country> countryJoin = docJoin.join("country");
q.where(cb.and(
cb.equal(countryJoin.get("code"), "US"),
cb.equal(docTypeJoin.get("code"), "TYPE")
));
List<User> users = em.createQuery(q).getResultList();
System.out.println(users);
关于java - Criteria API 查询失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51583823/