我正在使用Spring Boot 1.5.7,Spring Data REST,Spring JPA,Hibernate,Spring HATEOAS,Spring Validation和Swagge来构建我的Web应用程序。
该应用程序提供REST端点,将由Angular客户端使用。
介绍
在我的模型中,许多实体都有一个
让我们看一个模型的例子:
这样做,Hibernate会创建一个Note表,其中包括两个额外的列(id和type)来映射相关对象。
到目前为止,一切都像预期的那样。问题在于REST方面。
主要需要执行以下几个操作:
好的,让我们看看enpoint Note。您将看到一个
这是可以理解的。Spring不了解要创建哪个AbstractEntity的具体类。我希望它能从URI中发现,但似乎不行。
那么我们尝试获取用户的所有笔记。在这种情况下,有一个端点
介绍
在我的模型中,许多实体都有一个
Note
列表。用户,票,退款等都有一个List<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<>();
这样做,Hibernate会创建一个Note表,其中包括两个额外的列(id和type)来映射相关对象。
到目前为止,一切都像预期的那样。问题在于REST方面。
主要需要执行以下几个操作:
- 为特定父实体(用户、票务等)插入注释
- 获取特定实体的注释列表
- 从特定实体的注释列表中删除注释
POST /api/v1/users/{id}/notes
,但不幸的是根据this和this,您无法这样做。从文档中看来,似乎只能发布链接。而且,由于没有父级,笔记不存在,我不能先保存笔记,然后使用链接将其连接到用户。无论如何,即使可能,我也不喜欢这个想法:我希望所有内容都在事务内完成。好的,让我们看看enpoint Note。您将看到一个
POST http://localhost:8080/api/v1/notes
,似乎非常适合保存Note。如果您尝试像这样持久化笔记,您将会遇到此异常:{
"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\"])"
}
}
这是可以理解的。Spring不了解要创建哪个AbstractEntity的具体类。我希望它能从URI中发现,但似乎不行。
那么我们尝试获取用户的所有笔记。在这种情况下,有一个端点
GET http://localhost:8080/api/v1/users/1/notes
,但我没有成功,因为该端点返回一个HTTP 405错误(我打开了一个相关问题)。
结论
我想知道如何解决我使用SDR和多态关联时遇到的问题。是否有一种方便的方法来实现对模型中每个bean的笔记进行crud操作?(我想避免为每个bean都有一个特定的控制器)。