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);
}
}
Nur der Service sollte transaktional sein. http://StackOverflow.com/Questions/1079114/where-does-the-transactional-annotation-belong – JEY
Werfen Sie auch einen Blick auf die Veröffentlichung auf codereview.stackexchange.com –
, 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