Java 在Spring boot中使用post方法保存多个实体时的无限循环
为了解释我正在处理的问题,我将首先提供代码 往复式控制器 用户控制器 例外情况 问题Java 在Spring boot中使用post方法保存多个实体时的无限循环,java,mysql,database,spring-boot,backend,Java,Mysql,Database,Spring Boot,Backend,为了解释我正在处理的问题,我将首先提供代码 往复式控制器 用户控制器 例外情况 问题 因此,当我调用该方法添加配方时,我希望数据库知道有一个新配方,并且新配方链接到添加它的用户。当我删除保存用户实体的部分时,根本不进行映射。但是,当我使用userRepository告诉数据库已经进行了更改(将配方添加到他们的列表中)时,似乎有一个无限的添加新用户的循环。回答您的问题并包括您评论中的最后要求 如果您想打破循环,但有些人想以某种方式保留嵌套对象,我建议编写一个自定义序列化程序,并将导致无休止递归的对
因此,当我调用该方法添加配方时,我希望数据库知道有一个新配方,并且新配方链接到添加它的用户。当我删除保存用户实体的部分时,根本不进行映射。但是,当我使用userRepository告诉数据库已经进行了更改(将配方添加到他们的列表中)时,似乎有一个无限的添加新用户的循环。回答您的问题并包括您评论中的最后要求 如果您想打破循环,但有些人想以某种方式保留嵌套对象,我建议编写一个自定义序列化程序,并将导致无休止递归的对象替换为其他字段(在下面的示例中,我使用了author username,它是
String
,而不是author
对象)
为了重现这个案例,我创建了一个模拟模型,它与您的模型类似
配方:
public class Recipe {
private EvaUser author;
private String name = "test";
private String ingridients = "carrots, tomatos";
public EvaUser getAuthor() {
return author;
}
public void setAuthor(EvaUser author) {
this.author = author;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIngridients() {
return ingridients;
}
public void setIngridients(String ingridients) {
this.ingridients = ingridients;
}
}
public class EvaUser {
private List<Recipe> myRecipes = new ArrayList<>();
private List<Recipe> favoriteRecipes = new ArrayList<>();
private String username;
public List<Recipe> getMyRecipes() {
return myRecipes;
}
public void setMyRecipes(List<Recipe> myRecipes) {
this.myRecipes = myRecipes;
}
public List<Recipe> getFavoriteRecipes() {
return favoriteRecipes;
}
public void setFavoriteRecipes(List<Recipe> favoriteRecipes) {
this.favoriteRecipes = favoriteRecipes;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
EvaUser:
public class Recipe {
private EvaUser author;
private String name = "test";
private String ingridients = "carrots, tomatos";
public EvaUser getAuthor() {
return author;
}
public void setAuthor(EvaUser author) {
this.author = author;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIngridients() {
return ingridients;
}
public void setIngridients(String ingridients) {
this.ingridients = ingridients;
}
}
public class EvaUser {
private List<Recipe> myRecipes = new ArrayList<>();
private List<Recipe> favoriteRecipes = new ArrayList<>();
private String username;
public List<Recipe> getMyRecipes() {
return myRecipes;
}
public void setMyRecipes(List<Recipe> myRecipes) {
this.myRecipes = myRecipes;
}
public List<Recipe> getFavoriteRecipes() {
return favoriteRecipes;
}
public void setFavoriteRecipes(List<Recipe> favoriteRecipes) {
this.favoriteRecipes = favoriteRecipes;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
来自控制器的EvaUser
的JSON响应主体(前一个是StackOverflowerError
):
可能重复:@MehrajMalik这个问题和答案似乎有点过时了。我觉得这个对我没什么帮助。无论如何,谢谢。所有的技巧对当前任务也有效。这是由保存操作引起的吗?在我看来,Jackson似乎正试图在你的
getAllUsers()
中序列化你的EvaUser
,因为它引用了Recipe
,并且Recipe
引用了EvaUser
,它无法正确地序列化它,并最终进入映射该链的无限循环。通过添加@JsonIgnore
来打破该链的@MehrajMalik提供的答案实际上是一个正确的解决方案,并且没有过时。只是偶然发现了答案。我确实犯了一个错误,使用author作为一个对象,其中也包含recipe,导致了一个循环。非常感谢。
Failed to write HTTP message:
org.springframework.http.converter.HttpMessageNotWritableException: Could
not write content: Infinite recursion
public class Recipe {
private EvaUser author;
private String name = "test";
private String ingridients = "carrots, tomatos";
public EvaUser getAuthor() {
return author;
}
public void setAuthor(EvaUser author) {
this.author = author;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIngridients() {
return ingridients;
}
public void setIngridients(String ingridients) {
this.ingridients = ingridients;
}
}
public class EvaUser {
private List<Recipe> myRecipes = new ArrayList<>();
private List<Recipe> favoriteRecipes = new ArrayList<>();
private String username;
public List<Recipe> getMyRecipes() {
return myRecipes;
}
public void setMyRecipes(List<Recipe> myRecipes) {
this.myRecipes = myRecipes;
}
public List<Recipe> getFavoriteRecipes() {
return favoriteRecipes;
}
public void setFavoriteRecipes(List<Recipe> favoriteRecipes) {
this.favoriteRecipes = favoriteRecipes;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.util.Optional;
public class RecipeSerializer extends StdSerializer<Recipe> {
protected RecipeSerializer() {
this(null);
}
protected RecipeSerializer(Class<Recipe> t) {
super(t);
}
@Override
public void serialize(Recipe recipe, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeStartObject();
gen.writeStringField("name", recipe.getName());
gen.writeStringField("author", Optional.ofNullable(recipe.getAuthor().getUsername()).orElse("null"));
gen.writeStringField("ingridients", recipe.getIngridients());
gen.writeEndObject();
}
}
@JsonSerialize(using = RecipeSerializer.class)
public class Recipe {
// model entity
}
{
"myRecipes": [
{
"name": "soup",
"author": "user1",
"ingridients": "carrots, tomatos"
},
{
"name": "steak",
"author": "user1",
"ingridients": "meat, salt"
}
],
"favoriteRecipes": [
{
"name": "soup",
"author": "user1",
"ingridients": "carrots, tomatos"
},
{
"name": "steak",
"author": "user1",
"ingridients": "meat, salt"
}
],
"username": "user1"
}