簡體   English   中英

JPA 條件:處理實體上左連接的 QuerySyntaxException

[英]JPA Criteria: QuerySyntaxException for left join on treat entity

Model:

@Entity
public class User {

    @Id
    private Integer id;

    @JoinColumn(name = "user_id")
    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Project> projects;
}
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "Type")
public abstract class Project {

    @Id
    private Integer id;

    private String name;
}
@Entity
@DiscriminatorValue("Administrative")
public class AdminProject extends Project {

    private String departmentName;
}
@Entity
@DiscriminatorValue("Design")
public class DesignProject extends Project {

    private String companyName;
}

我正在嘗試使用 JPA 的標准 api 根據Project實現的屬性來查詢User實體。 例如,查詢具有“SOME_NAME”部門的項目的所有用戶(該字段在DesignProject上不存在)。

我看到有一種方法可以通過向下轉換查詢的Project實體來做到這一點。 我正在嘗試類似的東西:

CriteriaBuilder cb...
Root<User> userRoot...
root = ((From) root).join("projects", JoinType.LEFT);
root = cb.treat(root, AdminProject.class);
root = root.get("departmentName");

例外:

org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: 'generatedAlias2.departmentName' [select generatedAlias0 from io.github.perplexhub.rsql.model.User as generatedAlias0 left join generatedAlias0.projects as generatedAlias1 where Treat(generatedAlias2 as io.github.perplexhub.rsql.model.AdminProject);parampart).depart)。 nested exception is java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: 'generatedAlias2.departmentName' [select generatedAlias0 from io.github.perplexhub.rsql.model.User as generatedAlias0 left join generatedAlias0.項目作為 generatedAlias1 where Treat(generatedAlias2 as io.github.perplexhub.rsql.model0.AdminProject).dempart)。

我錯過了什么? 是否與加入有關,或者之后如何發生向下轉換?

編輯

在@K.Nicholas 的回答之后,我設法使查詢在一個孤立的場景中工作,但不是在我的應用程序上。 但是,我注意到entityManager.createQuery(query)調用在第一次調用時會引發上述異常,如果我再次調用它而不更改查詢 object,它會起作用。 這是第二次調用時生成的查詢(此查詢從數據庫中找到我想要的對象):

select generatedAlias0 from User as generatedAlias0 left join generatedAlias0.projects as generatedAlias2 where treat(generatedAlias2 as io.github.perplexhub.rsql.model.AdminProject).departmentName=:param0

為什么實體管理器在連續兩次調用時會創建兩個不同的查詢?

正如你將看到的,我會做一些不同的Entitys 主要問題是您使用User作為您的根並加入到Projects列表中。 這是一個問題,因為您應該在Project class 上擁有外鍵,並將projects字段用作僅查詢字段。 這就是我所做的。 這樣效果更好。 這也是一個問題,因為您必須執行join fetch而不是join ,以便projectsusers一起獲取。

所以,首先,實體是這樣的:

@Entity
public class User { 
    @Id
    private Integer id; 
    @OneToMany(mappedBy="user")
    private List<Project> projects;
}

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "Type")
public abstract class Project {
    @Id
    private Integer id;
    private String name;    
    @ManyToOne
    private User user;
}

@Entity
@DiscriminatorValue("Administrative")
public class AdminProject extends Project {
    private String departmentName;
}

@Entity
@DiscriminatorValue("Design")
public class DesignProject extends Project {    
    private String companyName;
}

經過一番挖掘,我發現了一個可以解決問題的 JPQL 查詢。 這是一個起點:

List<User> users = entityManager.createQuery("select distinct(u) from User u join fetch u.projects p where TYPE(p) = 'Administrative' and p.departmentName = 'dept1'", User.class).getResultList();

經過一番挖掘后,我發現如果你做得正確,那么treat效果很好,並且使用 JPA 2.1 你應該使用EntityGraph來獲取join來進行fetch

CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<User> query = builder.createQuery(User.class);
Root<User> root = query.from(User.class);
Join<User, Project> join = root.join("projects");
query.select(root).where(builder.equal(builder.treat(join, AdminProject.class).get("departmentName"), "dept1"));
EntityGraph<User> fetchGraph = entityManager.createEntityGraph(User.class);
fetchGraph.addSubgraph("projects");
users = entityManager.createQuery(query.distinct(true)).setHint("javax.persistence.loadgraph", fetchGraph).getResultList();

作為旁注,生成的查詢略有不同,但我沒有仔細觀察它們。 你應該。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM