Issue
I am having 2 entities namely Project
and File
in SpringBoot. The structure of those entity is as given below.
@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;
}
Now when I am creating an object of Project
entity, saving it in database and fetching it again from the database using the Repository and trying to use equals
method it is returning false
.
When I checked individually for each attribute it was failing for the List<File> files
which is present in the Project
. But it is understandable that it will fail because the equals
method of File
class will only return true
if each of it's data member will satisfy equals
but as the File
have a reference to Project
, it will fail.
So this is kind of creating a loop.
If I override the equals
method of Project
to as given below, it works, but at the cost of neglecting the 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);
}
How to solve this problem taking into consideration of the list of files as well?
Solution
I would say you could revisit your design. Often developers create circular dependencies with Entities(or Documents) when it is not required.
I assume your business case is one of the below:
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.
For case C ONLY: You should be prefering a circular dependency and that too ONLY if business needs it.
For case A and case B: You have an aggregate here, a project with a list of files associated with it, (or files with project).
"Aggregate" is a pattern in Domain Driven Design, where these two objects essentially can be treated as a single unit.
Also, when we think in that perspective, there needs to be just one repo as well for these Documents (aggregate).
You can check out this talk from Pivotal for more on aggregates : Talk on Aggregate and Spring Data JPA, from Pivotal
Answered By - Cozimetzer
Answer Checked By - Dawn Plyler (JavaFixing Volunteer)