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" : "localhost:8080/api/rest/products/8" }, "products" : { "href" : "localhost:8080/api/rest/products/8" }, "productCategory" : { "href" : "localhost:8080/api/rest/products/8/productCategory" } }问题
如何显示"productCategory"链接的类别名称?
How do I display the category name for the "productCategory" link?
"productCategory" : { "href" : "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:
产品类别"网址看起来像这样: localhost:8080/api/rest/productcat/1
The 'product category' url looks liks this: localhost:8080/api/rest/productcat/1
该产品具有以下特点: 产品分类" : { "href":" localhost:8080/api/rest/products/8/productCategory " }
Whereas the Product has this: "productCategory" : { "href" : "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":" localhost:8080/api/rest/products/8/productCategory " }
productCategory" : { "href" : "localhost:8080/api/rest/products/8/productCategory" }
http获取类别
"productCategory":{
"productCategory": {
"href": "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:
localhost:8080/api/rest/products/4?projection=dummyNameForProjection返回的json
{ "product_name": "Force Five", "_links": { "self": { "href": "localhost:8080/api/rest/products/4" }, "products": { "href": "localhost:8080/api/rest/products/4" }, "productCategory": { "href": "localhost:8080/api/rest/products/4/productCategory" } } }另外,我为这些设置了调试
Additionally, I set debugging on for these
logging.level.springframework.data=DEBUG logging.level.springframework.data.rest=DEBUG logging.level.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!
推荐答案春季投影
@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();}
只需在您的请求中包括投影名称,例如:/products?projection = dummyNameForProjection
Just include projection name in your request ex: /products?projection=dummyNameForProjection
更多推荐
如何循环并从HATEOAS
发布评论