【问题标题】:How to map array in the JSON body to a POJO?如何将 JSON 正文中的数组映射到 POJO?
【发布时间】:2017-11-10 07:29:28
【问题描述】:

我正在使用 hibernate 作为 JPA 和 spring-boot 来实现多对多关系。当我从 POSTMAN 发出 post 请求时,我收到以下错误:

Failed to convert from type [java.net.URI] to type [com.domain.Datasource]

MetricDatasource 之间存在多对多关系。

JSON 正文

{
    "companyId" : "fake_company_id",
    "name" : "test_name",
    "description" :"test Description",
    "datasources" :  ["fdaea7d4162bd2c3f3db5ba059638123"]
}

Metric.java

@Entity
public class Metric implements Persistable<Long> {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(nullable = false)
@RestResource(exported = false)
private Long id;

@Column(nullable = false, unique = true)
private String publicId;
@Column(nullable = false)
private String name;
private MetricType type;

@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "metric_datasource", joinColumns = @JoinColumn(name = "metric_id", referencedColumnName = "id"), inverseJoinColumns =  @JoinColumn(name = "datasource_id", referencedColumnName = "id"))
private Set<Datasource> datasources ;
private String definition;
private long dateCreated;
private String description;
private String companyId;

protected Metric() {
    this.dateCreated = new Date().getTime();
}

public Metric(String name, String publicId, String definition) {
    super();
    this.name = name;
    this.publicId = publicId;
    this.definition = definition;
}

@JsonIgnore
@Override
public boolean isNew() {
    return null == getId();
}

@PrePersist
public void generatePublicId() {
    publicId = PublicIdGenerator.generate(32);
}

@Override
public Long getId() {
    return id;
}

public String getPublicId() {
    return publicId;
}

public void setPublicId(String publicId) {
    this.publicId = publicId;
}

public String getName() {
    return name;
}

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

public String getDefinition() {
    return definition;
}

public void setDefinition(String definition) {
    this.definition = definition;
}

public void setDateCreated(long dateCreated) {
    this.dateCreated = dateCreated;
}

public long getDateCreated(){
    return this.dateCreated;
}

public String getDescription() {
    return description;
}

public void setDescription(String description) {
    this.description = description;
}

public Set<Datasource> getDatasources() {
    if (datasources != null) {
        return datasources;
    } else {
        return Collections.emptySet();
    }
}

public void setDatasources(Set<Datasource> datasources) {
    if (datasources != null) {
        this.datasources = datasources;
    } else {
        this.datasources = Collections.emptySet();
    }
}

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

public String getCompanyId() {
    return companyId;
}

public void setCompanyId(String companyId) {
    this.companyId = companyId;
}

public MetricType getType() {
    return type;
}

public void setType(MetricType type) {
    this.type = type;
}

public void update(Metric metric) {
    if (metric.getName() != null) {
        setName(metric.getName());
    }

    if (metric.getDescription() != null) {
        setDescription(metric.getDescription());
    }
    if (metric.getDefinition() != null) {
        setDefinition(metric.getDefinition());
    }
}

Datasource.java

@Entity
public class Datasource implements Persistable<Long> {

@Column(nullable = false, unique = true)
private String publicId;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(nullable = false)
@RestResource(exported = false)
private Long id;

@ManyToMany(mappedBy = "datasources")
private Set<Metric> metrics;

public Datasource() {
    this(null);
}

public Datasource(String publicId) {
    this.publicId = publicId;
}

public String getPublicId() {
    return publicId;
}

public void setPublicId(String publicId) {
    this.publicId = publicId;
}

@Override
public Long getId() {
    return id;
}

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

@Override
public boolean isNew() {
    return null == getId();
}

public Set<Metric> getMetrics() {
    return metrics;
}

public void setMetrics(Set<Metric> metrics) {
    this.metrics = metrics;
}

目前Metric和Datasource之间的关系设置正确,即我在数据库中创建了三个表metricdatasourcemetric_datasource。但我不确定如何使用给定的 JSON 正文保存值。请帮忙。

【问题讨论】:

    标签: java hibernate jpa spring-boot spring-io


    【解决方案1】:

    首先,确保 REST 控制器中的方法可以使用“application/json”,并在其参数中有正确的 @RequestBody 注释。
    其次,我认为从客户端发送全面的类域对象是不正确的。您应该为类Metric 实现DTO,这将完全匹配您提供的JSON。在这种情况下,datasources 属性应该是包含实际数据源 ID 的 List&lt;String&gt;

    然后你应该在你的方法中实现一个方法,将 DTO 转换为域对象(你可以为存储在 DTO 中的每个数据源 id 获取 DataSource 对象)然后将其持久化。

    // assuming that you already implemented any JpaRepository<Metric> interface
    @Autowired
    private MetricRepository metricRepo;
    
    @Autowired
    private DataSourceRepository dataSourceRepo;
    
    public Metric saveMetricDTO(MetricDTO dto) {
      Metric metric = metricRepo.findByName(dto.getName()); // or fetch by any other suitable property
      // assign all props from DTO to metric: metric.setSmth(dto.getSmth())
      // ...
      List<DataSource> dsList = dto.getDataSourceIds().stream()
        .map(dataSourceRepo::findOne)
        .collect(Collectors.toList())
      metric.setDataSources(dsList);
      metricRepo.save(metric); // finally persist object
    }
    

    【讨论】:

      猜你喜欢
      • 2017-02-24
      • 2015-05-12
      • 2019-08-10
      • 2020-09-23
      • 1970-01-01
      • 2014-04-12
      • 1970-01-01
      • 1970-01-01
      • 2017-03-31
      相关资源
      最近更新 更多