简体   繁体   中英

Jackson failed to deserialization OneToMany objects

I have faced with the problem that converter can't handle JSON object.

I have two objects in data base. Relationship OneToMany.

I have a AutoService with many services.

And wnen i am trying to send JSON object using postman to my server - I am getting an error:

WARN org.springframework.http.converter.json.MappingJackson2HttpMessageConverter - Failed to evaluate Jackson deserialization for type [[simple type, class com.webserverconfig.user.entity.AutoService]]: java.lang.IllegalArgumentException: Can not handle managed/back reference 'defaultReference': no back reference property found from type [collection type; class java.util.List, contains [simple type, class com.webserverconfig.user.entity.Service]]

Next two classes represents my model:

Class AutoService:

@Entity
@Table(name = "AutoRate")
public class AutoService {

    public AutoService() {
    }

    @Id
    @GeneratedValue(generator = "increment")
    @GenericGenerator(name = "increment", strategy = "increment")
    private long id;

    @Column(name = "serviceName", nullable = false)
    private String serviceName;

    @Column(name = "imageURL", nullable = false)
    private String imageURL;

    @Column(name = "mapCoordinate", nullable = false)
    private String mapCoordinate;

    @Column(name = "websiteURL", nullable = false)
    private String websiteURL;

    @Column(name = "phoneNumber", nullable = false)
    private String phoneNumber;

    @JsonManagedReference
    @OneToMany(fetch = FetchType.EAGER)
    @JoinColumn(name = "autoServiceId")
    private List<Service> services;

    public long getId() {
        return id;
    }

    public String getServiceName() {
        return serviceName;
    }

    public String getImageURL() {
        return imageURL;
    }

    public String getMapCoordinate() {
        return mapCoordinate;
    }

    public String getWebsiteURL() {
        return websiteURL;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public List<Service> getServices() {
        return services;
    }
}

Class service:

@Entity
@Table(name = "Service")
public class Service {

    public Service() {
    }

    @Id
    @GeneratedValue(generator = "increment")
    @GenericGenerator(name = "increment", strategy = "increment")
    @Column(name = "serviceId", unique = true, nullable = false)
    private long serviceId;

    @Column(name = "serviceName", nullable = false)
    private String serviceName;

    @Column(name = "category", nullable = false)
    private String category;

    @Column(name = "price", nullable = false)
    private int price;

    @Column(name = "autoServiceId", nullable = false)
    private long autoServiceId;

    public long getId() {
        return serviceId;
    }

    public String getCategory() {
        return category;
    }


    public int getPrice() {
        return price;
    }

    public String getServiceName() {
        return serviceName;
    }

    public long getAutoServiceId() {
        return autoServiceId;
    }
}

Asking for help. Am i missing some annotation ?

Also Controller class:

@RestController
@RequestMapping("/directory")
public class ServiceController {

    @Autowired
    private AutoRateService dataBaseService;

    @RequestMapping(value = "/get", method = RequestMethod.GET)
    @ResponseBody
    public AutoService getData(){
        AutoService dataList = dataBaseService.getById(1);
        return dataList;
    }

    @RequestMapping(value = "/saveService", method = RequestMethod.POST)
    @ResponseBody public AutoService saveAutoService(@RequestBody AutoService autoService){
        return dataBaseService.save(autoService);
    }
}

You could add @JsonBackReference to the other site of the relation. Which by the way is missing or not correct implemented. Add:

@JsonBackReference
@ManyToOne
@JoinColumn(name = "autoServiceId", nullable = false)
private AutoService autoService;

instead of private long autoServiceId; .

Also the AutoService needs to be adjusted with:

@JsonManagedReference
@OneToMany(mappedBy = "autoService", fetch=FetchType.EAGER)
private List<Service> services = new ArrayList<>();

Solution #1 : - add @JsonIgnore where you have attributes with @OneToMany Example:

class User {
    @OneToMany(mappedBy = "user", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JsonManagedReference
    @JsonIgnore
    private List<Comment> comments;
}

class Comment {
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "user_id")
    @JsonBackReference
    private User user;
}

Solution #2: - use on your class @JsonIgnoreProperties({"name-of-your-attribute"}), for example "comments"

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM