Home > Software design >  Why entity objects are not equal if I get one of that object with another fetched object that has co
Why entity objects are not equal if I get one of that object with another fetched object that has co

Time:12-12

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:

enter image description here

enter image description here

enter image description here

Relationships :

enter image description here

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

Result is : enter image description here

I looked for debug and saw that, first instance has hashcode in email, and another one doesn't First one:

enter image description here

Second one:

enter image description here

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;
}
  • Related