gpt4 book ai didi

JPA:根据多个子实体的多个标准选择实体

转载 作者:行者123 更新时间:2023-12-04 11:52:54 25 4
gpt4 key购买 nike

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

现在我想选择所有已根据一系列分组标准完成测试的学生。例如,我想搜索所有具有以下条件的学生:

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

和/或

第 2 组:完成“测试 2”并获得“50 到 80 分之间”的分数

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

SELECT s FROM Student s JOIN s.tests t WHERE t.score BETWEEN :minScore AND :maxScore AND t.testName = :testName

有没有办法使用单个 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());
}
}
}

最佳答案

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

尝试这样的事情(代码未测试):

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();

关于JPA:根据多个子实体的多个标准选择实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8883311/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com