繁体   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