Java 根据不同子对象类型的一对多关系排序
Java Order by on one to many relationship with different child object type
问题
如果 ExamObject
是 ExamTask
,我需要根据 id
对 ExamObjects 进行排序,如果是 ExamQuestion
,我需要根据 questionNumber
对它进行排序.我该怎么做?
重要
一次考试只会有一组ExamTask
或ExamQuestion
。换句话说,一次考试不能混合使用 ExamTask 和 ExamQuestion。
背景信息
我有一个名为 Exam
的实体 class 此 class 可以包含一个或多个 ExamObject
个实体。
@Entity
public class Exam {
@OneToMany(mappedBy = "exam" ...)
@OrderBy("id") //I need to order this by question number if its ExamQuestion
private Set<ExamObject> objects;
...
}
ExamObject
可以是下面两种类型,使用 JOINED
ExamTask
扩展 ExamObject
ExamQuestion
扩展 ExamObject
并有一个名为 questionNumber
的列
ExamObject
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class ExamObject {
@Id
private Long id;
...
ExamTask
@Entity
@PrimaryKeyJoinColumn(name = "id", referencedColumnName = "id")
public class ExamTask extends ExamObject{
...
ExamQuestion
@Entity
@PrimaryKeyJoinColumn(name = "id", referencedColumnName = "id")
public class ExamQuestion extends ExamObject{
@Column(name = "question_number")
private Integer questionNumber;
...
通过将集合声明为 TreeSet
类型并向构造函数提供 Comparator
,插入的项目将自动排序。
new TreeSet<ExamObject>(new Comparator<ExamObject>(){
@Override
public int compare(ExamObject a, ExamObject b){
int q1 = 0, q2 = 0;
if(a instanceof ExamQuestion){
q1 = ((ExamQuestion)a).questionNumber;
if(b instanceof ExamQuestion){
q2 = ((ExamQuestion)b).questionNumber;
}else{
q2 = ((ExamTask)b).id;
}
}else{
q1 = ((ExamTask)a).id;
if(b instanceof ExamQuestion){
q2 = ((ExamQuestion)b).questionNumber;
}else{
q2 = ((ExamTask)b).id;
}
}
if(q1 == q2) return 0;
else return q1 < q2 ? -1 : 1;
}
});
我认为您的问题是您在实体中使用了 Set。 Set 不会维持秩序。当您的关系加载时,集合将不保证插入顺序。尝试改用列表。列表将保持插入顺序。
@Entity
public class Exam {
@OneToMany(mappedBy = "exam" ...)
@OrderBy("id") //I need to order this by question number if its ExamQuestion
private List<ExamObject> objects;
...
}
希望对您有所帮助。
我将 @OrderBy 与 Set 一起使用,效果很好。
@OneToMany(mappedBy = "mailing", fetch = FetchType.LAZY)
@OrderBy("documentPrintOrder ASC")
private Set<MailingDocsEntity> mailingDocs = new HashSet<MailingDocsEntity>();
问题
如果 ExamObject
是 ExamTask
,我需要根据 id
对 ExamObjects 进行排序,如果是 ExamQuestion
,我需要根据 questionNumber
对它进行排序.我该怎么做?
重要
一次考试只会有一组ExamTask
或ExamQuestion
。换句话说,一次考试不能混合使用 ExamTask 和 ExamQuestion。
背景信息
我有一个名为 Exam
的实体 class 此 class 可以包含一个或多个 ExamObject
个实体。
@Entity
public class Exam {
@OneToMany(mappedBy = "exam" ...)
@OrderBy("id") //I need to order this by question number if its ExamQuestion
private Set<ExamObject> objects;
...
}
ExamObject
可以是下面两种类型,使用 JOINED
ExamTask
扩展ExamObject
ExamQuestion
扩展ExamObject
并有一个名为questionNumber
的列
ExamObject
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class ExamObject {
@Id
private Long id;
...
ExamTask
@Entity
@PrimaryKeyJoinColumn(name = "id", referencedColumnName = "id")
public class ExamTask extends ExamObject{
...
ExamQuestion
@Entity
@PrimaryKeyJoinColumn(name = "id", referencedColumnName = "id")
public class ExamQuestion extends ExamObject{
@Column(name = "question_number")
private Integer questionNumber;
...
通过将集合声明为 TreeSet
类型并向构造函数提供 Comparator
,插入的项目将自动排序。
new TreeSet<ExamObject>(new Comparator<ExamObject>(){
@Override
public int compare(ExamObject a, ExamObject b){
int q1 = 0, q2 = 0;
if(a instanceof ExamQuestion){
q1 = ((ExamQuestion)a).questionNumber;
if(b instanceof ExamQuestion){
q2 = ((ExamQuestion)b).questionNumber;
}else{
q2 = ((ExamTask)b).id;
}
}else{
q1 = ((ExamTask)a).id;
if(b instanceof ExamQuestion){
q2 = ((ExamQuestion)b).questionNumber;
}else{
q2 = ((ExamTask)b).id;
}
}
if(q1 == q2) return 0;
else return q1 < q2 ? -1 : 1;
}
});
我认为您的问题是您在实体中使用了 Set。 Set 不会维持秩序。当您的关系加载时,集合将不保证插入顺序。尝试改用列表。列表将保持插入顺序。
@Entity
public class Exam {
@OneToMany(mappedBy = "exam" ...)
@OrderBy("id") //I need to order this by question number if its ExamQuestion
private List<ExamObject> objects;
...
}
希望对您有所帮助。
我将 @OrderBy 与 Set 一起使用,效果很好。
@OneToMany(mappedBy = "mailing", fetch = FetchType.LAZY)
@OrderBy("documentPrintOrder ASC")
private Set<MailingDocsEntity> mailingDocs = new HashSet<MailingDocsEntity>();