使用Spring Data REST保存嵌套对象

时间:2017-09-28 16:03:09

标签: spring spring-boot spring-data-rest spring-hateoas

我正在使用Spring Boot,Spring Data REST,Hibernate,Spring JPA。 我有一个这样的模型:

 @TypeDefs({ @TypeDef(name = "json", typeClass = JsonStringType.class),
        @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) })
@EntityListeners({ AuditingEntityListener.class })
@MappedSuperclass
@Audited
public abstract class AbstractEntity extends AbstractPersistable<Long> {
    private static final long serialVersionUID = 1L;

    /* "UUID" and "UID" are Oracle reserved keywords -> "sid" */
    @Column(name = "sid", unique = true, nullable = false, updatable = false, length = 36)
    private String sid;

    @CreatedBy
    private String createdBy;

    @CreatedDate
    @Column(updatable = false)
    private Instant createdDate;

    @LastModifiedDate
    private Instant lastModifiedDate;

    @LastModifiedBy
    private String lastModifiedBy;

    // Trick to start version counting from 1 instead of 0
    @Version
    private long version = 1;

    public AbstractEntity() {
    }

    @PrePersist
    public void initializeUUID() {
        if (sid == null) {
            sid = UUID.randomUUID().toString();
        }
    }

    @Override
    @JsonIgnore
    @ApiModelProperty(hidden = true)
    public Long getId() {
        return super.getId();
    }

    @Override
    @JsonIgnore
    @ApiModelProperty(hidden = true)
    protected void setId(Long id) {
        super.setId(id);
    }

    public String getSid() {
        return sid;
    }

    public Instant getCreatedDate() {
        return createdDate;
    }

    public Instant getLastModifiedDate() {
        return lastModifiedDate;
    }

    public String getLastModifiedBy() {
        return lastModifiedBy;
    }

    public long getVersion() {
        return version;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (!super.equals(obj))
            return false;
        if (getClass() != obj.getClass())
            return false;
        AbstractEntity other = (AbstractEntity) obj;
        if (sid == null) {
            if (other.sid != null)
                return false;
        } else if (!sid.equals(other.sid)) {
            if (getId() == null) {
                if (other.getId() != null)
                    return false;
            } else {
                if (!getId().equals(other.getId()))
                    return false;
            }
        }

        return true;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = super.hashCode();
        result = prime * result + ((sid == null) ? 0 : sid.hashCode());
        return result;
    }

}



 @Entity
public class ParentEntity extends AbstractEntity {
    private String name;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true, mappedBy = "parentEntity")
    @OnDelete(action = OnDeleteAction.CASCADE)
    private List<NestedEntity> rows = new ArrayList<>();

}

@Entity
public class NestedEntity extends AbstractEntity {

    private String name;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    private ParentEntity parentEntity;  
}

我正在尝试使用SDR为ParentEntity类提供的默认POST方法。 我的存储库是:

@Transactional
@PreAuthorize("isAuthenticated()")
public interface ParentEntityRepository extends PagingAndSortingRepository<ParentEntity, Long> {
}

我想从客户端发出一个POST(Angular,但我先尝试使用Swagger)发送ParentEntity和嵌套对象NestedEntity,因为我希望保存发生在同一个事务中。

所以我发送这个Json:

    {   
  "name": "Test",  
  "_embedded": {
    "rows": [
      {
        "name": "Nested object"        
      }
    ]
  }
}

不幸的是,只有父实体保存在数据库中。我尝试 - 仅用于测试 - 覆盖ParentEntityRepository中的方法save()以便调试并查看收到的内容。我看到rows列表为空。 我的代码出了什么问题?您有什么建议可以了解我的数据丢失的位置吗?

1 个答案:

答案 0 :(得分:1)

只需关闭NestedEntityRepository的导出(或删除它):

@RepositoryRestResource(exported = false)
public interface NestedEntityRepository extends JpaRepository<NestedEntity, UUID> {
}

并提供两个实体之间的双向关联的同步。例如:

public class ParentEntity {

    // ...

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true, mappedBy = "parentEntity")
    private List<NestedEntity> rows;

    public void setRows(List<NestedEntity> rows) {
        if (this.rows != null) {
            this.rows.forEach(row -> row.setParentEntity(null));
        }
        if (rows != null) {
            rows.forEach(row -> row.setParentEntity(this));
        }
        this.rows = rows;
    }  
}

或者只是将你的关联转为单向。