Spring 选择多对多x的所有元素将导致多对多y中的重复
我遇到了这个奇怪的问题,希望有人能帮我解决。 也许我做错了什么或者忽略了什么 每当我选择所有n种材质时,我选择的模型都会列出n次。 反之亦然,当我选择所有n个模型时,材料会列出n次 例如:材料1已选定 材料2选定 材料3选定 模型1已选定 模型2 模型3 结果: 材料1 材质2 材料3 模型1 模型1 模型1 我使用的是Spring4.0.3、SpringDataJPA1.4.3、Hibernate4.3.1、MySQL 5.1.28和Thymeleaf2.1.2 发布的DTO是正确的,仅包含选定的材料和型号。 数据库中的数据也是正确的Spring 选择多对多x的所有元素将导致多对多y中的重复,spring,hibernate,spring-data-jpa,Spring,Hibernate,Spring Data Jpa,我遇到了这个奇怪的问题,希望有人能帮我解决。 也许我做错了什么或者忽略了什么 每当我选择所有n种材质时,我选择的模型都会列出n次。 反之亦然,当我选择所有n个模型时,材料会列出n次 例如:材料1已选定 材料2选定 材料3选定 模型1已选定 模型2 模型3 结果: 材料1 材质2 材料3 模型1 模型1 模型1 我使用的是Spring4.0.3、SpringDataJPA1.4.3、Hibernate4.3.1、MySQL 5.1.28和Thymeleaf2.1.2 发布的DTO是正确的,仅包含选
@Getter
@ToString
@Entity
@Table(name = "SKUS")
public class Sku extends BaseEntityAudit {
/**
*
*/
private static final long serialVersionUID = 1L;
@Column(name = "CODE", nullable = false)
protected String code;
@Column(name = "NAME", nullable = false)
protected String name;
@Column(name = "RETAIL_PRICE", nullable = true)
protected BigDecimal retailPrice;
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.MERGE)
@JoinTable(name = "SKU_MODELS",
joinColumns = {@JoinColumn(name = "SKU_ID", referencedColumnName = "ID")},
inverseJoinColumns = {@JoinColumn(name = "MODEL_ID", referencedColumnName = "ID")})
protected List<SkuModel> availableModels;
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.MERGE)
@JoinTable(name = "SKU_MATERIALS",
joinColumns = {@JoinColumn(name = "SKU_ID", referencedColumnName = "ID")},
inverseJoinColumns = {@JoinColumn(name = "MATERIAL_ID", referencedColumnName = "ID")})
protected List<Material> availableMaterials;
public static Builder getBuilder(String code, String name) {
return new Builder(code, name);
}
public void update(String code, String name) {
this.code = code;
this.name = name;
}
public void updatePrice(BigDecimal retailPrice) {
this.retailPrice = retailPrice;
}
public void updateMaterials(List<Material> materials) {
if (!materials.equals(availableMaterials)) {
this.availableMaterials.clear();
this.availableMaterials = materials;
}
}
public void updateModels(List<SkuModel> models) {
if (!models.equals(availableModels)) {
this.availableModels.clear();
this.availableModels = models;
}
}
public static class Builder {
private Sku built;
public Builder(String code, String name) {
built = new Sku();
built.code = code;
built.name = name;
}
public Builder retailPrice(BigDecimal retailPrice) {
built.retailPrice = retailPrice;
return this;
}
public Builder models(List<SkuModel> models) {
built.availableModels = models;
return this;
}
public Builder materials(List<Material> materials) {
built.availableMaterials = materials;
return this;
}
public Sku build() {
return built;
}
}
}
public interface SkuRepository extends JpaRepository<Sku, Long> {}
// SkuService
@Transactional(readOnly = true, rollbackFor = {NotFoundException.class})
@Override
public Sku findById(Long id) throws NotFoundException {
LOGGER.debug("Finding a sku entry with id: {}", id);
Sku found = skuRepository.findOne(id);
LOGGER.debug("Found sku entry: {}", found);
if (found == null) {
throw new NotFoundException("No sku found with id: " + id);
}
return found;
}
@Transactional(rollbackFor = {NotFoundException.class})
@Override
public Sku update(SkuDTO updated) throws NotFoundException {
LOGGER.debug("Updating sku with request information: {}", updated);
Sku model = findById(updated.getId());
model.update(updated.getCode(), updated.getName());
model.updatePrice(updated.getRetailPrice());
model.updateMaterials(updated.getMaterials());
model.updateModels(updated.getModels());
LOGGER.debug("Updating sku with information: {}", model);
skuRepository.save(model);
return model;
}
@RequestMapping(value = REQUEST_MAPPING_SKU_DETAILS, method = RequestMethod.GET)
public String findById(@PathVariable(PARAMETER_SKU_ID) Long id, Model uiModel) throws NotFoundException {
LOGGER.debug("Rendering sku page for sku entry with id: {}", id);
Sku found = skuService.findById(id);
LOGGER.debug("Found sku entry with information: {}", found);
uiModel.addAttribute(MODEL_ATTRIBUTE_SKU, found);
return VIEW_SKU_DETAILS;
}
@RequestMapping(value = REQUEST_MAPPING_SKU_EDIT, method = RequestMethod.POST)
public String processUpdateSkuForm(@Valid @ModelAttribute(MODEL_ATTRIBUTE_SKU) SkuDTO dto, BindingResult result, RedirectAttributes attributes) throws NotFoundException {
LOGGER.debug("Updating a sku entry with information: {}", dto);
if (result.hasErrors()) {
LOGGER.debug("Update sku entry form was submitted with validation errors. Redirecting back to form view.");
attributes.addFlashAttribute("org.springframework.validation.BindingResult." + MODEL_ATTRIBUTE_SKU, result);
attributes.addFlashAttribute(MODEL_ATTRIBUTE_SKU, dto);
attributes.addAttribute(PARAMETER_SKU_ID, dto.getId());
return createRedirectViewPath(REQUEST_MAPPING_SKU_EDIT);
}
Sku updated = skuService.update(dto);
LOGGER.debug("Updated the information of a sku entry to: {}", updated);
attributes.addAttribute(PARAMETER_SKU_ID, updated.getId());
return createRedirectViewPath(REQUEST_MAPPING_SKU_DETAILS);
}
我也有同样的问题
我相信这是因为Spring生成的查询在进行连接时不使用“DISTINCT”,但我不知道解决方案。您可以使用集合而不是列表这是否意味着要创建3个model1对象?或者它只列出了模型1 3次?它列出了模型1 3次,而它只是可接合SKU_模型SKU_id、模型_id中的一行SKU_物料表包含3行SKU_id,物料id。检索Sku模型会在availableModels中生成3个model1对象,在AvailableMaterials中生成3个material1、2和3。除了使用Set之外,还有其他解决方案吗