如何循环并从HATEOAS _link属性中检索值(例如,检索描述)? [英] How to loop and retrieve value from HATEOAS _link attribute (e.g. retrieve a description)?
问题描述
tl; dr
我的代码从Restful GET获取了一个javascript/json对象数组.如何编写代码以循环并从HATEOAS"_link"属性中检索描述(或任何值)以进行显示?
上下文
我继承了一个基于Spring的小项目-它跟踪服务器,软件安装等,以供我们团队内部使用.它使用Angular前端和Spring/java/mysql后端实现宁静的后端.
I've inherited a small Spring-based project --it tracks servers, software installations, etc for our team's internal use. It uses Angular front end and Spring/java/mysql back end for a restful back end.
我正在将手动编码的SQL转换为JPA和"Spring Starter Data Rest".
I'm in the process of converting the hand-coded SQL to JPA and 'spring starter data rest'
当前的API可以
当前的手工编码SQL连接表以提供显示友好的结果".
The current handcoded SQL joins tables to give "display friendly results".
Product
---------
Product ID
Product Name
Category ID
Category
---------
Category ID
Category Name
检索产品" sql将产品和类别连接在一起,以给出显示友好名称". Rest API检索带有此类别名称"的产品对象".
The 'retrieve products' sql joins product and category to give a 'display friendly name'. The Rest API retrieves an 'product object' with this 'category name' tacked on.
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;
}
}
产品类别
@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存储库.现在,获取产品"静态API将返回以下列表:
I've removed the joins, and added Spring repositories for Product and Category. The 'get products' restful API now returns a list of these:
{
"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"链接的类别名称?
How do I display the category name for the "productCategory" link?
"productCategory" : {
"href" : "http://localhost:8080/api/rest/products/8/productCategory"
}
最初,我认为我可以检索类别,然后将类别url"映射到描述".但是网址不同:
I initially thought I could retrieve the categories, then build a map of 'category url' to 'description.' However the url's differ:
产品类别"网址看起来像这样: http://localhost:8080/api/rest/productcat/1
The 'product category' url looks liks this: http://localhost:8080/api/rest/productcat/1
该产品具有以下特点: 产品分类" : { "href":" http://localhost:8080/api/rest/products/8/productCategory " }
Whereas the Product has this: "productCategory" : { "href" : "http://localhost:8080/api/rest/products/8/productCategory" }
问题澄清
因此,如果javascript控制器http获得了该产品:
so if the javascript controller http gets the products:
requests.get(productsUrl, $scope).success(function(data, status){
$scope.models = data._embedded.products;
});
那又怎样?这些步骤了吗?
So then what? Are these the steps?
javascript控制器循环遍历每个data._embedded.products.每个产品的代码
The javascript controller loops through each data._embedded.products. for each product, the code
-
http获取产品类别网址
http gets the product category url
productCategory":{ "href":" http://localhost:8080/api/rest/products/8/productCategory " }
productCategory" : { "href" : "http://localhost:8080/api/rest/products/8/productCategory" }
http获取类别
"productCategory":{
"productCategory": {
"href": "http://localhost:8080/api/rest/productcat/4"
},
-将描述存储在页面上的某个地方以供重复使用(即,将其添加到javascript对象中)
-stores the description somewhere for reuse on the page (i.e. adding it to the javascript object )
如果这些步骤是:
- 很多代码
- 对于较长的列表(例如50种产品),这是另外100个http get请求.
即使我添加了一个获取/缓存所有产品类别的调用,那仍然是额外的50个http获取
Even if I add a call to get/cache all product categories, that's still an extra 50 http gets
奖励:
- 易于编码
- 运行速度快
尝试#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();
}
}
但是,此网址未返回类别名称:
However this url does not return the category name:
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"
}
}
}
另外,我为这些设置了调试
Additionally, I set debugging on for these
logging.level.org.springframework.data=DEBUG
logging.level.org.springframework.data.rest=DEBUG
logging.level.org.hibernate=DEBUG
日志/控制台未提及任何投影.
Log/console do not mention any projections.
尝试#02:固定投影 在D下归档D'oh.我将投影卡在存储库上而不是实体上.查看一些示例代码显示了此问题.投影就是门票!
Attempt #02: Fixed Projections File under D for D'oh. I stuck projection on the repository not on the entity. Reviewing some sample code showed the issue. Projections are the ticket!