Spring 要创建的数据 JPA 和 PUT 请求
Spring Data JPA and PUT requests to create
所以我正在尝试使用 Spring Data JPA 来使用存储库接口制作一些休息服务。但是我一直在尝试做一些事情而不必创建自定义控制器。
假设这个服务只接受 PUT 和 GET 请求。 PUT 请求用于创建和更新资源。所以ID是客户端生成的。
实体和存储库将是这样的:
@Entity
public class Document {
@Id
private String name;
private String text;
//getters and setters
}
@RepositoryRestResource(collectionResourceRel = "documents", path = "documents")
public interface DocumentRepository extends PagingAndSortingRepository<Document, String> {
}
当我尝试使用以下主体发出 PUT 请求@localhost:8080/documents/foo时:
{
"text": "Lorem Ipsum dolor sit amet"
}
我收到这条消息:
{
"timestamp": 1474930016665,
"status": 500,
"error": "Internal Server Error",
"exception": "org.springframework.orm.jpa.JpaSystemException",
"message": "ids for this class must be manually assigned before calling save(): hello.Document; nested exception is org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): hello.Document",
"path": "/documents/foo"
}
所以我必须在正文中发送:
{
"name": "foo",
"text": "Lorem Ipsum dolor sit amet"
}
所以 returns 201 创建于
{
"text": "Lorem Ipsum dolor sit amet",
"_links": {
"self": {
"href": "http://localhost:8080/documents/foo"
},
"document": {
"href": "http://localhost:8080/documents/foo"
}
}
}
是否可以在不必在 json 正文中发送 id(名称字段)的情况下进行 PUT?因为我已经在 URI 中发送了它?
我知道我可以创建一个 RestController 和一些带有 /documents/{document.name} 的请求映射,并在保存之前用它来设置名称字段,但我想知道是否有注释什么的。
您可以定义一个 @HandleBeforeCreate
/ @HandleBeforeSave
方法来在保存之前更改模型:
@Component
@RepositoryEventHandler(Document.class)
public class DocumentBeforeSave {
@Autowired
private HttpServletRequest req;
@HandleBeforeCreate
public void handleBeforeSave(Document document) {
if("PUT".equals(req.getMethod())){
String uri = req.getRequestURI();
uri = uri.substring(uri.lastIndexOf('/') + 1);
document.setName(uri);
}
}
}
- 因为正文不包含任何id(此时),
POST
和PUT
都会触发@HandleBeforeCreate
方法(如果正文包含id
, PUT
请求宁愿触发 @HandleBeforeSave
).
- 我们需要在分配
id
之前检查 RequestMethod
是否为 PUT
(为了保持 POST
主体不变)。
HttpServletRequest
作为代理注入,可以被多线程使用。读这个:
所以我正在尝试使用 Spring Data JPA 来使用存储库接口制作一些休息服务。但是我一直在尝试做一些事情而不必创建自定义控制器。
假设这个服务只接受 PUT 和 GET 请求。 PUT 请求用于创建和更新资源。所以ID是客户端生成的。
实体和存储库将是这样的:
@Entity
public class Document {
@Id
private String name;
private String text;
//getters and setters
}
@RepositoryRestResource(collectionResourceRel = "documents", path = "documents")
public interface DocumentRepository extends PagingAndSortingRepository<Document, String> {
}
当我尝试使用以下主体发出 PUT 请求@localhost:8080/documents/foo时:
{
"text": "Lorem Ipsum dolor sit amet"
}
我收到这条消息:
{
"timestamp": 1474930016665,
"status": 500,
"error": "Internal Server Error",
"exception": "org.springframework.orm.jpa.JpaSystemException",
"message": "ids for this class must be manually assigned before calling save(): hello.Document; nested exception is org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): hello.Document",
"path": "/documents/foo"
}
所以我必须在正文中发送:
{
"name": "foo",
"text": "Lorem Ipsum dolor sit amet"
}
所以 returns 201 创建于
{
"text": "Lorem Ipsum dolor sit amet",
"_links": {
"self": {
"href": "http://localhost:8080/documents/foo"
},
"document": {
"href": "http://localhost:8080/documents/foo"
}
}
}
是否可以在不必在 json 正文中发送 id(名称字段)的情况下进行 PUT?因为我已经在 URI 中发送了它?
我知道我可以创建一个 RestController 和一些带有 /documents/{document.name} 的请求映射,并在保存之前用它来设置名称字段,但我想知道是否有注释什么的。
您可以定义一个 @HandleBeforeCreate
/ @HandleBeforeSave
方法来在保存之前更改模型:
@Component
@RepositoryEventHandler(Document.class)
public class DocumentBeforeSave {
@Autowired
private HttpServletRequest req;
@HandleBeforeCreate
public void handleBeforeSave(Document document) {
if("PUT".equals(req.getMethod())){
String uri = req.getRequestURI();
uri = uri.substring(uri.lastIndexOf('/') + 1);
document.setName(uri);
}
}
}
- 因为正文不包含任何id(此时),
POST
和PUT
都会触发@HandleBeforeCreate
方法(如果正文包含id
,PUT
请求宁愿触发@HandleBeforeSave
). - 我们需要在分配
id
之前检查RequestMethod
是否为PUT
(为了保持POST
主体不变)。 HttpServletRequest
作为代理注入,可以被多线程使用。读这个: