2016-03-24 3 views
0

Ich habe eine Spring Java Codebasis geerbt, wo es scheint, dass fast jede Methode aus dem Business-Service bis zu den Low-Level-DAOs mit @Transactional markiert sind. Es hat einige schwerwiegende Leistungsprobleme, die ich gemerkt habe, werden etwas gemildert, wenn bestimmte Annotationen von @Transactional (readOnly = false) in @Transactional (readOnly = true) geändert werden. Es scheint auch periodische Aufrufe von EntityManager.flush() zu geben, die nicht erklärt werden können, außer dass bestimmte Objekte nicht ohne sie in die DB geschrieben werden.Stark verschachtelt @Transactional Annotationen

Meine Ahnung ist, dass die ursprünglichen Entwickler Transaktionen missbrauchen/überstrapazieren, aber ich bin mir nicht sicher über den besten Ansatz, dies zu bereinigen. Ich würde mich über Ratschläge derer freuen, die in Spring Transactions besser vertraut sind als ich.

Ein reduziertes Beispiel für nur ein Segment des Codes folgt. Es gibt andere, die viel komplexer sind als dies mit 5-6 Ebenen von verschachtelten Transaktionen.

// MVC Controller REST Service 
@Controller 
@RequestMapping("/service") 
public class Group { 
    @Inject private GroupService groupService; 

    public @ResponseBody Object update(@RequestBody Group group) { 
     return groupService.update(group); 
    } 
} 

// Business service 
@Service 
public class GroupService { 
    @Inject private GroupDAO groupDao; 
    @Inject private AuditService auditService; 

    @Transactional(readOnly=false) 
    public Group update(Group group) { 
     Group groupToUpdate = groupDao.get(group.getId()); 
     // Do magic 
     groupDao.persist(groupToUpdate); // Shorthand to call EntityManager.persist() 
     auditService.logUpdate(group); 
     return groupToUpdate; 
    } 
} 

// DAO 
@Repository 
public class GroupDAO extends AbstractDAO { 
    @Transactional(readOnly=true) 
    public Group get(Long id) { 
     return entityManager.find(Group.class,id); 
    } 
} 

// Auditing service 
@Component 
public class AuditService { 
    @Inject AlertDAO alertDao; 

    @Transactional(readOnly=false) 
    public void logUpdate(Object o) { 
     Alert alert = alertDao.getFor(o); 
     // Do magic 
     alertDao.update(alert); 
     alertDao.flush() // Shorthand for EntityManager.flush() but WHY??? 
    } 
} 

// DAO 
@Repository 
public class AlertDAO extends AbstractDAO { 
    @Transactional(readOnly=true) 
    public Alert getFor(Object forObj) { 
     // Magic here 
     return entityManager.find(Alert.class,foundId); 
    } 

    @Transactional(readOnly=false) 
    public void update(Alert a) { 
     // Magic here 
     entityManager.merge(a); 
    } 
} 
+2

Nur der Service sollte transaktional sein. http://StackOverflow.com/Questions/1079114/where-does-the-transactional-annotation-belong – JEY

+0

Werfen Sie auch einen Blick auf die Veröffentlichung auf codereview.stackexchange.com –

+4

, es sei denn, einige von ihnen sind markiert mit der Fortpflanzung REQUIRES_NEW dann "nesting" Transaktionen sollten wirklich keine wesentlichen Auswirkungen haben. Das AOP wird nur sagen "Yup, da ist schon einer rennen, mach weiter." (Ich habe keine Antwort, weil Sie eigentlich keine Fragen gestellt haben. Mein Rat wäre das Konzept, sie isoliert zu verschachteln, ist wahrscheinlich nicht die Ursache für Ihre Leistungsprobleme.) – Affe

Antwort

0

Angesichts der Frage ist "wie Transaktionsannotationen aufzuräumen?" die Antwort wäre - basierend auf den obigen Kommentaren;

  1. Sie Transaktion Anmerkungen in DAOs, nur in Dienstleistungen (@Components)
  2. Stellen Sie sicher, DAOs werden nicht nur durch die Service-Layer genannt verwenden.