[英]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
,以便projects
與users
一起獲取。
所以,首先,實體是這樣的:
@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.