Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Protected getter triggers JPA_GETTER #909

Closed
rechandler12 opened this issue Jan 5, 2024 · 3 comments
Closed

Protected getter triggers JPA_GETTER #909

rechandler12 opened this issue Jan 5, 2024 · 3 comments

Comments

@rechandler12
Copy link

rechandler12 commented Jan 5, 2024

Describe the bug
When I have protected getter Equalsverifier trigger JPA_GETTER warning. When getter is public everything works correctly

Caused by: java.lang.AssertionError: EqualsVerifier found a problem in class pl.interrisk.irys.auto.partner.infrastructure.adapters.db.Partner.
-> JPA Entity: direct reference to field id used in equals instead of getter getId().

Code that triggers the behavior

@Entity
@DynamicUpdate
@Table(name = "partner")
@EntityListeners(AuditingEntityListener.class)
@Getter(AccessLevel.PACKAGE)
@Setter(AccessLevel.PACKAGE)
@AllArgsConstructor(access = AccessLevel.PACKAGE)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Builder(access = AccessLevel.PACKAGE)
class Partner2 extends BaseEntity<Long> {

    @Id
    @Column(name = "id", nullable = false, updatable = false)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "partner_seq_gen")
    @SequenceGenerator(name = "partner_seq_gen", sequenceName = "seq_partner_id", allocationSize = 1)
    @Getter(AccessLevel.PROTECTED)
    private Long id;

    @Column(name = "uuid", nullable = false, unique = true, updatable = false)
    private UUID uuid;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "calculation_id", nullable = false, updatable = false)
    private PartnerCalculationView calculation;

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
    @JoinColumn(name = "residence_address_id", referencedColumnName = "id")
    private Address residenceAddress;

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
    @JoinColumn(name = "postal_address_id", referencedColumnName = "id")
    private Address postalAddress;

    @Enumerated(EnumType.STRING)
    @ElementCollection
    @CollectionTable(name = "partner_role", joinColumns = @JoinColumn(name = "partner_id"))
    @Column(name = "partner_role", nullable = false)
    private Set<PartnerRole> roles;

    @CreatedDate
    @Column(name = "created_date", nullable = false, updatable = false)
    private Instant createdDate;

    @LastModifiedDate
    @Column(name = "last_modified_date", nullable = false)
    private Instant lastModifiedDate;

    @Version
    @Column(name = "version", nullable = false)
    private short version;
}

@MappedSuperclass
public abstract class BaseEntity<ID> {

    protected abstract ID getId();

    @Override
    public final boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null) {
            return false;
        }
        Class<?> oEffectiveClass = o instanceof HibernateProxy
                ? ((HibernateProxy) o).getHibernateLazyInitializer().getPersistentClass()
                : o.getClass();
        Class<?> thisEffectiveClass = this instanceof HibernateProxy
                ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass()
                : this.getClass();
        if (thisEffectiveClass != oEffectiveClass) {
            return false;
        }
        BaseEntity<?> that = (BaseEntity<?>) o;
        return getId() != null && Objects.equals(getId(), that.getId());
    }

    @Override
    public final int hashCode() {
        return this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer()
                .getPersistentClass()
                .hashCode() : getClass().hashCode();
    }
}

And Test:

    def "should check equals and hashCode for Partner entity"() {
        expect:
        EqualsVerifier.forClass(Partner2.class)
                .suppress(Warning.SURROGATE_KEY)
                .suppress(Warning.IDENTICAL_COPY_FOR_VERSIONED_ENTITY)
                .suppress(Warning.STRICT_HASHCODE)
                .withRedefinedSuperclass()
                .usingGetClass()
                .withPrefabValues(PartnerCalculationView, new PartnerCalculationView(), new PartnerCalculationView())
                .verify()
    }

this line is a problem:

    @Getter(AccessLevel.PROTECTED)
    private Long id;

Error message

Caused by: java.lang.AssertionError: EqualsVerifier found a problem in class pl.interrisk.irys.auto.partner.infrastructure.adapters.db.Partner.
-> JPA Entity: direct reference to field id used in equals instead of getter getId().

Expected behavior
No warning when I use protected getter

Version
3.15.5

@rechandler12
Copy link
Author

After further investigation combine:

    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "partner_seq_gen")
    @SequenceGenerator(name = "partner_seq_gen", sequenceName = "seq_partner_id", allocationSize = 1)

and:

    @Getter(AccessLevel.PROTECTED)

causes the problem

@jqno
Copy link
Owner

jqno commented Jan 8, 2024

You're right, protected getters are skipped. I'll investigate why this happens and try to come up with a fix.

@jqno
Copy link
Owner

jqno commented Jan 9, 2024

I've just released version 3.15.6, which should fix this

@jqno jqno closed this as completed Jan 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants