Spring Data JPA - gleichzeitige Bulk-inserts/updates

im moment entwickle ich eine Spring-Boot-Anwendung, die hauptsächlich zieht product review von Daten aus einer message queue (~5 gleichzeitige Verbraucher) und speichert Sie in einer MySQL-DB. Jeder abgeben können, werden eindeutig identifiziert durch seine reviewIdentifier (String), die den primären Schlüssel und gehören zu einem oder mehreren Produkt (z.B. Produkte mit unterschiedlichen Farben). Hier ist ein Auszug der Daten-Modell:

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;
}

Einer Nachricht aus der Warteschlange enthält 1 - 15 Bewertungen und einen productPlacementId. Jetzt will ich eine effiziente Methode zur Speicherung der Bewertungen für das Produkt. Es gibt grundsätzlich zwei Fälle, die berücksichtigt werden müssen, die für jede eingehende Beurteilung:

  1. Der überprüfung ist nicht in der Datenbank -> einfügen-Kritik mit Verweis auf das Produkt, das in der Nachricht enthaltene
  2. Die review ist bereits in der Datenbank -> fügen Sie einfach das Produkt Verweis auf die Set-productPlacements der bestehenden abgeben.

Derzeit meine Methode zum speichern der Bewertungen ist nicht optimal. Es sieht wie folgt aus (Spring verwendet Daten 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);
        }

    }
}

Fragen:

  1. Manchmal bekomme ich constraintViolationExceptions wegen Verletzung der unique-Einschränkung auf "reviewIndentifier". Dies ist offensichtlich, weil ich (gleichzeitig) schauen, ob das review ist bereits vorhanden und als insert-oder update es. Wie kann ich das vermeiden?
  2. Ist es besser, zu verwenden, speichern() oder saveAndFlush() in meinem Fall. Ich bekomme ~50-80 Bewertungen pro Natalies. Hibernate flush automatisch, wenn ich nur verwenden, speichern() oder wird es zu stark erhöhter Speicherauslastung?

Update zu Frage 1: Würde ein einfaches @Lock auf meinem Review-Repository prefent die unique-constraint-Ausnahme?

@Lock(LockModeType.PESSIMISTIC_WRITE)
CustomerReview findByReviewIdentifier(String reviewIdentifier);

Was passiert, wenn die findByReviewIdentifier null zurück? Überwintern Schloss die reviewIdentifier für ein Potenzial stecken, auch wenn die Methode null zurück?

Danke!

  • loswerden von race conditions, entweder saveAllReviews() synchronisiert oder Implementierung von expliziten sperren auf der Grundlage der Schlüssel der Bewertung (Eigenschaft, die eingeschränkt ist). In unserer Organisation, wir müssen auch zum Umgang mit solchen Situationen. Über 3+ Jahre von versuchen und Tests, die wir nicht in der Lage bist, eine Methode zu finden, besser als Verriegelung durch Schlüssel... vielleicht gibt es eine andere Praxis, und ich möchte auch, es zu lernen.
  • Danke für Ihre Antwort. Denkst du es gibt einen Unterschied in der machen die Methode synchronisiert und verriegeln Sie die Taste (performance-wise)
  • natürlich-Schlüssel-sperren werden sehr viel effektiver, da können Sie sicher gleichzeitigen schreibt für verschiedene Schlüssel. Aber dieser Ansatz erfordert die Umsetzung Bemühungen. Sie können zunächst versuchen synchronized ist, dann denken Sie über erweiterte techinque wenn die Leistung nicht mehr befriedigen.
InformationsquelleAutor JuHarm89 | 2016-04-01
Schreibe einen Kommentar