Я работаю над проектом Spring Boot, которому необходимо преобразовать JSON в Entity для сохранения в базе данных postgresql. У меня есть некоторые отношения, ссылающиеся на себя, которые не знают, как десериализовать и сохранить в БД. У меня есть пользователи, у которых есть какие-то отношения с другими пользователями. Например, пользователь А является клиентом пользователя Б.
Давайте посмотрим пример кода, чтобы лучше понять...
У меня есть JSON для сохранения информации в БД.
{
id: 1,
name: "myName"
relations:[
{
"user_id": "2",
"relation": "relation_name"
},
{
"user_id": "3",
"relation": "other_relation_name"
}
]
}
У меня есть следующие классы (пример кода)
@Entity
@Data
public class User {
@Id
private Long id;
private String name;
@OneToMany(mappedBy = "user_id_parent")
private List<UserRelation> relations;
}
@Entity
@Data
public class UserRelation {
@Id
@ManyToOne(targetEntity = User.class)
@JoinColumn(name = "user_id_parent", referencedColumnName = "id", nullable = false)
private Long user_id_parent;
@Id
@JsonProperty("user_id")
private Long user_id_child;
private String relation;
}
Для десериализации и сохранения в БД я делаю это
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(json.toString(), User.class);
// user have [User(id=1, name:"myName", relations=[UserRelation(user_id_child=2, relation = "relation_name", user_id_parent=null)]]
userRepository.save(user);
Но у меня есть эта ошибка:
Unable to find com.compani.project.domain.UserRelation with id UserRelation(user_id_child=2, relation=null, user_id_parent=null)
Я понятия не имею, как хорошо выполнить эту задачу. Есть идеи или предложения, что можно сделать?
РЕДАКТИРОВАТЬ
Как предложил @Wladimir Diskowski, это работа для меня.
@Entity
@Data
public class User {
@Id
private Long id;
private String name;
@OneToMany(mappedBy = "userParent", cascade = { CascadeType.PERSIST, CascadeType.MERGE })
private List<UserRelation> relations;
}
@Entity
@Data
public class UserRelation {
@Id
@ManyToOne(targetEntity = User.class)
@JoinColumn(name = "user_id_parent", referencedColumnName = "id", nullable = false)
@JsonIgnore
private User userParent;
@Id
@JsonProperty("user_id")
private Long user_id_child;
private String relation;
}
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(json.toString(), User.class);
user.relations.foreach(r -> r.setUserParent(user));
userRepository.save(user);
Но у меня есть эта ошибка
Unable to find com.compani.project.domain.UserRelation with id com.compani.project.domain.UserRelationId@356bed68
Вам следует установить user_id_parent равным 2 и сначала сохранить UserRelation или определить Cascade Persist по сущности User.
@WladimirDiskowski, я думаю, что user_id_parent должен быть 1, а 2 будет user_id_child. Также я определяю Cascade Persist в сущности User и не работает.
@AntonKozub да, я знаю. user_id_parent должен иметь значение nullable = false, потому что это идентификатор пользователя (в примере json id:1), но я не знаю, как получить этот идентификатор и поместить UserRelation .user_id_parent
Что я имею в виду:
@Entity
@Data
public class User {
@Id
private Long id;
private String name;
@OneToMany(mappedBy = "userParent", cascade = { CascadeType.PERSIST, CascadeType.MERGE })
private List<UserRelation> relations;
}
@Entity
@Data
public class UserRelation {
@ManyToOne(targetEntity = User.class)
@JoinColumn(name = "user_id_parent", referencedColumnName = "id", nullable = false)
@JsonIgnore
private User userParent;
@Id
@JsonProperty("user_id")
private Long user_id_child;
private String relation;
}
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(json.toString(), User.class);
user.relations.foreach(r -> r.setUserParent(user));
userRepository.save(user);
Я написал, как вы говорите, но у меня есть еще одна ошибка (я отредактировал вопрос).
я исправил свой ответ
И если пользователь уже существует в базе данных и вы производите обновление, вам также понадобится CascadeType.MERGE.
Ваше поле user_id_parent отмечено nullable = false, но вы пытаетесь сохранить с нулевым значением.