简体   繁体   English

大量嵌套的@Transactional批注

[英]Heavily nested @Transactional annotations

I have inherited a Spring Java codebase where it seems pretty much every method from the business service down to the low level DAOs are tagged with @Transactional. 我继承了一个Spring Java代码库,其中似乎从商务服务到底层DAO的几乎所有方法都使用@Transactional进行了标记。 It has some severe performance issues that I noticed are mitigated somewhat when certain annotations are changed from @Transactional(readOnly=false) to @Transactional(readOnly=true). 当某些注释从@Transactional(readOnly = false)更改为@Transactional(readOnly = true)时,我注意到有些严重的性能问题得到了缓解。 It also seems to have periodic calls to EntityManager.flush() that can't be explained except that certain objects do not get written to the DB without them. 它似乎也有对EntityManager.flush()的定期调用,除非某些对象没有它们就无法写入数据库,否则无法解释。

My hunch is that the original developers are misusing/overusing transactions, but I'm not sure of the best approach to clean this up. 我的直觉是原始开发人员正在滥用/过度使用事务,但是我不确定清除此问题的最佳方法。 I would appreciate advice from those more well-versed in Spring Transactions than me. 我会比从我那些更精通Spring Transactions的人那里得到的建议大加赞赏。

A reduced example of just one segment of the code follows. 下面是仅一段代码的简化示例。 There are others much more complex than this with 5-6 levels of nested transactions. 还有其他比这复杂得多的嵌套事务5-6级。

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

Given that the question is "how to clean up transaction annotations?" 假设问题是“如何清理交易注释?” the answer would be - based on the above comments; 答案将是-根据上述评论;

  1. Do not use transaction annotations in DAOs, only in Services (@Components) 不要在DAO中使用事务注释,而只能在服务(@Components)中使用
  2. Make sure DAOs are only called through the service-layer. 确保仅通过服务层调用DAO。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM