springdatarepository ElasticSearch 在保存时工作,但在更新时失败 java.lang.***Error: null

Posted

技术标签:

【中文标题】springdatarepository ElasticSearch 在保存时工作,但在更新时失败 java.lang.***Error: null【英文标题】:springdatarepository ElasticSearch works on save but fails on update with java.lang.***Error: null 【发布时间】:2021-10-10 20:15:37 【问题描述】:

通过springdataelasticsearch 更新我的数据时,我收到java.lang.***Error: null。该应用程序是使用Jhipster 7.0.1 生成的。 Spring Boot 版本为2.4.4.。创建新对象时它可以正常工作,但更新会导致错误。这是CountryAdminUnitTypeService.java的相关部分。

     * Save a countryAdminUnitType.
     *
     * @param countryAdminUnitType the entity to save.
     * @return the persisted entity.
     */
    public CountryAdminUnitType save(CountryAdminUnitType countryAdminUnitType) 
        log.debug("Request to save CountryAdminUnitType : ", countryAdminUnitType);
        CountryAdminUnitType result = countryAdminUnitTypeRepository.save(countryAdminUnitType);
        countryAdminUnitTypeSearchRepository.save(result);
        return result;
    

创建时,对象在调用countryAdminUntiTypeSearchRepository.save(result); 时的外观如下。

result = CountryAdminUnitType@23268 "CountryAdminUnitTypeid=200102, name='Province'"
   id = Long@23292 200102
   name = "Province"
   parent = null
   country = Country@23275 "Countryid=183778, name='Turkey', isoCode='TR'"
    id = Long@23281 183778
    name = "Turkey"
    isoCode = "TR"
    countryAdminUnitTypes = null

这是 更新时的样子。

result = CountryAdminUnitType@24746 "CountryAdminUnitTypeid=200102, name='Province'"
 id = Long@24752 200102
 name = "Province"
 parent = null
 country = Country@24754 "Countryid=183778, name='Turkey', isoCode='TR'"
  id = Long@24756 183778
  name = "Turkey"
  isoCode = "TR"
  countryAdminUnitTypes = PersistentSet@24761  size = 1
   0 = CountryAdminUnitType@24746 "CountryAdminUnitTypeid=200102, name='Province'"
    id = Long@24752 200102
    name = "Province"
    parent = null
    country = Country@24754 "Countryid=183778, name='Turkey', isoCode='TR'"

我看到的唯一区别是countryAdminUnitTypes 在第二种情况下不为空。但是,这应该由下面 Country.java 中给出的JsonIgnoreProperties 处理。

这是一个很长的日志文件的开头。

ERROR 91444 --- [  XNIO-5 task-1] c.s.c.s.CountryAdminUnitTypeService      : Exception in save() with cause = 'NULL' and exception = 'null'

java.lang.***Error: null
    at org.springframework.data.util.Streamable.stream(Streamable.java:87)
    at org.springframework.data.util.Streamable.lambda$map$1(Streamable.java:101)
    at org.springframework.data.util.LazyStreamable.stream(LazyStreamable.java:55)
    at org.springframework.data.util.LazyStreamable.iterator(LazyStreamable.java:46)
    at java.base/java.lang.Iterable.forEach(Iterable.java:74)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeCollectionValue(MappingElasticsearchConverter.java:710)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.getWriteComplexValue(MappingElasticsearchConverter.java:620)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeProperty(MappingElasticsearchConverter.java:601)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeProperties(MappingElasticsearchConverter.java:553)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeEntity(MappingElasticsearchConverter.java:511)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeEntity(MappingElasticsearchConverter.java:636)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.getWriteComplexValue(MappingElasticsearchConverter.java:627)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeProperty(MappingElasticsearchConverter.java:601)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeProperties(MappingElasticsearchConverter.java:553)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeEntity(MappingElasticsearchConverter.java:511)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeEntity(MappingElasticsearchConverter.java:636)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.getWriteComplexValue(MappingElasticsearchConverter.java:627)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.lambda$writeCollectionValue$7(MappingElasticsearchConverter.java:709)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
    at java.base/java.util.Spliterators$IteratorSpliterator.tryAdvance(Spliterators.java:1812)
    at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.lambda$initPartialTraversalState$0(StreamSpliterators.java:294)
    at java.base/java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.fillBuffer(StreamSpliterators.java:206)
    at java.base/java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.doAdvance(StreamSpliterators.java:161)
    at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.tryAdvance(StreamSpliterators.java:300)
    at java.base/java.util.Spliterators$1Adapter.hasNext(Spliterators.java:681)
    at java.base/java.lang.Iterable.forEach(Iterable.java:74)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeCollectionValue(MappingElasticsearchConverter.java:710)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.getWriteComplexValue(MappingElasticsearchConverter.java:620)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeProperty(MappingElasticsearchConverter.java:601)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeProperties(MappingElasticsearchConverter.java:553)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeEntity(MappingElasticsearchConverter.java:511)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeEntity(MappingElasticsearchConverter.java:636)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.getWriteComplexValue(MappingElasticsearchConverter.java:627)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeProperty(MappingElasticsearchConverter.java:601)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeProperties(MappingElasticsearchConverter.java:553)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeEntity(MappingElasticsearchConverter.java:511)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.writeEntity(MappingElasticsearchConverter.java:636)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.getWriteComplexValue(MappingElasticsearchConverter.java:627)
    at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter.lambda$writeCollectionValue$7(MappingElasticsearchConverter.java:709)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
    at java.base/java.util.Spliterators$IteratorSpliterator.tryAdvance(Spliterators.java:1812)
    at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.lambda$initPartialTraversalState$0(StreamSpliterators.java:294)
    at java.base/java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.fillBuffer(StreamSpliterators.java:206)
    at java.base/java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.doAdvance(StreamSpliterators.java:161)
    at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.tryAdvance(StreamSpliterators.java:300)
    at java.base/java.util.Spliterators$1Adapter.hasNext(Spliterators.java:681)
    at java.base/java.lang.Iterable.forEach(Iterable.java:74)

这里是模型类。

CountryAdminUnitType.java

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.io.Serializable;
import javax.persistence.*;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.springframework.data.elasticsearch.annotations.FieldType;

/**
 * A CountryAdminUnitType.
 */
@Entity
@Table(name = "country_admin_unit_type")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@org.springframework.data.elasticsearch.annotations.Document(indexName = "countryadminunittype")
public class CountryAdminUnitType implements Serializable 

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
    @SequenceGenerator(name = "sequenceGenerator")
    private Long id;

    @Column(name = "name")
    private String name;

    @ManyToOne
    @JsonIgnoreProperties(value =  "parent", "country" , allowSetters = true)
    private CountryAdminUnitType parent;

    @ManyToOne
    @JsonIgnoreProperties(
        value =  "defaultResidenceMeasurementUnit", "countryAdminUnitTypes", "preferences", "personNationalities" ,
        allowSetters = true
    )
    private Country country;

    // jhipster-needle-entity-add-field - JHipster will add fields here
    public Long getId() 
        return id;
    

    public void setId(Long id) 
        this.id = id;
    

    public CountryAdminUnitType id(Long id) 
        this.id = id;
        return this;
    

    public String getName() 
        return this.name;
    

    public CountryAdminUnitType name(String name) 
        this.name = name;
        return this;
    

    public void setName(String name) 
        this.name = name;
    

    public CountryAdminUnitType getParent() 
        return this.parent;
    

    public CountryAdminUnitType parent(CountryAdminUnitType countryAdminUnitType) 
        this.setParent(countryAdminUnitType);
        return this;
    

    public void setParent(CountryAdminUnitType countryAdminUnitType) 
        this.parent = countryAdminUnitType;
    

    public Country getCountry() 
        return this.country;
    

    public CountryAdminUnitType country(Country country) 
        this.setCountry(country);
        return this;
    

    public void setCountry(Country country) 
        this.country = country;
    

    // jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here

    @Override
    public boolean equals(Object o) 
        if (this == o) 
            return true;
        
        if (!(o instanceof CountryAdminUnitType)) 
            return false;
        
        return id != null && id.equals(((CountryAdminUnitType) o).id);
    

    @Override
    public int hashCode() 
        // see https://vladmihalcea.com/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/
        return getClass().hashCode();
    

    // prettier-ignore
    @Override
    public String toString() 
        return "CountryAdminUnitType" +
            "id=" + getId() +
            ", name='" + getName() + "'" +
            "";
    

Country.java

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.springframework.data.elasticsearch.annotations.FieldType;

/**
 * A Country.
 */
@Entity
@Table(name = "country")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@org.springframework.data.elasticsearch.annotations.Document(indexName = "country")
public class Country implements Serializable 

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
    @SequenceGenerator(name = "sequenceGenerator")
    private Long id;

    @Column(name = "name")
    private String name;

    @Column(name = "iso_code")
    private String isoCode;

    @OneToMany(mappedBy = "country")
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
    @JsonIgnoreProperties(value =  "parent", "country" )
    private Set<CountryAdminUnitType> countryAdminUnitTypes = new HashSet<>();

    // jhipster-needle-entity-add-field - JHipster will add fields here
    public Long getId() 
        return id;
    

    public void setId(Long id) 
        this.id = id;
    

    public Country id(Long id) 
        this.id = id;
        return this;
    

    public String getName() 
        return this.name;
    

    public Country name(String name) 
        this.name = name;
        return this;
    

    public void setName(String name) 
        this.name = name;
    

    public String getIsoCode() 
        return this.isoCode;
    

    public Country isoCode(String isoCode) 
        this.isoCode = isoCode;
        return this;
    

    public void setIsoCode(String isoCode) 
        this.isoCode = isoCode;
    

    public Set<CountryAdminUnitType> getCountryAdminUnitTypes() 
        return this.countryAdminUnitTypes;
    

    public Country countryAdminUnitTypes(Set<CountryAdminUnitType> countryAdminUnitTypes) 
        this.setCountryAdminUnitTypes(countryAdminUnitTypes);
        return this;
    

    public Country addCountryAdminUnitType(CountryAdminUnitType countryAdminUnitType) 
        this.countryAdminUnitTypes.add(countryAdminUnitType);
        countryAdminUnitType.setCountry(this);
        return this;
    

    public Country removeCountryAdminUnitType(CountryAdminUnitType countryAdminUnitType) 
        this.countryAdminUnitTypes.remove(countryAdminUnitType);
        countryAdminUnitType.setCountry(null);
        return this;
    

    public void setCountryAdminUnitTypes(Set<CountryAdminUnitType> countryAdminUnitTypes) 
        if (this.countryAdminUnitTypes != null) 
            this.countryAdminUnitTypes.forEach(i -> i.setCountry(null));
        
        if (countryAdminUnitTypes != null) 
            countryAdminUnitTypes.forEach(i -> i.setCountry(this));
        
        this.countryAdminUnitTypes = countryAdminUnitTypes;
    


    // jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here

    @Override
    public boolean equals(Object o) 
        if (this == o) 
            return true;
        
        if (!(o instanceof Country)) 
            return false;
        
        return id != null && id.equals(((Country) o).id);
    

    @Override
    public int hashCode() 
        // see https://vladmihalcea.com/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/
        return getClass().hashCode();
    

    // prettier-ignore
    @Override
    public String toString() 
        return "Country" +
            "id=" + getId() +
            ", name='" + getName() + "'" +
            ", isoCode='" + getIsoCode() + "'" +
            "";
    

【问题讨论】:

您好,我也遇到了同样的问题,请问您解决了吗? 【参考方案1】:

这是因为 JHipster 如何设置save。它只发生在更新具有双向关系的对象时。

    * Save a countryAdminUnitType.
    *
    * @param countryAdminUnitType the entity to save.
    * @return the persisted entity.
    */
    public CountryAdminUnitType save(CountryAdminUnitType countryAdminUnitType) 
        log.debug("Request to save CountryAdminUnitType : ", countryAdminUnitType);
        CountryAdminUnitType result = countryAdminUnitTypeRepository.save(countryAdminUnitType);
        countryAdminUnitTypeSearchRepository.save(result);
        return result;
    

要更新的对象在传递给jpa repository countryAdminUnitTypeRepository.save(countryAdminUnitType); 时设置正确。但是返回的result对象存在循环依赖,直接转发给elasticsearch repository countryAdminUnitTypeSearchRepository.save(result);进行更新。我只使用对象的id 解决了它。

线

CountryAdminUnitType result = countryAdminUnitTypeRepository.save(countryAdminUnitType);
countryAdminUnitTypeSearchRepository.save(result);

已改为

CountryAdminUnitType result = countryAdminUnitTypeRepository.save(countryAdminUnitType);
countryAdminUnitType.setId(result.getId());
countryAdminUnitTypeSearchRepository.save(countryAdminUnitType);
return result;

【讨论】:

很好的解决方案,谢谢。您对如何使用实体中的注释有任何想法吗?我想这是因为对于双向多对一或单对多关系,此时忽略 JsonIgnoreProperties。这个错误实际上破坏了最初生成的使用弹性搜索的 jhipster 应用程序,应该提升到我想的项目的主线程。我自己可能会很快解决这个问题,但也许你已经有了解决方案?问候 这里是官方线程问题的更通用解决方案:github.com/jhipster/generator-jhipster/issues/…

以上是关于springdatarepository ElasticSearch 在保存时工作,但在更新时失败 java.lang.***Error: null的主要内容,如果未能解决你的问题,请参考以下文章

资讯Elas推出比特币企业套件Signavera

CrudRepository JpaRepository PagingAndSortingRepository之间的区别

在 Spring Data Repository 中刷新 Oracle Materialized 视图

Spring Entity Manager 和 Spring Data Repository 有啥区别?

elk+redis+filebeat

使用 Hibernate Projection 的预期 N+1 查询