I have 3 entity clasess that have relationships on each others
TestClassParent :
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(of = "email")
@Inheritance(strategy = InheritanceType.JOINED)
public class TestClassParent {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String email;
}
TestClassChild :
@Entity
@Data
@EqualsAndHashCode(callSuper = true)
public class TestClassChild extends TestClassParent{
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "test_collection_id")
private TestChildCollection testChildCollection;
}
TestChildCollection :
@Entity
@Data
@EqualsAndHashCode(of ="id")
@AllArgsConstructor
@NoArgsConstructor
public class TestChildCollection {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "testChildCollection",cascade = CascadeType.ALL,fetch = FetchType.EAGER)
private Set<TestClassChild> testClassChildSet;
}
Currently my database look like this:
Relationships :
Equalitiy of objects is done by comparing their email
I have code for testing this case:
@SpringBootApplication
@AllArgsConstructor
public class DemoApplication {
private final TestClassChildRepository testClassRepository;
private final TestChildCollectionRepository testChildCollectionRepository;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean
public ApplicationRunner applicationRunner() {
return args -> {
TestClassChild testClassChild = testClassRepository.findById(1L).get();
TestClassChild testClass1 = new TestClassChild();
testClass1.setId(testClassChild.getId());
testClass1.setEmail(new String("newTestEmail2"));
System.out.println(testClass1.equals(testClassChild));
};
}
}
And I get false for comparing these objects
I looked for debug and saw that, first instance has hashcode in email, and another one doesn't First one:
Second one:
CodePudding user response:
testClassRepository.findById(1L).get();
returns an object with testChildCollection
. When you generate a new TestClassChild
you set id and email, but not the collection, but in your example Lombok also uses the testChildCollection
to calculate equals/hashCode.
When using inheritance I usually try to avoid using @Data
, because it's easy to loose track of how the equals/hashCode are actually generated.
@Entity
@Getter
@Setter
@ToString(callSuper = true) // Only if you really need a toString implementation that also prints your collection.
public class TestClassChild extends TestClassParent
Will do the same just without the hashCode/equals generation.
CodePudding user response:
The problem is that your TestClassChild
equals()
method also include a check for its testChildCollection
property. The variable testClassChild
has such property as not null, but testClass1
has it as null. Hence the call testClass1.equals(testClassChild)
will always be false
.
If you only want to rely on the superclass equals()
implementation, then you will have to exclude testClassChild
as follows:
@Entity
@Data
@EqualsAndHashCode(callSuper = true)
public class TestClassChild extends TestClassParent{
@EqualsAndHashCode.Exclude
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "test_collection_id")
private TestChildCollection testChildCollection;
}