I am building a simple spring boot blog app. This app has two entities user and post. The user table holds user data and has the primary key as Id and the post table holds content information with user information as a foreign key "postedBy" which refers to the id of user table. One User can have many posts.
Based on this I have designed Entity class like below.
@Entity
@Table
public class User {
@Id
@GeneratedValue(generator="system-uuid")
@GenericGenerator(name="system-uuid", strategy = "uuid")
private String id;
private String name;
private String email;
}
@Entity
@Table
public class Post {
@Id
@GeneratedValue(generator="system-uuid")
@GenericGenerator(name="system-uuid", strategy = "uuid")
private String id;
private String title;
@ManyToOne
@JoinColumn(name = "id" , insertable = false,updatable = false)
private User postedBy;
private String content;
}
As a user can have multiple posts I have user @ManyToOne annotation which maps to id of user via @JoinColumn
I am using the JpaRepository interface which is then exposed via rest controller.
But when I send the body to insert post like below
{
"title":"The Graphql way of design",
"postedBy":"402880ee73aa45570173aa462ea00001",
"content":" The content of blog "
}
It throws below error
Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `com.graphql.blog.model.User` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('402880ee73aa45570173aa462ea00001'); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.graphql.blog.model.User` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('402880ee73aa45570173aa462ea00001')
at [Source: (PushbackInputStream); line: 3, column: 13] (through reference chain: com.graphql.blog.model.Post["postedBy"])]
I was expecting postedBy column will store "402880ee73aa45570173aa462ea00001" as the user already exists and in response, it will send with user details automatically fetching user details for that post.
You are getting the error because a string field can not deserialize into object of User
.
I was expecting postedBy column will store "402880ee73aa45570173aa462ea00001" as the user already exists and in response, it will send with user details automatically fetching user details for that post.
No, spring can't do that automatically. To do it first properly deserialize the id by using json like this.
{
"title":"The Graphql way of design",
"postedBy":{
"id": "402880ee73aa45570173aa462ea00001"
},
"content":" The content of blog "
}
Then fetch the User
by id first and set in Post
, Ex:
Optional<User> user = userRepository.findById(post.getPostedBy.getId());
post.setUser(user.get());
And use @JoinColumn
for the field you want to store foreign key for user in post table.
@ManyToOne
@JoinColumn(name = "postedBy")
private User postedBy;
As per your requirement, you should put the following code:
In the class, User
:
@OneToMany(mappedBy = "postedBy", cascade = CascadeType.DETACH)
private List<Post> posts;
In the class, Post
:
@ManyToOne
@JsonIgnore
private User postedBy;
Add the @JsonIdentityInfo
annotation to the User
class:
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
Annotation used for indicating that values of annotated type or property should be serializing so that instances either contain additional object identifier (in addition actual object properties), or as a reference that consists of an object id that refers to a full serialization.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With