如何从HATEOAS _link属性循环和检索值(例如检索描述)?

时间:2017-06-14 21:26:20

标签: javascript angularjs spring-data-rest hateoas spring-hateoas

tl; dr

我的代码从Restful GET获取一个javascript / json对象数组。如何编写代码以循环并从HATEOAS“_link”属性中检索(以显示)描述(或任何值)?

上下文

我继承了一个基于Spring的小项目 - 跟踪服务器,软件安装等,以供我们团队内部使用。它使用Angular前端和Spring / java / mysql后端来实现一个宁静的后端。

我正在将手工编码的SQL转换为JPA和'spring starter data rest'

当前API

当前手动编码的SQL连接表以提供“显示友好结果”。

Product
---------
Product ID
Product Name
Category ID

Category
---------
Category ID
Category Name

'检索产品'sql连接产品和类别以提供'显示友好名称'。 Rest API会检索一个“产品对象”,并附上此“类别名称”。

Spring Data Rest Domain Objects

产品

@Entity
@Table(name="products")
public class Products
{

    private static final long serialVersionUID = 5697367593400296932L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)

    public long id;

    public String product_name;

    @ManyToOne(optional = false,cascade= CascadeType.MERGE)
    @JoinColumn(name = "category_id")
    private ProductCategory productCategory;

    public Products(){}

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public Products(String product_name) {
        this.product_name = product_name;
    }

    public String getProduct_name() {
        return product_name;
    }

    public void setProduct_name(String product_name) {
        this.product_name = product_name;
    }

    public ProductCategory getProductCategory()
    {
        return productCategory;
    }

    public void setProductCategory(ProductCategory pProductCategory)
    {
        productCategory = pProductCategory;
    }
}

产品类别

@Entity
@Table(name="productcat")

public class ProductCategory implements Serializable{

        private static final long serialVersionUID = 890485159724195243L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public long id;
    public String category;

    @OneToMany(mappedBy = "productCategory", cascade = CascadeType.ALL)
    @JsonBackReference
    Set<Products> products;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    public Set<Products> getProducts() {
        return products;
    }

}

问题

我删除了联接,并添加了产品和类别的Spring存储库。 'get products'restful API现在返回以下列表:

{
      "product_name" : "ForceFive 1.0",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/api/rest/products/8"
        },
        "products" : {
          "href" : "http://localhost:8080/api/rest/products/8"
        },
        "productCategory" : {
          "href" : "http://localhost:8080/api/rest/products/8/productCategory"
        }
      }

问题

如何显示“productCategory”链接的类别名称?

"productCategory" : {
  "href" : "http://localhost:8080/api/rest/products/8/productCategory"
}

我最初认为我可以检索类别,然后构建“类别网址”到“描述”的地图。然而,网址不同:

'产品类别'网址看起来像这样:     http://localhost:8080/api/rest/productcat/1

而产品具有:     “产品分类” : {       “href”:“http://localhost:8080/api/rest/products/8/productCategory”     }

问题澄清

所以如果javascript控制器http获取产品:

requests.get(productsUrl, $scope).success(function(data, status){
    $scope.models = data._embedded.products;  
});

那么呢?这些是步骤吗?

javascript控制器遍历每个data._embedded.products。对于每个产品,代码

- 将描述存储在某处以便在页面上重复使用(即将其添加到javascript对象中)

如果是以下步骤:

  • 这是很多代码
  • 为长列表(例如50个产品),这是另外100个http获取请求。

即使我添加了一个调用来获取/缓存所有产品类别,这仍然是额外的50个http获取

奖励:

  • 易于编码
  • 快跑

尝试#01:添加了预测

我添加了这个预测:

  public interface ProductRepository extends PagingAndSortingRepository<Products, Long>
    {

       @Projection(name = "dummyNameForProjection", types = { Products.class })
       interface VirtualProjection
       {

          String getProduct_name() ;
          //Get Product Category
          @Value("#{target.productCategory.category}")
          String getCategoryName();
       }
    }

但是,此网址不会返回类别名称:

http://localhost:8080/api/rest/products/4?projection=dummyNameForProjection

返回json

{
    "product_name": "Force Five",
    "_links": {
        "self": {
            "href": "http://localhost:8080/api/rest/products/4"
        },
        "products": {
            "href": "http://localhost:8080/api/rest/products/4"
        },
        "productCategory": {
            "href": "http://localhost:8080/api/rest/products/4/productCategory"
        }
    }
}

另外,我为这些

设置了调试
 logging.level.org.springframework.data=DEBUG
 logging.level.org.springframework.data.rest=DEBUG
 logging.level.org.hibernate=DEBUG

日志/控制台没有提及任何预测。

尝试#02:修正预测 D下的文件为D'哦。我将投影卡在存储库而不是实体上。查看一些示例代码显示了该问题。预测是门票!

1 个答案:

答案 0 :(得分:4)

Spring Projection

@Projection(name = "dummyNameForProjection", types = { Product.class })
public interface VirtualProjection {

// this will get the attribute name from the product entity
String getProductName();

//this will get the name of the category entity related to the product
@Value("#{target.category.name}") 
String getCategoryName();

}

Just include projection name in your request ex: /products?projection=dummyNameForProjection