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(此时),POSTPUT都会触发@HandleBeforeCreate方法(如果正文包含id, PUT 请求宁愿触发 @HandleBeforeSave).
  • 我们需要在分配 id 之前检查 RequestMethod 是否为 PUT(为了保持 POST 主体不变)。
  • HttpServletRequest作为代理注入,可以被多线程使用。读这个: