I'm implementing many-to-many relationship using hibernate as JPA and spring-boot. When I do a post request from the POSTMAN, I get the following error:
Failed to convert from type [java.net.URI] to type [com.domain.Datasource]
There is a many to many relationship between Metric
and Datasource
.
JSON body
{
"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;
}
Currently the relationship between Metric and Datasource is set properly , ie I have three tables metric
, datasource
and metric_datasource
created in the database. But I'm not sure how can I save the value using the give JSON body. Please help.
First, make sure that method in your REST-controller can consume "application/json", has a proper @RequestBody
annotation in it's arguments.
Second, I think sending a full-scale domain-like objects from client is not correct. You should implement DTO for class Metric
that would fully match the JSON you've provided. And the datasources
property should be List<String>
containing the actual datasources' ids in that case.
Then you should implement a method in your that would convert DTO to domain object (where you can fetch DataSource
objects for each datasource id stored in DTO) to persist it then.
// 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
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.