2016-11-14 77 views
2

我正在嘗試使用支持客戶端和作業的Spring Boot構建REST API。客戶端可以有很多作業,並且作業屬於客戶端。然而,當我保存或者由CLIENT_ID或試圖找到客戶端對象的引用給客戶一個工作,我得到這個錯誤:在Spring Boot中通過POST爲創建實體創建引用

{ 
    "timestamp" : 1479163164739, 
    "status" : 400, 
    "error" : "Bad Request", 
    "exception" : "org.springframework.http.converter.HttpMessageNotReadableException", 
    "message" : "Could not read document: Can not construct instance of com.core.model.Client: no String-argument constructor/factory method to deserialize from String value ('3')\n at [Source: [email protected]; line: 1, column: 12] (through reference chain: com.core.model.Job[\"client\"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.core.model.Client: no String-argument constructor/factory method to deserialize from String value ('3')\n at [Source: [email protected]; line: 1, column: 12] (through reference chain: com.core.model.Job[\"client\"])", 
    "path" : "/api/v1/jobs" 
} 

包括我的模型和控制器的工作和客戶端:

我的工作模式:

package com.core.model; 

import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.CascadeType; 
import javax.persistence.Table; 
import javax.persistence.Column; 
import javax.persistence.JoinColumn; 
import javax.persistence.ManyToOne; 
import javax.persistence.Id; 

@Entity 
@Table(name="`job`") 
public class Job { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name="job_id") 
    private Long jobId; 

    @ManyToOne(cascade=CascadeType.ALL, targetEntity = Client.class) 
    @JoinColumn(name = "client_id", nullable = false) 
    private Client client; 

    private String address1; 
    private String address2; 
    private String city; 
    private String county; 
    private String state; 
    private String zip; 
    private String country; 
    private String description; 

    //Note: I tried Long client_id instead of using the Client object here and same thing 
    public Job(String description, String address1, String address2, String city, String county, 
       String state, String zip, String country, Client client) { 
     this.setDescription(description); 
     this.setAddress1(address1); 
     this.setAddress2(address2); 
     ... 
     this.setClient(client); 
    } 

    public Job() {} 

    public Long getId() { return jobId; } 
    public void setId(Long id) { this.jobId = id; } 
    ... 
    public Client getClient() { return client; } 
    public void setClient(Client client) { this.client = client; } 

} 

控制器的工作:

package com.core.controller; 

import com.core.model.Job; 
import com.core.repository.JobRepository; 
import org.apache.catalina.connector.Response; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.http.HttpStatus; 
import org.springframework.http.ResponseEntity; 
import org.springframework.web.bind.annotation.*; 
import com.core.repository.JobRepository; 
import org.springframework.hateoas.Resource; 

import java.util.Collection; 
import java.util.List; 

@RestController 
@RequestMapping("/api/v1/jobs") 
public class JobController { 

    @Autowired 
    private JobRepository repository; 

    @RequestMapping(method = RequestMethod.GET) 
    public ResponseEntity<Collection<Job>> getAllJob(){ 
     return new ResponseEntity<>((Collection<Job>) repository.findAll(), HttpStatus.OK); 
    } 
    @RequestMapping(method = RequestMethod.GET, value = "/{id}") 
    public ResponseEntity<Job> getEquipmentWithId(@PathVariable Long id) { 
     return new ResponseEntity<>(repository.findOne(id),HttpStatus.OK); 
    } 

    @RequestMapping(value="", method=RequestMethod.POST) 
    public ResponseEntity createNew(@RequestBody Job job) { 
     repository.save(job); 
     return new ResponseEntity(job, HttpStatus.CREATED); 
    } 
} 

和客戶端型號:

package com.core.model; 

import javax.persistence.Entity; 
import javax.persistence.Access; 
import javax.persistence.AccessType; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Table; 
import javax.persistence.Column; 
import javax.persistence.JoinColumn; 
import javax.persistence.Id; 
import javax.persistence.OneToMany; 

@Entity 
@Table(name="`client`") 
public class Client { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name="client_id") 
    @Access(AccessType.PROPERTY) 
    private Long clientId; 

    public Client(String description) { 
     this.setDescription(description); 
    } 

    public Client() {} 

    public Long getClientId() { 
     return clientId; 
    } 
    public void setClientId(Long id) { this.clientId = id; } 
    ... 
} 

我只是想將該客戶端ID保存到工作中,這裏有什麼正確的方法?

+0

你能證明你的要求 – kuhajeyan

回答

1

我的猜測是,你正在嘗試使用REST調用此方法:

@RequestMapping(value="", method=RequestMethod.POST) 
public ResponseEntity createNew(@RequestBody Job job) { 
     repository.save(job); 
     return new ResponseEntity(job, HttpStatus.CREATED); 
} 

釷的例外是很清楚的,它談論:

com.fasterxml.jackson.databind.JsonMappingException 

這意味着,只要您試圖在請求體內傳遞Job實體,Jackson無法將其綁定到您的方法控制器上的Job job參數。

我的建議是嘗試寫傑克遜反序列化器類,它會告訴傑克遜如何完全去做反序列化。

下面是如何做到這一點的例子:

Right way to write JSON deserializer in Spring or extend it

+0

酷,好不好。所以我爲Job實體制作了一個Deserializer和Serializer,我可以像這個例子那樣獲取client_id的值。我想我的問題是:從這裏,我應該實例化一個新的Job對象與一個(長)client_id並嘗試以這種方式保存它(並且只使用client_id作爲成員而不是Client對象),或者我應該實例化一個Client對象,嘗試找到傳入ID的對象,然後做一些事情來將新的Job作爲子項添加到客戶端? – albaba

+0

我用後者去了,那工作! Spring新手,來自不同的ORM世界,非常感謝您的幫助! – albaba

+1

乾杯;-)沒問題 –