Hibernate Envers如何正确获取日志历史记录?

时间:2020-06-21 07:37:15

标签: java spring-boot hibernate hibernate-envers spring-data-envers

我使用Hibernate Envers创建了一个表审核日志,并且我使用Spring Data Envers作为我的库,当我保存/更新/删除它时,该日志成功地将日志保存在了autid_log表中,但是当我想检索日志数据时,我遇到了无限的错误循环,我该怎么做呢?这是我的代码:

这是我的控制器:

@GetMapping("/getPartnerRelationshipLog/{partnerId}")
public ResponseEntity<?> getPartnerRelationshipLog(@PathVariable Long partnerId) {
    // Long id = partner.getId();

    Revisions<Integer,Partner> history = partnerService.findRelationLog(partnerId);
    return ResponseEntity.ok(history);
 
}

这是我的Partner.java模型: 包com.example.envers.auditing.Model;

@Data
@Entity
@Audited
@EntityListeners(AuditingEntityListener.class)
@Table(name = "msPartner")
public class Partner {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Long id;

    public String partnerCode;

    public String partnerName;

    @CreatedDate
    private Date createDate;
    @LastModifiedDate
    private Date lastModifiedDate;
    @CreatedBy
    private String createdBy;
    @LastModifiedBy
    private String modifiedBy;

    @OneToMany(mappedBy = "partner", cascade = CascadeType.ALL)
    public List<PartnerShipment> partnerShipment;

}

这是我的PartnerShipment.java:

@Data
@Entity
@Audited
@EntityListeners(AuditingEntityListener.class)
@Table(name = "msPartnerShipment")
public class PartnerShipment {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Long id;

    public String partnerShipmentCode;

    public String partnerShipmentAddress;

    @JsonIgnore
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "partnerId")
    // @NotAudited
    public Partner partner;

    @CreatedDate
    private Date createDate;
    @LastModifiedDate
    private Date lastModifiedDate;
    @CreatedBy
    private String createdBy;
    @LastModifiedBy
    private String modifiedBy;

}

这是我的服务:

public Revisions<Integer,Partner> findRelationLog(Long id) {
    Revisions<Integer,Partner> partner = partnerRepository.findRevisions(id);

    return partner;
}

这是我的存储库:

@Repository
public interface PartnerRepository extends RevisionRepository<Partner, Long, Integer>, JpaRepository<Partner, Long > {
    
}

这是我的Application.java

@SpringBootApplication
@EnableJpaRepositories(repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class)
@EnableJpaAuditing
public class AuditingApplication {

    public static void main(String[] args) {
        SpringApplication.run(AuditingApplication.class, args);
    }

}

当我获得id = 1的数据时,出现类似循环的无限错误之类的东西,从java.lang.StackOverflowError:null开始,我在终端中看到的只是这个:

java.lang.StackOverflowError: null
    at com.example.envers.auditing.Model.PartnerShipment.hashCode(PartnerShipment.java:33) ~[classes/:na]
    at java.util.AbstractList.hashCode(AbstractList.java:541) ~[na:1.8.0_241]
    at org.hibernate.envers.internal.entities.mapper.relation.lazy.proxy.CollectionProxy.hashCode(CollectionProxy.java:131) ~[hibernate-envers-5.4.17.Final.jar:5.4.17.Final]
    at com.example.envers.auditing.Model.Partner.hashCode(Partner.java:31) ~[classes/:na]
    at com.example.envers.auditing.Model.PartnerShipment.hashCode(PartnerShipment.java:33) ~[classes/:na]
    at java.util.AbstractList.hashCode(AbstractList.java:541) ~[na:1.8.0_241]
    at org.hibernate.envers.internal.entities.mapper.relation.lazy.proxy.CollectionProxy.hashCode(CollectionProxy.java:131) ~[hibernate-envers-5.4.17.Final.jar:5.4.17.Final]
    at com.example.envers.auditing.Model.Partner.hashCode(Partner.java:31) ~[classes/:na]
    at com.example.envers.auditing.Model.PartnerShipment.hashCode(PartnerShipment.java:33) ~[classes/:na]
    at java.util.AbstractList.hashCode(AbstractList.java:541) ~[na:1.8.0_241]
    at org.hibernate.envers.internal.entities.mapper.relation.lazy.proxy.CollectionProxy.hashCode(CollectionProxy.java:131) ~[hibernate-envers-5.4.17.Final.jar:5.4.17.Final]
    at com.example.envers.auditing.Model.Partner.hashCode(Partner.java:31) ~[classes/:na]
    at com.example.envers.auditing.Model.PartnerShipment.hashCode(PartnerShipment.java:33) ~[classes/:na]
    at java.util.AbstractList.hashCode(AbstractList.java:541) ~[na:1.8.0_241]
    at org.hibernate.envers.internal.entities.mapper.relation.lazy.proxy.CollectionProxy.hashCode(CollectionProxy.java:131) ~[hibernate-envers-5.4.17.Final.jar:5.4.17.Final]
    at com.example.envers.auditing.Model.Partner.hashCode(Partner.java:31) ~[classes/:na]
    at com.example.envers.auditing.Model.PartnerShipment.hashCode(PartnerShipment.java:33) ~[classes/:na]
    at java.util.AbstractList.hashCode(AbstractList.java:541) ~[na:1.8.0_241]
    at org.hibernate.envers.internal.entities.mapper.relation.lazy.proxy.CollectionProxy.hashCode(CollectionProxy.java:131) ~[hibernate-envers-5.4.17.Final.jar:5.4.17.Final]
    at com.example.envers.auditing.Model.Partner.hashCode(Partner.java:31) ~[classes/:na]
    at com.example.envers.auditing.Model.PartnerShipment.hashCode(PartnerShipment.java:33) ~[classes/:na]
    at java.util.AbstractList.hashCode(AbstractList.java:541) ~[na:1.8.0_241]
    at org.hibernate.envers.internal.entities.mapper.relation.lazy.proxy.CollectionProxy.hashCode(CollectionProxy.java:131) ~[hibernate-envers-5.4.17.Final.jar:5.4.17.Final]

为了避免此错误,我错过了什么?

1 个答案:

答案 0 :(得分:1)

在您的两个实体上添加@EqualsAndHashCode(of = "id")。我认为使用@ToString指定必填字段也很好。我希望这能解决您的问题。

@Data
@Entity
@Audited
@EntityListeners(AuditingEntityListener.class)
@Table(name = "msPartner")
@EqualsAndHashCode(of = "id")
@ToString(of = {"id", "partnerCode", "partnerName"})
public class Partner {}



@Data
@Entity
@Audited
@EntityListeners(AuditingEntityListener.class)
@Table(name = "msPartnerShipment")
@EqualsAndHashCode(of = "id")
@ToString(of = {"id", "partnerShipmentCode", "partnerShipmentAddress"})
public class PartnerShipment {}

@Data注释实现@EqualsAndHashCode。但是在这种情况下,它将创建无限的循环递归。例如:对于hashCode方法,@EqualsAndHashCode的默认实现将包括所有字段。

public class Partner {
  public int hashCode() {
    final int PRIME = 59;
    int result = 1;
    final Object $id = this.getId();
    result = result * PRIME + ($id == null ? 43 : $id.hashCode());
    final Object $partnerCode = this.getPartnerCode();
    result = result * PRIME + ($partnerCode == null ? 43 : $partnerCode.hashCode());
    final Object $partnerName = this.getPartnerName();
    result = result * PRIME + ($partnerName == null ? 43 : $partnerName.hashCode());
    final Object $createDate = this.getCreateDate();
    result = result * PRIME + ($createDate == null ? 43 : $createDate.hashCode());
    final Object $lastModifiedDate = this.getLastModifiedDate();
    result = result * PRIME + ($lastModifiedDate == null ? 43 : $lastModifiedDate.hashCode());
    final Object $createdBy = this.getCreatedBy();
    result = result * PRIME + ($createdBy == null ? 43 : $createdBy.hashCode());
    final Object $modifiedBy = this.getModifiedBy();
    result = result * PRIME + ($modifiedBy == null ? 43 : $modifiedBy.hashCode());
    final Object $partnerShipment = this.getPartnerShipment();
    result = result * PRIME + ($partnerShipment == null ? 43 : $partnerShipment.hashCode());
    return result;
}
}

查看partnerShipment。它使用 result = result * PRIME + ($partnerShipment == null ? 43 : $partnerShipment.hashCode());,而partnerShipment是此处的列表。

,列表中的hashCode来自AbstractList

    public int hashCode() {
    int hashCode = 1;
    for (E e : this)
        hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
    return hashCode;
}
在这种情况下,

遍历每个PartnerShipment项目并调用其hashCode方法。并且您还在@Data上使用PartnerShipment注释,因此它的hashCode方法还包括Partner字段,该字段创建了无限递归。