Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JPA:基于多个子实体上的多个标准选择实体_Jpa_Jpa 2.0_Eclipselink - Fatal编程技术网

JPA:基于多个子实体上的多个标准选择实体

JPA:基于多个子实体上的多个标准选择实体,jpa,jpa-2.0,eclipselink,Jpa,Jpa 2.0,Eclipselink,我在实现以下场景时遇到问题。学生可以参加考试。随着时间的推移,一名学生参加了几次考试,每次考试都得到了分数。每个学生实体都有一个他们已完成的测试列表,映射为@OneToMany 现在我想选择所有完成了一系列分组标准测试的学生。例如,我希望搜索具有以下特征的所有学生: 第一组:完成“测试1”并获得“75到100”的分数 和/或 第二组:完成“测试2”,得分在“50到80”之间 这是我到目前为止所拥有的,但它不满足我的需要(无法通过多个参数进行搜索,这意味着我必须多次执行查询): 有没有一种方法可以

我在实现以下场景时遇到问题。学生可以参加考试。随着时间的推移,一名学生参加了几次考试,每次考试都得到了分数。每个学生实体都有一个他们已完成的测试列表,映射为@OneToMany

现在我想选择所有完成了一系列分组标准测试的学生。例如,我希望搜索具有以下特征的所有学生:

第一组:完成“测试1”并获得“75到100”的分数

和/或

第二组:完成“测试2”,得分在“50到80”之间

这是我到目前为止所拥有的,但它不满足我的需要(无法通过多个参数进行搜索,这意味着我必须多次执行查询):

有没有一种方法可以使用单个NamedQuery来实现我想要的?要检索完成至少与上述一个参数组匹配的测试的所有学生?我一直在尝试连接,但一直碰壁

我在下面制作了一个示例代码框架来说明我要做的事情

@Entity
@NamedQueries({
    @NamedQuery(name="Student.findStudentByParams", query="????????") // What should this query look like to satisfy the criteria? (see below for more detail)
})
public class Student {
    // .. Some other variables that are not relevant for this example

    @Id
    private String name;

    @OneToMany(fetch=FetchType.EAGER, mappedBy = "student")
    private List<Test> tests;

    // Setters and getters
}

@Entity
public class Test {
    private double score;
    private String testName;
    // .. Some other variables that are not relevant for this example

    @ManyToOne(cascade=CascadeType.ALL)
    private Student student;

    // Setters and getters
}

public class SearchParameters {
    private double minScore;
    private double maxScore;
    private String testName; 

    public SearchParameters(String minScore, String maxScore, String testName) {
        this.minScore = minScore;
        this.maxScore = maxScore;
        this.testName = testName;
    }

    // Setters and getters
}

public class MainClass {
    public static List<Student> getStudents(List<SearchParameters> searchParams) {

        // Database initialization stuff

        // What should the query look like to find all students that match any of the combined requirements in the searchParams list? 
        // Is it possible to do in a single query or should i make multiple ones?
        // What parameters should i set? Is it possible to put in the entire array and do some sort of join?

        // Retrieve all students which matches any of these search parameters:
        // Have either:
        //      Completed "Test 1" and got a score between 75 and 100
        // and/or:
        //      Completed "Test 2" and got a score between 50 and 80
        Query namedQuery = em.createNamedQuery("Student.findStudentByParams");
        namedQuery.setParameter(??); 

        return (List<Student>)namedQuery.getResultList();

    }
    public static void main() {
        List<SearchParams> searchParams = new ArrayList<SearchParams();
        searchParams.add(new SearchParameters(75,100, "Test 1"));
        searchParams.add(new SearchParameters(50,80, "Test 2"));

        // Retrieve all students which matches any of these search parameters:
        // Have either:
        //      Completed "Test 1" and got a score between 75 and 100
        // and/or:
        //      Completed "Test 2" and got a score between 50 and 80
        ArrayList<Student> students = getStudents(searchParams);
        for(Student s: students) // Print all user that match the criteria
        {
            System.out.println("Name: " + s.getName());
        }
    }   
}
@实体
@命名查询({
@NamedQuery(name=“Student.findStudentByParams”,query=“???????”//此查询应该是什么样子才能满足条件?(有关详细信息,请参阅下文)
})
公立班学生{
//…一些与本例无关的其他变量
@身份证
私有字符串名称;
@OneToMany(fetch=FetchType.EAGER,mappedBy=“student”)
私人列表测试;
//二传手和接球手
}
@实体
公开课考试{
私人双积分;
私有字符串testName;
//…一些与本例无关的其他变量
@多通(级联=级联类型.ALL)
私立学生;
//二传手和接球手
}
公共类搜索参数{
私人双核心;
私人双倍最大分数;
私有字符串testName;
公共搜索参数(字符串minScore、字符串maxScore、字符串testName){
this.minScore=minScore;
this.maxScore=maxScore;
this.testName=testName;
}
//二传手和接球手
}
公共类主类{
公共静态列表getStudents(列表搜索参数){
//数据库初始化的东西
//要在searchParams列表中找到符合任何组合要求的所有学生,查询应该是什么样子的?
//可以在一个查询中执行,还是应该执行多个查询?
//我应该设置哪些参数?是否可以放入整个数组并进行某种连接?
//检索与以下任何搜索参数匹配的所有学生:
//有:
//完成“测试1”,得分在75到100分之间
//和/或:
//完成“测试2”,得分在50到80分之间
Query namedQuery=em.createNamedQuery(“Student.findStudentByParams”);
namedQuery.setParameter(??);
返回(列表)namedQuery.getResultList();
}
公共静态void main(){

列表SalePARAMS = NealAljList< P>我不知道如何在不动态地组成查询的情况下是可能的。请考虑使用标准API来创建它。 我会这样设计查询:

select s from Student s where
    exists (select t.id from Test t where t.student.id = s.id and ...)
or
    exists (select t.id from Test t where t.student.id = s.id and ...)
or
    exists (...)

如您所见,有一个重复模式,所有这些子查询都是类似的,它们组合成一个析取。

您需要使用Criteria Builder(以及最终的规范元模型)

尝试类似的方法(未测试代码):

EntityManager em;//将EntityManager实例放在这里
CriteriaBuilder cb=em.getCriteriaBuilder();
CriteriaQuery cq=cb.createQuery(Student.class);
Root student=cq.from(student.class);
谓词=cb.析取();
for(SearchParams参数:SearchParams){
ListJoin测试=student.join(student.tests);
谓词tempPredicate1=cb.equal(tests.get(Test.testName),param.getTestName());
谓词tempPredicate2=cb.ge(tests.get(Test.score),param.getMinScore());
谓词tempPredicate3=cb.le(tests.get(Test.score),param.getMaxScore());
谓词tempredicate=cb.and(tempredicate1、tempredicate2、tempredicate3);
谓词=cb.or(谓词,临时谓词);
}
cq.where(谓词);
TypedQuery tq=em.createQuery(cq);
返回tq.getResultList();

看看Criteria Query builder。您可以构建一个谓词数组:感谢代码示例,它似乎符合我的要求。
select s from Student s where
    exists (select t.id from Test t where t.student.id = s.id and ...)
or
    exists (select t.id from Test t where t.student.id = s.id and ...)
or
    exists (...)
EntityManager em;    // put here your EntityManager instance
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Student> cq = cb.createQuery(Student.class);
Root<Student> student = cq.from(Student.class);
Predicate predicate = cb.disjunction();
for (SearchParams param : searchParams) {
    ListJoin<Student, Test> tests = student.join(Student_.tests);
    Predicate tempPredicate1 = cb.equal(tests.get(Test_.testName), param.getTestName());
    Predicate tempPredicate2 = cb.ge(tests.get(Test_.score), param.getMinScore());
    Predicate tempPredicate3 = cb.le(tests.get(Test_.score), param.getMaxScore());
    Predicate tempPredicate = cb.and(tempPredicate1, tempPredicate2, tempPredicate3);
    predicate = cb.or(predicate, tempPredicate);
}
cq.where(predicate);
TypedQuery<Student> tq = em.createQuery(cq);
return tq.getResultList();