java - Criteria API 查询失败

标签 java spring spring-mvc jpa criteria

我是 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/

相关文章:

Java BMP 头文件

java - Java中与逻辑运算符的字符串比较

java - 未找到 org.springframework.web.servlet.mvc.SimpleFormController

java - 无法使用上下文 :property-placeholder (Spring) 获取属性

java - 在真实的基于 Java 的企业应用程序中,应该在哪一层进行验证?

java - Spring MVC - 应用程序级别的缓存

java - Swagger @ApiParam 注释使在 Swagger UI 中不需要使用 @PathVariable 注释的参数

java - Spring Batch 作业实例已存在

java - 带有引导 : "There was an unexpected error (type=Not Found, status=404)" 的 Spring MVC

java - 单击 jButton 时如何将 jTextField 值从一个类传递到另一个类?