2016-11-14 75 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

干杯;-)没问题 –