0

I'm using spring boot and hibernate, trying to save an entity with a @ManyToOne relation by posting only the id of the referenced entity

@Entity
@Table(name = "foo_table")
public class Foo implements Serializable {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private id;

    @NotNull
    @JsonIdentityReference(alwaysAsId=true)
    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "bar_id", nullable = false)
    private Bar bar;

    ...
}


@Entity
@Table(name = "bar_table")
public class Bar implements Serializable {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private id;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "bar")
    private Set<Foo> foos;

    ...
}

And the controller code is similar to:

@RestController
public class FooController {

    @Autowired
    private FooRepo fooRepo;

    @RequestMapping(value = "/foo", method= RequestMethod.POST)
    public Foo foo(@RequestBody @Valid Foo foo)
        throws Exception {
        return fooRepo.save(foo);
    }
}

And the posted JSON is similar to

{
    "bar" : 1
}

However I'm getting an error in jackson while deserializing

"Could not read document: Unresolved forward references for: Object id [1]"

1 Answer 1

2

You either change your json so that you provide an object type for bar field where Jackson expects it, instead of an integer, and pass id explicitly:

{
    "bar": {
        "id": 1
    }
}

OR

Create the corresponding setter inside your Foo class - a setter that has the same input type as the ID type - in your case an integer:

public class Foo implements Serializable {
    ...

    @JsonProperty("bar")
    public void setBar(int id) {
        // For example:
        this.bar = new Bar(id);
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

While this works (after adding @JsonProperty(access = Access.WRITE_ONLY)), however, I'm trying to achieve serializing and deserializing Bar in the same manner using @JsonIdentityReference(alwaysAsId=true)
i.e. if it's represented in response as { bar : 1 }, I need to send it in post as {bar : 1} too.
@BadrGhatasheh I'm sorry, I didn't get it from the question - the provided classes don't have those annotations that you say you use. Updated my answer.
But that doesn't work since "new Bar()" isn't attached to the entity manager and will fail to insert
@BadrGhatasheh yes, that question rather refers to deserialization error. But it's up to you how to handle the integrity of data. You could load your entity from DB by calling dao.getBarById(id) after which you would have a managed instance. Actually, it's not a good idea to mess with transactions during serializaton/deserialization steps - usually you create additional classes FooDto and BarDto that are used for web layer only and then convert them to your entities manually inside the controller, ensuring all the fields the way you need - which fields to load, which to ignore.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.