2016-12-22 1 views
0

Ich möchte hier die Leistung eines Codes zu verbessern, ich habe diese Arbeit:Wie kann man JPA bitten, Transaktionen zu akkumulieren?

List<Doctor> team = doctorService.getAll(); team.stream() .filter(doctor -> !doctor.equals(msg.getSender())) .forEach(doctor -> { ChatMessageTeam chatMsg = new ChatMessageTeam(); chatMsg.setDoctor(doctor); chatMsg.setMessage(msg); rep.save(chatMsg); });

Die rep ist ein JPA Eigenbau-Repository.

Und ich möchte diesen Strom parallel, aber wenn ich .parallel auf den Strom setzen, habe ich einen Fehler, wie ich sah, weil Entity Manager nicht darauf vorbereitet ist. Also ich denke (und nicht herausgefunden, wie), dass ich tun kann, akkumulieren die Transaktionen und bündeln sie alle zusammen in einer einzigen Abfrage dann. Andere Vorschläge sind ebenfalls willkommen.

Vielen Dank für Ihre Zeit das Lesen!

+0

Ist "rep" ein selbstgebautes Repository? Verwenden Sie ein Framework/eine Bibliothek, die Sie bei Ihrer Persistenz unterstützen? Abhängig davon können Sie eine einzelne Transaktion deklarieren, in der Sie dann Ihre Saves durchführen. – oschlueter

+0

Ja, ist ein Self-Build-Repository, ich werde das in der Frage hinzufügen. Und die Bibliothek, die ich benutze, ist die JPA. –

Antwort

0

Um einen Ansatz zum Ausführen mehrerer Datenbankanweisungen in einer einzigen Transaktion zu demonstrieren, habe ich Ihren Code in eine Methode verpackt und dann die Annotation @Transactional zu dieser Methode hinzugefügt. Auf diese Weise wird Ihre Methode entweder in einer bestehenden Transaktion verarbeitet oder eine Transaktion wird für Sie erstellt. Wenn dies in Ihrer Umgebung nicht funktioniert, geben Sie bitte Fehlermeldungen oder Stack-Traces an.

import javax.transaction.Transactional; 

// ... 

@Transactional 
public void store() { 
    List<Doctor> team = doctorService.getAll(); 
    team.stream() 
      .filter(doctor -> !doctor.equals(msg.getSender())) 
      .forEach(doctor -> { 
       ChatMessageTeam chatMsg = new ChatMessageTeam(); 
       chatMsg.setDoctor(doctor); 
       chatMsg.setMessage(msg); 
       rep.save(chatMsg); 
      }); 
} 
+0

Es läuft OK, aber ich kann immer noch nicht parallel den Stream, hat die Leistung nicht verbessert ... –

0

Ich denke, bei Ihrem Anwendungsfall ist .parallel langsamer. Aber Sie können für einen Commit alle in eine Methode in Ihren Repo einbinden.

List<Doctor> team = doctorService.getAll(); 
    List<ChatMessageTeam> cmtList = team.stream() 
     .filter(doctor -> !doctor.equals(msg.getSender())) 
     .map(doctor -> new ChatMessageTeam(doctor ,msg)) 
     .collector(Collectors.toList())); 
    rep.saveList(cmtList); 


@Transactional 
public saveList(List<ChatMessageTeam> list){ 
    for(ChatMessageTeam ctm: list){ 
     save(ctm); 
    } 
} 
+0

Warum sagst du, es wird langsamer? und Ihre Lösung wird die Liste nicht zweimal ausführen? einer beim Befehl 'for' und ein anderer im' stream'? –

+0

Der Overhead von Fork-Join ist höher als die Dauer Ihrer Ausführungen. http://stackoverflow.com/questions/20375176/should-i-always-use-a-parallel-stream-when-possible saveList ist eine Methode aus Ihrem Repo. Ich würde den Build teilen und speichern. – jklee

Verwandte Themen