gpt4 book ai didi

java - Spring JPA 多对多持久性问题

转载 作者:行者123 更新时间:2023-11-29 10:23:42 27 4
gpt4 key购买 nike

我有以下使用 Spring JPA 进行多对多关系持久化的代码。这似乎第一次有效,但在随后的保存中却失败了。

@Entity
public class ProductCategory {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;

@NotNull
@Column(unique = true)
private String name;

@OneToMany(mappedBy = "productCategory", cascade = CascadeType.ALL)
private Set<ProductCategoryToProductAttributeRel> productCategoryToProductAttributeRel = new HashSet<ProductCategoryToProductAttributeRel>();
}

和 rel 类(此处添加了一个新类,因为我需要在此表上添加其他列

@Entity
public class ProductCategoryToProductAttributeRel implements Serializable{
private static final long serialVersionUID = 1L;
private Integer id;
@Id
@ManyToOne
@JoinColumn(name = "product_category_id")
private ProductCategory productCategory;
@Id
@ManyToOne
@JoinColumn(name = "product_attribute_id")
private ProductAttribute productAttribute;
}

和类别

@Entity
public class ProductAttribute {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
@NotNull
private String name;
}

以及要保存的代码

@RequestMapping(value = "/saveProductCategory", method = RequestMethod.POST)
public String ProductCategorySave(ProductCategoryDTO productCategoryDTO, Model model) {
ProductCategory pc = new ProductCategory(productCategoryDTO);
if (productCategoryDTO.getProductAttributeIds() != null
&& productCategoryDTO.getProductAttributeIds().size() > 0) {
Iterator<ProductCategoryToProductAttributeRel> it =
pc.getProductCategoryToProductAttributeRel().iterator();
// removing elements
while (it.hasNext()) {
boolean isPresent = false;
for (Integer paId : productCategoryDTO.getProductAttributeIds()) {
if (it.next().getProductAttribute().getId().equals(paId)) {
isPresent = true; break;
}
}
if (!isPresent) { it.remove(); }
}
for (Integer paId : productCategoryDTO.getProductAttributeIds()) {
ProductAttribute pa = productAttributeRepository.findOne(paId);

boolean add = true;
for (ProductCategoryToProductAttributeRel pcToPARel :
pc.getProductCategoryToProductAttributeRel()) {
if (pcToPARel.getProductAttribute().getId().equals(paId)) {
add = false;
}
}
if (add) {
ProductCategoryToProductAttributeRel pcToPARel = new ProductCategoryToProductAttributeRel();
pcToPARel.setProductAttribute(pa);
pcToPARel.setProductCategory(pc);
pc.getProductCategoryToProductAttributeRel().add(pcToPARel);
}
}
}
productCateogryRepository.save(pc);
return "edit-product-category";
}

第一次调用保存似乎工作正常并按预期更新表。然而,当我尝试为 rel 表添加其他行时,第二次调用保存时会使用其他要保存的项目,似乎失败并出现错误

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'product_category_id' cannot be null

我在这里做错了什么

最佳答案

  • 在我看来,该错误似乎是在 while 循环中第二次保存时引起的,在该循环中,您使用迭代器从 ProductCategory 中删除了已保存的 ProductCategoryToProductAttributeRel 记录关联。
  • 它将尝试将 null 设置为 ProductCategoryToProductAttributeRel.productCategory,但由于是主键的一部分而无法设置。
  • 要纠正此问题,您需要允许 null(即重新设计主键),或者在删除与 ProductCategory 的关联时对 Rel 实体进行删除。

如果您使用的是 JPA 2.0,请尝试使用 orphanRemoval=true)

@OneToMany(mappedBy = "productCategory", orphanRemoval=true, cascade = CascadeType.ALL)
private Set<ProductCategoryToProductAttributeRel> productCategoryToProductAttributeRel = new HashSet<ProductCategoryToProductAttributeRel>();

下面可能是我注意到的另一个错误

<小时/>

将您的 it.next() 放在 for 循环之外,因为我认为您不希望它每次 while 迭代都会增加多次。

即将 while block 替换为如下所示的内容。

// removing elements
while (it.hasNext()) {
boolean isPresent = false;
ProductCategoryToProductAttributeRel nextRel = it.next() // I think you wanted to increment once per while loop?
for (Integer paId : productCategoryDTO.getProductAttributeIds()) {
if (nextRel.getProductAttribute().getId().equals(paId)) {
isPresent = true; break;
}
}
if (!isPresent) { it.remove(); }
}

这可能是它第一次工作的原因(因为 while 循环第一次可能为空)。

关于java - Spring JPA 多对多持久性问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48733158/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com