微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何将联接表中嵌入式ID的关系公开为与Spring Data Rest的链接

如何解决如何将联接表中嵌入式ID的关系公开为与Spring Data Rest的链接

简介

假设在带有Spring Data Rest模块的Spring Boot应用程序中,有两个主要实体(例如StudentLegalGuardian)。它们通过由嵌入式ID(例如Guardianship)标识的“关联实体”(例如GuardianshipId)加入。此外,此嵌入的ID包含与两个主要实体的关系(不是主要实体的ID,即实体本身)。

// The Main entities

@Entity
public class Student extends AbstractPersistable<Long> {

  private String name;
  
  @OnetoMany(mappedBy = "guardianshipId.student")
  private List<Guardianship> guardianships;
  
  // getters and setters
  
}

@Entity
public class LegalGuardian extends AbstractPersistable<Long> {

  private String name;
  
  @OnetoMany(mappedBy = "guardianshipId.legalGuardian")
  private List<Guardianship> guardianships;
  
  // getters and setters
  
}

// The association entity

@Entity
public class Guardianship implements Serializable {

  @EmbeddedId
  private GuardianshipId guardianshipId;
  
  private String name;
  
  // getters,setters,equals and hashCode

  @Embeddable
  public static class GuardianshipId implements Serializable {

    @ManyToOne
    private Student student;
    
    @ManyToOne
    private LegalGuardian legalGuardian;
    
    // getters,equals and hashCode

  }

}

对于所有这些实体,都有单独的存储库:

  • StudentRepository : JpaRepository<Student,Long>
  • LegalGuardianRepository : JpaRepository<LegalGuardian,Long>
  • GuardianshipRepository : JpaRepository<Guardianship,Guardianship.GuardianshipId>

要通过REST通过ID查询Guardianship中的单个GuardianshipRepository,还实现了BackendIdConverter(因此,该ID类似于 {studentId} _ {legalGuardianId} )。

如果请求关联实体的存储库,则认情况下,嵌入式id本身(及其属性)未序列化,因此响应如下所示:

$ curl "http://localhost:8080/guardianships/1_2"
{
  "name" : "Cool father","_links" : {
    "self" : {
      "href" : "http://localhost:8080/guardianships/1_2"
    },"guardianship" : {
      "href" : "http://localhost:8080/guardianships/1_2"
    }
  }
}

问题/问题

要做些什么,以便响应包括与包含在嵌入ID中的实体的链接链接,如下所示:

$ curl "http://localhost:8080/guardianships/1_2"
{
  "name" : "Cool father","guardianship" : {
      "href" : "http://localhost:8080/guardianships/1_2"
    },"student" : {
      "href" : "http://localhost:8080/guardianships/1_2/student"
    },"legalGuardian" : {
      "href" : "http://localhost:8080/guardianships/1_2/legalGuardian"
    }
  }
}

(天真无味)尝试/尝试

一个想法是通过委派嵌入的id来使嵌套关系可访问:

@Entity
public class Guardianship implements Serializable {

  @EmbeddedId
  private GuardianshipId guardianshipId;
  
  public Student getStudent() { return guardianshipId.getStudent(); }
  
  public LegalGuardian getLegalGuardian() { return guardianshipId.getLegalGuardian(); }
  
  // the same as before

}

但是,这两个实体都已完全序列化,响应如下所示:

$ curl "http://localhost:8080/guardianships/1_2"
{
  "name" : "Cool father","student" : {
    "name" : "Hans","new" : false
  },"legalGuardian" : {
    "name" : "Peter","guardianship" : {
      "href" : "http://localhost:8080/guardianships/1_2"
    }
  }
}

一个完整的例子,我创建了一个可执行文件sample project

解决方法

经过一些搜索,我发现了两种将ID关系公开为链接的可能方法:

1。提供RepresentationModelProcessor

通过实施RepresentationModelProcessor,我可以向响应表示添加自定义链接。

@Component
public class GuardianshipProcessor
    implements RepresentationModelProcessor<EntityModel<Guardianship>> {

  @Autowired
  private RepositoryEntityLinks repositoryEntityLinks;

  @Override
  public EntityModel<Guardianship> process(EntityModel<Guardianship> model) {
    Link studentLink = repositoryEntityLinks.linkToItemResource(Student.class,model.getContent().getGuardianshipId().getStudent().getId());
    model.add(studentLink);
    Link legalGuardianLink = repositoryEntityLinks.linkToItemResource(LegalGuardian.class,model.getContent().getGuardianshipId().getLegalGuardian().getId());
    model.add(legalGuardianLink);
    return model;
  }

}
$ curl "http://localhost:8080/guardianships/1_2"
{
  "name" : "Cool father","_links" : {
    "self" : {
      "href" : "http://localhost:8080/guardianships/1_2"
    },"guardianship" : {
      "href" : "http://localhost:8080/guardianships/1_2"
    },"student" : {
      "href" : "http://localhost:8080/students/1"
    },"legalGuardian" : {
      "href" : "http://localhost:8080/legalGuardians/2"
    }
  }
}

Pro:

  • 完全匹配所需的响应表示形式

Con:

  • 更多的关联类导致RepresentationModelProcessor的更多实现或多或少都相同

2。配置RepositoryRestConfiguration以公开ID的

默认情况下,Spring Data Rest不公开ID,尽管该主题是关于嵌入式ID的,但它们也是ID。这种行为是可以逐级配置的。

@Configuration
public class RepositoryConfig implements RepositoryRestConfigurer {

  @Override
  public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
    config.exposeIdsFor(Guardianship.class);
  }
  
}
$ curl "http://localhost:8080/guardianships/1_2"
{
  "guardianshipId" : {
    "_links" : {
      "student" : {
        "href" : "http://localhost:8080/students/1"
      },"legalGuardian" : {
        "href" : "http://localhost:8080/legalGuardians/2"
      }
    }
  },"name" : "Cool father","guardianship" : {
      "href" : "http://localhost:8080/guardianships/1_2"
    }
  }
}

Pro:

  • 较少的“实现”

Con:

  • (以这种形式)与原始所需的响应表示形式不完全匹配(请参见链接周围的guardianshipId包装器)

修改

方法二:公开使用嵌入式(复合)id的实体的所有ID,如下所示:

@Configuration                                                                                
public class RepositoryRestConfig implements RepositoryRestConfigurer {                       
                                                                                              
  @Autowired                                                                                  
  Repositories repositories;                                                                  
                                                                                              
  @Override                                                                                   
  public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {      
    repositories.forEach(repository -> {                                                      
      Field embeddedIdField =                                                                 
          ReflectionUtils.findField(repository,new AnnotationFieldFilter(EmbeddedId.class)); 
      if (embeddedIdField != null) {                                                          
        config.exposeIdsFor(repository);                                                      
      }                                                                                       
    });                                                                                       
  }                                                                                           
                                                                                              
}                                                                                             
                                                                                              

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。