目前,我开发了一个Spring Boot应用程序,该应用程序主要从消息队列(约5个并发使用者)中提取产品评论数据,并将其存储到MySQL DB中。每个评论都可以通过其reviewIdentifier(String)进行唯一标识,该评论标志是主键,可以属于一个或多个产品(例如,具有不同颜色的产品)。这是数据模型的摘录:
public class ProductPlacement implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "product_placement_id")
private long id;
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="productPlacements")
private Set<CustomerReview> customerReviews;
}
public class CustomerReview implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@Column(name = "customer_review_id")
private String reviewIdentifier;
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinTable(
name = "tb_miner_review_to_product",
joinColumns = @JoinColumn(name = "customer_review_id"),
inverseJoinColumns = @JoinColumn(name = "product_placement_id")
)
private Set<ProductPlacement> productPlacements;
}
队列中的一条消息包含1-15条评论和一个productPlacementId。现在,我想要一种有效的方法来保留产品的评论。每次传入审核基本上都需要考虑两种情况:
目前,我保留评论的方法不是最佳的。它看起来如下(使用Spring Data JpaRespoitories):
@Override
@Transactional
public void saveAllReviews(List<CustomerReview> customerReviews, long productPlacementId) {
ProductPlacement placement = productPlacementRepository.findOne(productPlacementId);
for(CustomerReview review: customerReviews){
CustomerReview cr = customerReviewRepository.findOne(review.getReviewIdentifier());
if (cr!=null){
cr.getProductPlacements().add(placement);
customerReviewRepository.saveAndFlush(cr);
}
else{
Set<ProductPlacement> productPlacements = new HashSet<>();
productPlacements.add(placement);
review.setProductPlacements(productPlacements);
cr = review;
customerReviewRepository.saveAndFlush(cr);
}
}
}
问题:
更新到问题1:我的Review-Repository上的简单@Lock是否会表示unique-constraint异常?
@Lock(LockModeType.PESSIMISTIC_WRITE)
CustomerReview findByReviewIdentifier(String reviewIdentifier);
当findByReviewIdentifier返回null时会发生什么?即使方法返回null, hibernate 也可以为潜在的插入锁定reviewIdentifier吗?
谢谢!
最佳答案
从性能的角度来看,我将考虑通过以下更改来评估解决方案。
我有一个相同的问题,即从执行的DML语句中哪个更有效。引用Typical ManyToMany mapping versus two OneToMany。
从配置的角度来看,选项一可能更简单,但它会产生效率较低的DML语句。
启用批处理支持将减少往返数据库以插入/更新相同数量记录的往返次数。
从batch INSERT and UPDATE statements报价
当前代码获取
ProductPlacement
,并且对于每个review
都执行一个saveAndFlush
,这将导致不对DML语句进行批处理。相反,我会考虑加载
ProductPlacement
实体,并将List<CustomerReview> customerReviews
添加到Set<CustomerReview> customerReviews
实体的ProductPlacement
字段中,最后在最后一次调用一次merge
方法,并进行以下两个更改:ProductPlacement
属性移到mappedBy
实体的Set<ProductPlacement> productPlacements
字段上,使CustomerReview
实体成为关联的所有者。 CustomerReview
字段中的equals
字段来使hashCode
实体实现reviewIdentifier
和reviewIdentifier
方法。我相信ojit_code是唯一的并由用户分配。 最后,当您通过这些更改进行性能调整时,请以当前代码为基准来确定性能。然后进行更改,并比较更改是否确实为您的解决方案带来了显着的性能改进。