【发布时间】:2016-10-09 14:13:40
【问题描述】:
我有 3 个实体(产品、提供商和价格),其中价格与其他 2 个相关联。一个产品可以有多个价格,每个提供商一个价格:
产品类别:
@Entity
@Table(name = "products")
public class Product implements java.io.Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "product_id")
private int id;
@Column(name = "product_category")
private String productCategory;
@Column(name = "product_subcategory")
private String productSubcategory;
@Column(name = "product_name")
private String productName;
@Column(name = "product_description")
private String productDescription;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.product", cascade=CascadeType.ALL)
private Set<Prices_1> prices_1 = new HashSet<Prices_1>(0);
public Set<Prices_1> getPrices_1(){
return prices_1;
}
public void setPrices_1(Set<Prices_1> prices_1){
this.prices_1 = prices_1;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getProductCategory() {
return productCategory;
}
public void setProductCategory(String productCategory) {
this.productCategory = productCategory;
}
public String getProductSubcategory() {
return productSubcategory;
}
public void setProductSubcategory(String productSubcategory) {
this.productSubcategory = productSubcategory;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getProductDescription() {
return productDescription;
}
public void setProductDescription(String productDescription) {
this.productDescription = productDescription;
}
@Override
public String toString() {
return "ProductController [id=" + id + ", productName=" + productName
+ ", productCategory=" + productCategory + ", productSubcategory=" + productSubcategory
+ ", productDescription=" + productDescription
+ "]";
}
}
提供者类:
@Entity
@Table(name="providers")
public class Provider implements java.io.Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="provider_id")
private int id;
@Column(name="provider_name")
private String providerName;
@Column(name="provider_address")
private String providerAddress;
@Column(name="provider_phone")
private String providerPhone;
@Column(name="provider_archived")
private int providerArchived = 0;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.provider")
private Set<Prices_1> prices_1 = new HashSet<Prices_1>(0);
public Set<Prices_1> getPrices_1() {
return prices_1;
}
public void setPrices_1(Set<Prices_1> prices_1) {
this.prices_1 = prices_1;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getProviderName() {
return providerName;
}
public void setProviderName(String providerName) {
this.providerName = providerName;
}
public String getProviderAddress() {
return providerAddress;
}
public void setProviderAddress(String providerAddress) {
this.providerAddress = providerAddress;
}
public String getProviderPhone() {
return providerPhone;
}
public void setProviderPhone(String providerPhone) {
this.providerPhone = providerPhone;
}
public int getProviderArchived() {
return providerArchived;
}
public void setProviderArchived(int providerArchived) {
this.providerArchived = providerArchived;
}
@Override
public String toString() {
return "ProviderController [id=" + id + ", providerName=" + providerName
+ ", providerAddress=" + providerAddress + ", providerPhone="
+ providerPhone + "]";
}
}
Prices_1 类:
@Entity
@Table(name = "prices_1")
@AssociationOverrides({
@AssociationOverride(name = "pk.product",
joinColumns = @JoinColumn(name = "product_id")),
@AssociationOverride(name = "pk.provider",
joinColumns = @JoinColumn(name = "provider_id"))})
public class Prices_1 implements java.io.Serializable {
@EmbeddedId
private PricesId pk = new PricesId();
@Column(name = "price")
private float price;
public PricesId getPk() {
return pk;
}
public void setPk(PricesId pk) {
this.pk = pk;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
@Transient
public Product getProduct() {
return getPk().getProduct();
}
public void setProduct(Product product) {
getPk().setProduct(product);
}
@Transient
public Provider getProvider() {
return getPk().getProvider();
}
public void setProvider(Provider provider) {
getPk().setProvider(provider);
}
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Prices_1 that = (Prices_1) o;
if (getPk() != null ? !getPk().equals(that.getPk())
: that.getPk() != null)
return false;
return true;
}
public int hashCode() {
return (getPk() != null ? getPk().hashCode() : 0);
}
}
PricesID 类:
@Embeddable
public class PricesId implements java.io.Serializable {
@ManyToOne
private Product product;
@ManyToOne
private Provider provider;
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public Provider getProvider() {
return provider;
}
public void setProvider(Provider provider) {
this.provider = provider;
}
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PricesId that = (PricesId) o;
if (product != null ? !product.equals(that.product) : that.product != null) return false;
if (provider != null ? !provider.equals(that.provider) : that.provider != null) return false;
return true;
}
public int hashCode() {
int result;
result = (product != null ? product.hashCode() : 0);
result = 31 * result + (provider != null ? provider.hashCode() : 0);
return result;
}
}
ProductsRepository 类:
@Repository
public class ProductsRepository {
@PersistenceContext
EntityManager em;
public List<Product> findAllProducts(){
Query query = em.createQuery("SELECT e FROM Product e");
return (List<Product>) query.getResultList();
}
}
ProductsService 类:
@Service
public class ProductsService {
@Autowired
ProductsRepository productsRepository;
@Transactional(readOnly = true)
public List<Product> findAllProducts(){
List<Product> pv = productsRepository.findAllProducts();
return pv;
}
}
ProductsController 类:
@Controller
@RequestMapping("product")
public class ProductController {
@Autowired
private ProductsService productsService;
@ResponseBody
@ResponseStatus(HttpStatus.OK)
@RequestMapping(method = RequestMethod.GET)
public List<Product> getProducts(){
List<Product> productList = productsService.findAllProducts();
for (Product p : productList){
System.out.println("Andres. Provider name: " + p.getProductName());
}
return productList;
}
}
问题是 Products[0] 有 2 个价格_1。 Price_1[0] 关联了 Product 和 Provider,两者都关联了 Price_1 等。最终陷入无限循环
任何想法如何获得以下对象: 产品列表,每个产品都有一个价格列表,每个供应商一个价格。
谢谢!
编辑: 问题不在于创建的 ArrayList productList,当 productList 对象返回到浏览器时会触发错误:
【问题讨论】:
-
您如何将其返回到浏览器? - 这可能是因为当它被转换为 json 时,调用了 toString() 方法,该方法试图序列化在 prices_1 中定义的产品和提供者。尝试在 priceid 类中将产品和提供者定义为瞬态。
-
非常感谢您的快速回复@PushpendraPal。我并返回浏览器“return productList;” (ArrayList 产品列表)。我在 PriceId.java 中的 Product 和 Provider 对象中都添加了“@Transient”,但应用程序没有运行:“PricesId 没有持久的 id 属性:....model.Prices_1.pk”。自动序列化是我首先关心的问题,这就是我覆盖所有 toString() 方法(产品、提供者和价格_1)的原因。
-
hmm... 我认为在产品和提供者上覆盖 toString() 将不起作用,因为当您返回 productList 时,将在列表上调用 toString()(您的产品的 java.util.List )。它没有被覆盖,并且仍然会查找列表中所有对象的序列化......我还观察到 toString 没有被覆盖为 prices_1 .....
-
嗨@PushpendraPal,我在 Price_1 类中添加了“@Override toString()”,但没有任何区别。
-
您可以尝试创建产品的通用列表。我在答案下面给出的泛型.. 然后通过在 GenericClass
对象上使用 toString 从控制器返回字符串...您可以向此 GenericClass 添加其他未实现的方法,但无需为这些提供实现