RESTful API与Spring Boot的循环依赖关系

时间:2017-05-24 22:19:36

标签: java hibernate rest api spring-boot

我正在使用Spring Boot开发Rest API,使用Hibernate和Maven作为存储库管理器开发JPA。在我的模型中,我有班级Club

@Entity
@Table( name = "CLUB")
public class Club {

   /**
    * Id da entidade
    */
   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   private Long id;

    /**
    * Atual técnico do clube.
    */
   @OneToOne(mappedBy = "actualClub")
   private Coach coach;
   
   //Outros atributos, getters e setters
  }

上述课程与班级@OneToOne之间存在Coach关系:

@Entity
@Table(name = "COACH")
public class Coach extends Person {

   /**
    * Clube atual do técnico.
    */
   @OneToOne
   @JoinColumn(name = "CLUB_ID")
   private Club actualClub;

   //Outros atributos, getters e setters
   
}

课程Person还有一个带有@Id@GeneratedValue注释的 id 属性。

最后,我还有控制器类ClubController,它可以处理一些请求,如下所示:

@RestController
public class ClubController {

   /**
    * Instância da classe de serviços da entidade <i>Club</i>
    */
   @Autowired
   private ClubService clubService;

   /**
    * Retorna JSON que representa o clube com o 'id' especificado.
    *
    * @param id Identificador do clube a ser buscado.
    * @return ResponseEntity Objeto com detalhes da requisição HTTP, como o Status.
    */
   @RequestMapping(value = "/clubs/{id}", produces = MediaType.APPLICATION_JSON_VALUE,
           method = RequestMethod.GET)
   public ResponseEntity<?> getClubById(@PathVariable Long id) {

      final Club club = this.clubService.findById(id);
      if (club != null) {
         return new ResponseEntity<>(club, HttpStatus.FOUND);
      } else {
         return new ResponseEntity<>("Não encontrado", HttpStatus.NOT_FOUND);
      }
   }
   
   /*Entre outros métodos...*/
   
}

问题是:在GET /clubs/{id}中,返回的JSON内部有一个循环(无限)依赖。俱乐部有一个教练,有一个俱乐部,所以它... ...( 这也适用于@OneToMany relationship between分会and播放器......

我找到了这个解决方案:Link。我只需要在类声明中使用@JsonIdentityInfo注释。此解决方案的问题是我不会使用的信息开销(只需考虑@OneToManyPlayer的关系)。此外,正如您在上面的链接中所看到的那样:

  

“但是,JSON id引用在整个图形中必须是唯一的,而JPA id只需要在同一个实体中是唯一的。”“

因此,我必须将UUID用于JPA id字段。

我还找到了另一种可能的解决方案:Spring HATEOAS。在这种情况下,我可以为某些属性添加链接(href),只需将请求“按需”。但是看起来Spring HATEOAS有一些限制,比如支持嵌入资源......

那么,我应该遵循哪种方法?还有其他解决方案吗?

很快,我打算在iOS应用程序中使用此API(我不知道它是否有所不同)。

抱歉我的英语不好......来自巴西的问候x)

2 个答案:

答案 0 :(得分:1)

@JsonIgnoreProperties注释两个关系

如下

// Employee entity, owning side of relationship 
@ManyToOne(cascade = CascadeType.ALL)
@JsonIgnoreProperties("employee")
private Department department;

// Department side, inverse side of relationship
@OneToMany(mappedBy = "department")
@JsonIgnoreProperties("department")
private Collection<Employee> employee;

答案 1 :(得分:0)

创建自己的DTO(https://en.wikipedia.org/wiki/Data_transfer_object

可以解决此问题

数据传输对象(DTO)是一种Java结构,仅用于组织数据以传输到另一个系统。它是根据需要创建的,没有不相关或私人信息,也没有循环引用。

例如:

private Map<String, Object> makeClubDTO(Club club) {
  Map<String, Object> dto = new LinkedHashMap<String, Object>();
  dto.put("id", club.getId());
  dto.put("coach", club.getCoach().getId());
  return dto;
}