gpt4 book ai didi

java - 延迟加载数据表使用 FetchType.EAGER 显示重复结果

转载 作者:太空宇宙 更新时间:2023-11-04 07:16:12 25 4
gpt4 key购买 nike

我知道对此有很多疑问,但没有一个解决方案对我有帮助。

我正在使用 PrimeFaces 构建延迟加载数据表。这意味着这个数据表列表是一个 LazyDataModel 列表,我必须开发一个 LazyDataModel 实现,在其中重写 load 方法。这一切都可以从PrimeFaces showcase了解到,并且当数据表仅使用数据库中的一张表时(这不是我的情况),它在大多数情况下都可以正常工作。

现在,我有两个实体:

@Entity
@Table(name="UNIVERSITY")
public class University {

@Id
@Column(name="ID_UNIVERSITY")
@GeneratedValue(strategy = GenerationType.AUTO ,generator="SQ_UNIVERSITY")
@SequenceGenerator(name="SQ_UNIVERSITY", sequenceName="SQ_UNIVERSITY")
private Long idUniversity;

@Column(name="NAME")
private String name;

@ManyToOne
@JoinColumn(name="ID_DIRECTOR")
private Director director;

@OneToMany(fetch=FetchType.EAGER, mappedBy = "university")
private Set<Students> students = new HashSet<Students>(0);

...

public int getStudentsQty(){
return this.students.size();
}

...

我将使用 getStudentsQty() 方法填充数据表中的一列。这是学生实体:

@Entity
@Table(name="STUDENTS")
public class Students
{

@Id
@Column(name="ID_STUDENTS")
@GeneratedValue(strategy = GenerationType.AUTO ,generator="SQ_STUDENTS")
@SequenceGenerator(name="SQ_STUDENTS", sequenceName="SQ_STUDENTS")
private Long idStudent;

@ManyToOne
@JoinColumn(name="ID_UNIVERSITY")
private University student;

@Column(name="NAME")
private String name;

...

这是我的加载实现将使用的搜索方法:

public List<University> find(int startingAt, int maxPerPage,
final String sortField, final SortOrder sortOrder, Map<String, String> filters) {

session = HibernateUtil.getSession();
Criteria criteria =session.createCriteria(University.class);

List<String> aliases = new ArrayList<String>();

if(maxPerPage > 0){
criteria.setMaxResults(maxPerPage);
}

criteria.setFirstResult(startingAt);

addFiltersToCriteria(filters, criteria, aliases);

Order order = Order.desc("name");

if(sortField != null && !sortField.isEmpty()){

if(sortField.contains(".")){
String first = (sortField.split("\\."))[0];
if(!aliases.contains(first)){
criteria.createAlias(first, first);
aliases.add(first);
}
}

if(sortOrder.equals(SortOrder.ASCENDING)){
order = Order.asc(sortField);
}
else if(sortOrder.equals(SortOrder.DESCENDING)){
order = Order.desc(sortField);
}
}
criteria.addOrder(order);

return (List<University>) criteria.list();
}

现在,我的问题来了。如果我使用FetchType.LAZY,一切正常,但性能很糟糕,所以我希望使用EAGER。如果我使用 EAGER ,结果将按预期重复并解释 here 。我尝试在 University 实体中实现 equals()hashCode() 方法,以按照上一个链接中的建议使用 LinkedHashSet,但它不起作用,我不知道如何。我还尝试将 DISTINCTCriteria 一起使用,但它不起作用,因为我使用了 addOrder,它要求加入。

所以,我找到了this other suggestion效果很好。基本上,解决方案是执行第二个 Criteria 查询,仅搜索 ID 包含在原始搜索中的大学。像这样:

private List<University> removeDuplicates(Order order,
List<University> universities) {

Criteria criteria;
List<University> distinct = null;

if(universities.size() > 0){

Set<Long> idlist = new HashSet<Long>();

for(University univ: universities){
idlist.add(univ.getIdUniversity());
}

criteria = session.createCriteria(University.class);
criteria.add(Restrictions.in("id", idlist)) ;

distinct = (List<University>) criteria.list();

return distinct;
}
else{
return universities;
}
}

因此,它将为我的延迟加载分页数据表带来前 100 行。在第一个 Criteria 搜索中,它们将在第一页进行排序,并且在第二个 Criteria 搜索后将出现相同的 100 个正确行,但现在它们将是未排序。这是第一页的正确行,但在第一页内未排序。我不能在第二个 Criteria 中使用“addOder”,否则它们会重复。

最奇怪的事情是:如果我尝试使用Collections.sort对结果进行排序,结果将会重复!如何??我到底该如何订购我的结果?

谢谢!!

编辑:学生计数只是一个示例,我需要在其他场景中获取每个关联实体内的信息。

最佳答案

如果我理解正确的话,您正在输出一个列出大学的表格,并且您想显示每所大学的学生人数。如果是这样,仅仅为了获得计数而将 x000 个学生记录加载到内存中是疯狂的(无论您是急切还是懒惰地这样做)。

尝试以下方法之一:

一个

不要加载关联的学生来获取计数,而是使用 Hibernates @Formula 功能并向您的大学实体添加派生属性。

@Formula(value = "select count(*) from students where university_id = ?")
private int studentCount;

两个

创建一个数据库 View ,例如university_summary_data,其中包含此计数,并创建映射到此 View 的实体(就像表一样工作),然后在大学中:

@OneToOne
private UniversitySummaryData data;

研究 Hibernate 的 @LazyCollection(LazyCollectionOption.EXTRA),它允许您在映射集合上调用 size(),而无需加载所有学生。

所有比您拥有的更简单的解决方案。

关于java - 延迟加载数据表使用 FetchType.EAGER 显示重复结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19936450/

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