当前位置: 首页 > 知识库问答 >
问题:

如何使用Spring数据REST的多态关联

齐永昌
2023-03-14

我在我的web应用程序中使用了Spring Boot1.5.7、Spring Data REST、Spring JPA、Hibernate、Spring HATEOAS、Spring Validation和Swagge。这个应用程序提供RESTendpoint,这些endpoint将由Angular客户机使用。

在我的模型中,许多实体都有一个note列表。用户、车票、退票等有一个列表 。根据我在网上找到的一些文档,这似乎是一个使用@any的好例子。这样会很方便,所以我也可以避免连接表(User_note、Ticket_note、Refund_note等)。

让我们看一个模型的例子:

@Entity
public class Note extends AbstractEntity {
    private static final long serialVersionUID = -5062313842902549565L;

    @Lob
    private String text;

     @RestResource(rel = "parent")
     @Any(fetch = FetchType.LAZY, optional = false, metaColumn = @Column(name ="item_type"))
     @AnyMetaDef(idType = "long", metaType = "string", metaValues = {
     @MetaValue(targetEntity = User.class, value = "User"),
     @MetaValue(targetEntity = Ticket.class, value = "Ticket"),
     @MetaValue(targetEntity = Refund.class, value = "Refund") })
     @JoinColumn(name = "item_id")
     private AbstractEntity parent;

您可以看到,父级是AbstractEntity,它是每个实体bean的超类。

@Entity
public class User extends AbstractEntity {

     private String name;

     @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
     private List<Note> notes = new ArrayList<>();
    null

问题所在

在这一点上,问题出现了。例如,如果您想要向用户添加一个便笺,您希望调用post/api/v1/users/{id}/notes,但不幸的是,您不能根据这个和这个。从文档看来,您可以只发布链接。仅仅因为一个便笺没有他的父母就不存在,我不能保存之前的便笺,然后使用链接将其加入用户。无论如何,即使有可能,我也不喜欢这样的想法:我希望所有的事情都在一个交易中。

好的,那么让我们看看enpoint注释。您将看到post http://localhost:8080/api/v1/notes,它似乎非常适合保存注释。如果不是这样,当您尝试保存如下注释时,就会出现这样的异常:

{
  "parent": 
    "http://localhost:8080/api/v1/users/1"
  ,
  "text": "string",
  "version": 0
}
{
  "timestamp": "2017-10-15T22:37:06.668+0000",
  "status": 400,
  "error": "Bad Request",
  "exception": "org.springframework.http.converter.HttpMessageNotReadableException",
  "message": "Il valore del campo <null> deve essere di tipo <null>; è stato invece ricevuto il valore <null> di tipo <null>. Correggere il dato e riprovare.",
  "path": "/api/v1/notes",
  "cause": {
    "exception": "com.fasterxml.jackson.databind.JsonMappingException",
    "message": "Can not construct instance of it.rebus.server.model.AbstractEntity: abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information\n at [Source: org.apache.catalina.connector.CoyoteInputStream@67a66b7d; line: 7, column: 5] (through reference chain: server.model.auditing.Note[\"parent\"])"
  }
}

结论

我想知道如何使用多态关联来解决我在使用SDR时遇到的这些问题。是否有一种方便的方法来达到这个目标,为模型的每个bean提供注释上的crud操作?(我希望避免每个bean都有一个特定的控制器)。

共有1个答案

欧阳俊捷
2023-03-14

我很确定你解决了你的问题,但我最近也有同样的问题。所以我会贴出我是如何解决它的,希望能帮助其他人。我必须在抽象类中指定反序列化策略。我使用了:

@JsonTypeInfo(use = Id.NAME, property = "@entityType")
 @JsonSubTypes({
        @JsonSubTypes.Type(value = User.class, name = "User"),
        @JsonSubTypes.Type(value = Ticket.class, name = "Ticket"),
        @JsonSubTypes.Type(value = Refund.class, name = "Refund"),
})

因此,在控制器级别,当我接收到POST请求时,我会稍微更改接收到的对象节点,根据您所说的“HTTP”属性值,将“@EntityType”属性添加到父子节点。现在做了这个小改动,Spring应该能够知道应该创建哪个具体类的实例。

 类似资料:
  • 我想知道如何通过REST调用删除多对多关联。我能够创建记录并将其关联,但不知道如何删除。 我有一个SpringBoot项目,在这个项目中,我使用REST和HATEOAS绕过服务和控制器,并直接公开我的存储库。 我有一个用户模型/域类 如您所见,我有一个roles成员,它与Role类有多对多的关联,其代码如下: 我的仓库看起来是这样的: 用户库 角色还原 现在一切都好了。当我从浏览器访问项目根目录时

  • 有以下URL-/users/2/profile、/users/2/userPosts 我需要在服务器端整合两个Spring Data REST结果的输出,并从它们构建单个JSON,并在不同的网址上发送。 所以,我想从SpringMVC中调用2个SDR URL,我们可以使用RestTemplate和一些JSON concat实用程序来实现这一点吗?这里服务器和数据库在同一台机器上,所以RestTem

  • 我的项目中有两个域对象,和。s分别与单个相关联。我正在使用Spring-Data-Rest,它是抽象,所以我有这个: 当我通过HTTP获取时,我会得到这个: 但是,我不能将相同的内容发回以首先创建文档。我发现最好的办法是发布以下内容: 然而,这似乎真的很奇怪,因为: a) 现在,我在对象中嵌入了一个未命名、未类型化的链接,这不是很HATEAOS(尽管Spring似乎正确地反序列化了它)。 b)我现

  • 我在通过REST向子类型暴露关系时遇到了问题。我有一个抽象类,名为Page: 当我从api获得一个Song实例时,json看起来如下所示: 问题是singer字段似乎是嵌入式的。我不能把一个现有的音乐家和这个歌手领域联系在一起。当我试图将现有音乐家的uri分配到singer字段时,它抱怨说它不能从String转换为Music。如果我提供json而不是uri,那么它将创建一个具有相同字段值的新Mus

  • @test public void generateToken(){ } 当以上述方式发送时,得到错误的请求。