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

use*_*465 0 javascript hateoas angularjs spring-data-rest 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
Run Code Online (Sandbox Code Playgroud)

“检索产品” sql将产品和类别连接在一起,以给出“显示友好名称”。Rest API检索带有此“类别名称”的“产品对象”。

Spring Data Rest域对象

产品

@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;
    }
}
Run Code Online (Sandbox Code Playgroud)

产品分类

@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;
    }

}
Run Code Online (Sandbox Code Playgroud)

问题

我删除了联接,并为产品和类别添加了Spring存储库。现在,“获取产品”静态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"
        }
      }
Run Code Online (Sandbox Code Playgroud)

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

"productCategory" : {
  "href" : "http://localhost:8080/api/rest/products/8/productCategory"
}
Run Code Online (Sandbox Code Playgroud)

我最初以为我可以检索类别,然后将“类别url”映射到“描述”。但是网址不同:

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

而产品具有以下内容:“ productCategory”:{“ href”:“ http:// localhost:8080 / api / rest / products / 8 / productCategory ”}

问题澄清

因此,如果javascript控制器http获得了以下产品:

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

那又如何呢?这些步骤是吗?

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

-将描述存储在页面上的某个地方以供重用(即,将其添加到javascript对象中)

如果是这些步骤:

  • 大量的代码
  • 对于较长的列表(例如50种产品),则还有100个http get请求。

即使我添加了一个调用以获取/缓存所有产品类别,仍然可以获得额外的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();
       }
    }
Run Code Online (Sandbox Code Playgroud)

但是,此url不返回类别名称:

http://localhost:8080/api/rest/products/4?projection=dummyNameForProjection
Run Code Online (Sandbox Code Playgroud)

返回的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"
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

另外,我为这些设置了调试功能

 logging.level.org.springframework.data=DEBUG
 logging.level.org.springframework.data.rest=DEBUG
 logging.level.org.hibernate=DEBUG
Run Code Online (Sandbox Code Playgroud)

日志/控制台未提及任何投影。

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

小智 5

春季投影

@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();
Run Code Online (Sandbox Code Playgroud)

}

只需在您的请求中包括投影名称即可:/ products?projection = dummyNameForProjection