如何检查包含列表作为数据成员的 2 个对象是否相等?
How to check if 2 objects that contains list as a data member equal or not?
我在 SpringBoot 中有 2 个实体,即 Project
和 File
。这些实体的结构如下所示。
@Document(collection="project")
public class Project{
@Id
private String id;
@Field("name")
private String name;
@Field("files")
@DBRef
@JsonIgnore
private List<File> files;
}
@Document(collection="file")
public class File{
@Id
private String id;
@Field("name")
private String name;
@Field("project")
@DBRef
private Project project;
}
现在,当我创建 Project
实体的对象时,将其保存在数据库中并使用存储库从数据库中再次获取它并尝试使用 equals
方法,它是 returning false
。
当我单独检查每个属性时,Project
中存在的 List<File> files
失败。但它会失败是可以理解的,因为 File
class 的 equals
方法只会 return true
如果它的每个数据成员都满足 equals
但由于 File
引用了 Project
,它将失败。
所以这是一种循环。
如果我将 Project
的 equals
方法重写为如下所示,它会起作用,但代价是忽略 List<File> file
.
@Override
public boolean equals(Object obj) {
if(obj == null)
return false;
if(!(obj instanceof Project))
return false;
if(this == obj)
return true;
Project that = (Project) obj;
return
this.id.equals(that.id) &&
this.name.equals(that.name);
}
如何同时考虑文件列表来解决这个问题?
您可以重写 equals 方法,并通过在不同的方法中匹配列表对象的 ID 来检查列表的相等性。或者您可以使用 containsAll() 来检查列表元素是否相等。这不是一个完美的解决方案,但仍然会检查列表元素而不是完全忽略它们。
同时检查循环依赖并尝试以不同的方式构建这些实体:
尝试在文件中只保存 Project.id。我假设您需要它仅供参考。比较用例,您需要多久从文件中查找项目或从项目中查找文件并相应地保存。
我会说你可以重新审视你的设计。
开发人员经常在不需要时创建与实体(或文档)的循环依赖关系。
我假设您的业务案例是以下之一:
A) Files are always associated to a Project (there are no files
without a project association)
B) All Projects contain atleast one File (there are no projects
without atleast one file)
C) There can be projects without files or files without a project
associated to it.
仅对于案例 C:
您应该更喜欢循环依赖,并且只有在业务需要时才使用循环依赖。
对于案例 A 和案例 B:
你在这里有一个聚合,一个项目和一个与之关联的文件列表,(或带有项目的文件)。
"Aggregate" is a pattern in Domain Driven Design, where these two
objects essentially can be treated as a single unit.
此外,当我们从这个角度考虑时,这些文档(汇总)也只需要一个回购协议。
您可以查看来自 Pivotal 的演讲以了解更多关于聚合的信息:Talk on Aggregate and Spring Data JPA, from Pivotal
我在 SpringBoot 中有 2 个实体,即 Project
和 File
。这些实体的结构如下所示。
@Document(collection="project")
public class Project{
@Id
private String id;
@Field("name")
private String name;
@Field("files")
@DBRef
@JsonIgnore
private List<File> files;
}
@Document(collection="file")
public class File{
@Id
private String id;
@Field("name")
private String name;
@Field("project")
@DBRef
private Project project;
}
现在,当我创建 Project
实体的对象时,将其保存在数据库中并使用存储库从数据库中再次获取它并尝试使用 equals
方法,它是 returning false
。
当我单独检查每个属性时,Project
中存在的 List<File> files
失败。但它会失败是可以理解的,因为 File
class 的 equals
方法只会 return true
如果它的每个数据成员都满足 equals
但由于 File
引用了 Project
,它将失败。
所以这是一种循环。
如果我将 Project
的 equals
方法重写为如下所示,它会起作用,但代价是忽略 List<File> file
.
@Override
public boolean equals(Object obj) {
if(obj == null)
return false;
if(!(obj instanceof Project))
return false;
if(this == obj)
return true;
Project that = (Project) obj;
return
this.id.equals(that.id) &&
this.name.equals(that.name);
}
如何同时考虑文件列表来解决这个问题?
您可以重写 equals 方法,并通过在不同的方法中匹配列表对象的 ID 来检查列表的相等性。或者您可以使用 containsAll() 来检查列表元素是否相等。这不是一个完美的解决方案,但仍然会检查列表元素而不是完全忽略它们。
同时检查循环依赖并尝试以不同的方式构建这些实体:
尝试在文件中只保存 Project.id。我假设您需要它仅供参考。比较用例,您需要多久从文件中查找项目或从项目中查找文件并相应地保存。
我会说你可以重新审视你的设计。 开发人员经常在不需要时创建与实体(或文档)的循环依赖关系。
我假设您的业务案例是以下之一:
A) Files are always associated to a Project (there are no files without a project association)
B) All Projects contain atleast one File (there are no projects without atleast one file)
C) There can be projects without files or files without a project associated to it.
仅对于案例 C: 您应该更喜欢循环依赖,并且只有在业务需要时才使用循环依赖。
对于案例 A 和案例 B: 你在这里有一个聚合,一个项目和一个与之关联的文件列表,(或带有项目的文件)。
"Aggregate" is a pattern in Domain Driven Design, where these two objects essentially can be treated as a single unit.
此外,当我们从这个角度考虑时,这些文档(汇总)也只需要一个回购协议。
您可以查看来自 Pivotal 的演讲以了解更多关于聚合的信息:Talk on Aggregate and Spring Data JPA, from Pivotal