在Spring JPA方面,在我的控制器中,我有:
@GetMapping()
public List<Product> getProducts() {
List<Product> products = repository.findAll();
int a = 1;
return products;
}
在Angular(6)服务中,我有:
getAll(): Observable<Product[]> {
return this.http.get<Product[]>(this.PRODUCT_API);
}
在Angular组件中,我有:
products: Product[] = [];
ngOnInit() {
this.productService.getAll().subscribe((data: Product[]) => {
console.log(data);
this.products = data;
});
}
在列表组件HTML中,数据库的4个产品中,第一个产品的属性正确发出,但其他3个字段中没有任何内容。
在浏览器的控制台中,我看到以下内容:
Array(4) [ {…}, 2, 3, 4 ] product-list.component.ts:19:6
我可以在Spring控制器中运行的代码中的虚假赋值上放置一个断点,并看到我正在按预期返回Product数组。但是,当它离开Spring并到达Angular时,该数组已变平为一个对象(第一个乘积)和3个数字。
一切似乎都正确键入。我不知道应该怎么做才能正确返回我的Product类型的数组。
根据从API端显示JSON的请求,我终于弄清楚了如何进行一些基本日志记录,并转储了产品列表。现在我更加困惑了。果然,Angular端正在准确显示它收到的内容:
[ {
"id" : 1,
"title" : "New Friggin Product",
"note" : "This is a note",
"createDateTime" : {
"month" : "AUGUST",
"year" : 2018,
"dayOfMonth" : 20,
"dayOfWeek" : "MONDAY",
"dayOfYear" : 232,
... <SNIP>
"second" : 59,
"monthValue" : 8,
"chronology" : {
"id" : "ISO",
"calendarType" : "iso8601"
}
},
"engine" : 1
} ]
}
}, 2, 3, 4 ]
JSON中有一个产品数组,然后是3个数字。
双重编辑!我已经列出了存储库代码,但是经过进一步的思考,repo类是正确的。它会在响应中返回4种正确的产品。
问题是转换为JSON,当我将响应返回到Angular时,我想我已经完全记录了Jackson库对List所做的事情。问题是,为什么在正确键入所有内容后。
答案 0 :(得分:0)
结果证明这是一个已知问题。 Jackson中的JSON渲染器在对象列表中未包含对重复的子对象的引用。出于某些奇怪的原因,这是设计使然。
要解决此问题,您需要在Spring端使用JSOG(https://github.com/jsog/jsog)在Angular端使用JSOG-Typescript(https://github.com/emundo/jsog-typescript)生成JSON响应。
请注意,您仍然需要@JsonBackReference
和@JsonManagedReferences
来防止无限递归循环。
我的期末课程如下:
Engine.java(父级)
@Entity
@Getter @Setter
@NoArgsConstructor
@ToString @EqualsAndHashCode
@JsonIdentityInfo(generator = JSOGGenerator.class)
public class Engine implements Serializable { //
@Id
@GeneratedValue(strategy=IDENTITY)
private Long id;
@NonNull
private String name;
private String family;
@CreationTimestamp
private LocalDateTime createDateTime;
@UpdateTimestamp
private LocalDateTime updateDateTime;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "engine")
@JsonBackReference
private Collection<Product> products;
}
Product.java(子级)
@Entity
@Getter @Setter
@NoArgsConstructor
@ToString @EqualsAndHashCode
@JsonIdentityInfo(generator = JSOGGenerator.class)
public class Product implements Serializable { //
@Id
@GeneratedValue(strategy=IDENTITY)
private Long id;
@NonNull
private String title;
private String note;
@CreationTimestamp
private LocalDateTime createDateTime;
@UpdateTimestamp
private LocalDateTime updateDateTime;
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "engine_id")
@JsonManagedReference
private Engine engine;
}
product-list.component.ts
import { Component, OnInit } from '@angular/core';
import { ProductService } from '../shared/product/product.service';
import { Product } from '../shared/models/product';
import { JsogService } from 'jsog-typescript';
@Component({
selector: 'app-product-list',
templateUrl: './product-list.component.html',
styleUrls: ['./product-list.component.css']
})
export class ProductListComponent implements OnInit {
products: Product[] = [];
constructor(private productService: ProductService) { }
ngOnInit() {
this.productService.getAll().subscribe(data => {
const jsog = new JsogService();
this.products = jsog.deserializeArray(data, Product);
});
}
}
此外,要完成上述工作,我必须在Angular组件中返回联合国类型的.getAll():
getAll(): Observable<any> {
return this.http.get(this.PRODUCT_API);
}