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

出租

介绍

假设在带有Spring Data Rest模块的Spring Boot应用程序中,有两个主要实体(例如StudentLegalGuardian)。它们通过Guardianship由嵌入式ID(例如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, setters, equals and hashCode

  }

}

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

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

要查询单个GuardianshipS的GuardianshipRepository通过REST的ID,也是一个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",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/guardianships/1_2"
    },
    "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",
    "new" : false
  },
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/guardianships/1_2"
    },
    "guardianship" : {
      "href" : "http://localhost:8080/guardianships/1_2"
    }
  }
}

举一个完整的例子,我创建了一个可执行的示例项目

出租

经过一些搜索,我发现了两种将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"
    }
  }
}

优点:

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

带有:

  • 更多的关联类导致更多的实现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",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/guardianships/1_2"
    },
    "guardianship" : {
      "href" : "http://localhost:8080/guardianships/1_2"
    }
  }
}

优点:

  • 较少的“实现”

带有:

  • (采用这种形式)与原始所需的响应表示形式不完全匹配(请参见guardianshipId链接周围的-wrapper)

编辑

对于方式二:要公开所有使用嵌入式(复合)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);                                                      
      }                                                                                       
    });                                                                                       
  }                                                                                           
                                                                                              
}                                                                                             
                                                                                              

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Spring Data REST-检测到多个具有相同关系类型的关联链接

如何通过自链接在Spring Data REST Server中加载实体?

如何使用Spring Data REST仅公开可写的REST API?

为什么Spring Data REST包含“重复”链接?

扩展Spring Data Rest索引资源链接

Spring Data Rest将链接添加到根-RepositoryLinksResource无法转换为Resource

调用Spring Data Rest Repository方法不会返回链接

如何添加到Spring Data REST投影的链接?

嵌入式实体的Spring Data Rest投影

将链接添加到Spring Data REST Repository资源

Spring Data Rest-将链接添加到搜索端点

如何简单地添加到Spring Data REST实体的链接

Spring Data Rest-代理路径不包括链接路径

资源上的Spring Data Rest自定义链接

将图像插入为嵌入式而不是链接

Spring Data Rest-关联资源的自我链接

使用嵌入式码头,如何将ServerConnector链接到服务器?

空或为空时,Spring Data ReST ref链接遗漏

使用spring-data-rest将@Service方法公开为Rest端点

Spring Data REST为嵌入式集合错误生成链接

如何将嵌入式链接添加到 html 5 视频

如何使用自定义 Spring Data Rest Controller 将现有链接扩展到资源

如何将链接放入带有嵌入式模板的页面?

如何将 catalina.out 文件与嵌入式 tomcat 链接

使用 Spring Data Rest 默认链接创建

如何限制对 Spring Data Rest 中子链接的访问?

Spring Data Rest - 嵌入式实体未在 POST 上反序列化

我如何将 CORS 添加到 Spring Data rest 公开的“/profile”端点

关系中的 Spring Data Rest 和实体的 ID