JPA多对多关系导致无限递归

huangapple go评论72阅读模式
英文:

JPA many to many relationship causing infinite recursion

问题

我使用了 @JsonIgnoreProperties 在两个类中来解决这个问题。

@JsonIgnoreProperties("pokemons")
@ManyToMany
@JoinTable(
    name = "pokemon_types",
    joinColumns = @JoinColumn(name = "pokemon_id"),
    inverseJoinColumns = @JoinColumn(name = "type_id"))
private Set<Type> types;

@JsonIgnoreProperties("types")
@ManyToMany(mappedBy = "types")
Set<Pokemon> pokemons;

我在我的 API 中有两个实体类。Pokemon 包含一个列表 "types",表示每个 Pokemon 都有哪些类型,而 Type 包含一个列表 "pokemons",表示拥有该特定类型的 Pokemon。

我正在尝试在我的控制器中实现一个 "getAll" 方法,但是遇到了无限递归的问题。

我尝试在 Type 类中使用 @JsonIgnore 注解,但这样我就无法获取每个类型内的 Pokemon 列表。关系的另一侧正常工作。

有没有办法避免无限递归问题,并同时获取关系的两个列表?

我的存储库扩展了 JpaRepository,我的控制器只调用 JpaRepository 的 findAll 方法。

Pokemon 类:

@Getter @Setter @NoArgsConstructor @AllArgsConstructor
@Entity
@Table(name="pokemons")
public class Pokemon implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;
    
    private String name;
    
    private String url;
    
    private String img;
    
    @ManyToMany
    @JoinTable(
        name = "pokemon_types",
        joinColumns = @JoinColumn(name = "pokemon_id"),
        inverseJoinColumns = @JoinColumn(name = "type_id"))
    private Set<Type> types;
    
}

Type 类:

@Setter @Getter @NoArgsConstructor @AllArgsConstructor
@Entity
@Table(name="types")
public class Type implements Serializable{

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;
    
    private String name;
    
    @JsonIgnore
    @ManyToMany(mappedBy = "types")
    Set<Pokemon> pokemons;

}

期望的结果:

[
   {
      id: ...,
      name: ...,
      pokemons: [
         {
            id: ...,
            name: ...
            url: ...
            img: ...
         },
         .
         .
         .
      ]
   },
   .
   .
   .
]

实际结果:

[
   {
      id: ...,
      name: ...,
   },
   .
   .
   .
]

希望这可以帮助你解决你的问题。如果你有任何其他问题,请随时提问。

英文:

Edit: I solved the problem using @JsonIgnoreProperties in both classes

@JsonIgnoreProperties(&quot;pokemons&quot;)
@ManyToMany
@JoinTable(
	name = &quot;pokemon_types&quot;,
	joinColumns = @JoinColumn(name = &quot;pokemon_id&quot;),
	inverseJoinColumns = @JoinColumn(name = &quot;type_id&quot;))
private Set&lt;Type&gt; types;


@JsonIgnoreProperties(&quot;types&quot;)
@ManyToMany(mappedBy = &quot;types&quot;)
Set&lt;Pokemon&gt; pokemons;

I have two entities in my api. Pokemon which has a list of "types" that pokemon have and Type which has a list of "pokemon" that have that specific type. I'm trying to implement a getAll method in my controllers but i'm having an infinite recursion problem.

I've tried to use the @JsonIgnore annotation in my type class but with this i'm not able to get the list of pokemons inside each type. The other side of the relashionship works well.

Is there any way to avoid the infinite recursion problem and at the same time get both lists of the relashionship.

My repositories extend the JpaRepository and my controllers just call the findAll method of the JpaRepository.

Pokemon:

@Getter @Setter @NoArgsConstructor @AllArgsConstructor
@Entity
@Table(name=&quot;pokemons&quot;)
public class Pokemon implements Serializable {

	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private Long id;
	
	private String name;
	
	private String url;
	
	private String img;
	
	@ManyToMany
	@JoinTable(
		name = &quot;pokemon_types&quot;,
		joinColumns = @JoinColumn(name = &quot;pokemon_id&quot;),
		inverseJoinColumns = @JoinColumn(name = &quot;type_id&quot;))
	private Set&lt;Type&gt; types;
	
}

Type:

@Setter @Getter @NoArgsConstructor @AllArgsConstructor
@Entity
@Table(name=&quot;types&quot;)
public class Type implements Serializable{

	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private Long id;
	
	private String name;
	
    @JsonIgnore
	@ManyToMany(mappedBy = &quot;types&quot;)
	Set&lt;Pokemon&gt; pokemons;

}

Expected result:

[
   {
      id: ...,
      name: ...,
      pokemons: [
         {
            id: ...,
            name; ...
            url: ...
            img: ...
         },
         .
         .
         .
      ]
   },
   .
   .
   .
]

Actual result:

[
   {
      id: ...,
      name: ...,
   },
   .
   .
   .
]

答案1

得分: 0

我建议使用@JsonManagedReference@JsonBackReference(后者用于子实体)来自com.fasterxml.jackson.annotation包。

另外在这里有解释:https://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion 第3节。

英文:

I suggest using @JsonManagedReference @JsonBackReference (latter to be used on the child entity) from the com.fasterxml.jackson.annotation package.

Also explained here: https://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion section 3

答案2

得分: 0

从类型表中移除Id的getter也会起作用。

英文:

Removing getter of Id from type table will also work

huangapple
  • 本文由 发表于 2020年8月10日 19:59:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/63339755.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定