嵌套在HAL中使用Spring HATEOAS

时间:2016-02-29 22:41:30

标签: java rest spring-hateoas hal hypermedia

我正在寻找使用Spring HATEOAS API如何在HAL中嵌套_embedded的示例。什么是最佳做法?

这是我想要实现的一个例子:

{
    "_links": {
        "self": { "href": "/invoices" }
    },
    "_embedded": {
        "invoices": [
            {
                "_links": {
                    "self": { "href": "/invoice/1" }
                },
                "_embedded": {
                    "items": [
                        { "_links": { "self": { "href": "/product/1" }}, "id": 1, "name": "Super cheap Macbook Pro", "price": 2.99 }
                    ]
                },
                "id": 1,
                "total": 2.99,
                "no_items": 1
            },
            {
                "_links": {
                    "self": { "href": "/invoice/2" }
                },
                "_embedded": {
                    "items": [
                        { "_links": { "self": { "href": "/product/2" }}, "id": 2, "name": "Raspberry Pi", "price": 34.87 },
                        { "_links": { "self": { "href": "/product/3" }}, "id": 3, "name": "Random product", "price": 30 },
                        { "_links": { "self": { "href": "/product/4" }}, "id": 4, "name": "More randomness", "price": 30 }
                    ]
                },
                "id": 2,
                "total": 94.87,
                "no_items": 3
            }
        ]
    }
}

1 个答案:

答案 0 :(得分:0)

使用Spring Data REST和Spring HATEOAS,我看到了两种方法可以轻松实现您想要的功能。

  1. 创建Invoice和Item实体,并仅为Invoice实体创建存储库。这将内联项目。在缺点方面,您无法查询自己的项目,这可能不是您想要的。
  2. 创建两个实体并为它们创建存储库。现在在Invoice存储库上创建一个Excerpt,可以查询并嵌入项目并包含相应的链接集合。但也有一个缺点:嵌入式项目不会有链接。我认为你应该可以通过在投影中使用资源来包含链接。
  3. 使用Order with Items:

    查看一些示例代码
    @Data
    @Entity
    public class Item {
      @Id
      @GeneratedValue
      private Long id;
      private String name;
    }
    
    @Data
    @Entity
    @Table(name = "customer_order")
    public class Order {
      @Id
      @GeneratedValue
      private Long id;
      private String name;
      @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
      private Collection<Item> items;
    }
    
    public interface ItemRepository extends CrudRepository<Item, Long> {
    }
    
    @RepositoryRestResource(excerptProjection = InlineItems.class)
    public interface OrderRepository extends CrudRepository<Order, Long> {
    }
    
    @Projection(name = "inlineItems", types = Order.class)
    public interface InlineItems {
      String getName();
    
      Collection<Item> getItems();
    }
    

    您可以查询此GET http://localhost:8080/orders/1?projection=inlineItems之类的订单,这会产生以下结果:

    {
      "name": "My Order",
      "items": [
        {
          "name": "Banana"
        },
        {
          "name": "Apple"
        }
      ],
      "_links": {
        "self": {
          "href": "http://localhost:8090/api/orders/1"
        },
        "order": {
          "href": "http://localhost:8090/api/orders/1{?projection}",
          "templated": true
        },
        "items": {
          "href": "http://localhost:8090/api/orders/1/items"
        }
      }
    }