From cd9219acefd4cc13cbad98c0e82907b4933f0f25 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Thu, 6 Jul 2023 12:43:24 +0200 Subject: [PATCH] Adds Warning.JPA_GETTER --- .../main/java/nl/jqno/equalsverifier/Warning.java | 13 +++++++++++++ .../internal/checkers/FieldsChecker.java | 5 ++++- .../extra_features/JpaLazyEntityTest.java | 15 +++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/Warning.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/Warning.java index 5b3939839..ab67cf27a 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/Warning.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/Warning.java @@ -165,6 +165,19 @@ public enum Warning { */ SURROGATE_OR_BUSINESS_KEY, + /** + * Disables the check that collection fields in JPA, or @Basic fields marked with + * FetchType.LAZY, should be accessed through their getter methods in {@code equals} and + * {@code hashCode} methods. + * + *

Normally, it is necessary to go through the getter for these fields, because their + * content may not be materialized in some instances. Calling the getter will materialize them, + * but referencing the field directly will not. This can lead to situations where the + * {@code equals} method of objects that should be equal to each other returns false, because + * one instance has the content materialized and the other does not. + */ + JPA_GETTER, + /** * Disables the check that transient fields not be part of the {@code equals} contract. * diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java index e83cd8fc5..ab958f5fe 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java @@ -95,7 +95,10 @@ public void check() { } AnnotationCache cache = config.getAnnotationCache(); - if (cache.hasClassAnnotation(config.getType(), SupportedAnnotations.ENTITY)) { + if ( + cache.hasClassAnnotation(config.getType(), SupportedAnnotations.ENTITY) && + !config.getWarningsToSuppress().contains(Warning.JPA_GETTER) + ) { inspector.check(jpaLazyGetterFieldCheck); } } diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/extra_features/JpaLazyEntityTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/extra_features/JpaLazyEntityTest.java index a27451e51..c88b8def3 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/extra_features/JpaLazyEntityTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/extra_features/JpaLazyEntityTest.java @@ -47,41 +47,49 @@ public void basicGetterNotUsed_givenCorrespondingFieldIgnored() { @Test public void basicGetterUsed_givenAnnotationIsOnGetter() { getterNotUsed(IncorrectBasicJpaLazyGetterContainer.class, "equals"); + getterNotUsed_warningSuppressed(IncorrectBasicJpaLazyGetterContainer.class); } @Test public void basicGetterNotUsedInHashCode() { getterNotUsed(IncorrectBasicJpaLazyFieldContainerHashCode.class, "hashCode"); + getterNotUsed_warningSuppressed(IncorrectBasicJpaLazyFieldContainerHashCode.class); } @Test public void basicGetterNotUsed() { getterNotUsed(IncorrectBasicJpaLazyFieldContainer.class, "equals"); + getterNotUsed_warningSuppressed(IncorrectBasicJpaLazyFieldContainer.class); } @Test public void oneToOneGetterNotUsed() { getterNotUsed(IncorrectOneToOneJpaLazyFieldContainer.class, "equals"); + getterNotUsed_warningSuppressed(IncorrectOneToOneJpaLazyFieldContainer.class); } @Test public void oneToManyGetterNotUsed() { getterNotUsed(IncorrectOneToManyJpaLazyFieldContainer.class, "equals"); + getterNotUsed_warningSuppressed(IncorrectOneToManyJpaLazyFieldContainer.class); } @Test public void manyToOneGetterNotUsed() { getterNotUsed(IncorrectManyToOneJpaLazyFieldContainer.class, "equals"); + getterNotUsed_warningSuppressed(IncorrectManyToOneJpaLazyFieldContainer.class); } @Test public void manyToManyGetterNotUsed() { getterNotUsed(IncorrectManyToManyJpaLazyFieldContainer.class, "equals"); + getterNotUsed_warningSuppressed(IncorrectManyToManyJpaLazyFieldContainer.class); } @Test public void elementCollectionGetterNotUsed() { getterNotUsed(IncorrectElementCollectionJpaLazyFieldContainer.class, "equals"); + getterNotUsed_warningSuppressed(IncorrectElementCollectionJpaLazyFieldContainer.class); } @Test @@ -131,6 +139,13 @@ private void getterNotUsed(Class type, String method) { .assertMessageContains("JPA Entity", method, "direct reference"); } + private void getterNotUsed_warningSuppressed(Class type) { + EqualsVerifier + .forClass(type) + .suppress(Warning.JPA_GETTER, Warning.NONFINAL_FIELDS) + .verify(); + } + @Entity static class CorrectJpaLazyFieldContainer {