为什么将@Transactional与@Service一起使用而不是@Controller

Sha*_*oor 17 service hibernate controller spring-mvc transactional

我在堆栈溢出文章中看到很多评论我发现@Transactional@Service@Controller一起使用的某些事情

"通常,应该在服务层进行交易."

"正常情况是在服务层级注释"

"认为事务属于服务层.它是了解工作单元和用例的人.如果你有几个DAO注入到需要在单个事务中协同工作的服务,那么这是正确的答案." [资源]

使用带有@service层的@transactional的缺点

如果我有2个方法,例如saveUser()和saveEmail()(因为我将电子邮件存储在数据库中以便稍后发送 - 就像一个队列)我会在我的服务中创建一个方法saveUserAndSendEmail(用户用户),它将是事务性的.[资源]

这意味着我在服务层创建了许多方法,而不是一个Save Generic Method,如下所示

public <T> long save(T entity) throws DataAccessException {
    Session session = sessionFactory.getCurrentSession();
    long getGenVal=(Long) session.save(entity);
    return getGenVal;
}
Run Code Online (Sandbox Code Playgroud)

根据上面的解决方案,这意味着我们有很多方法,如以下LOL ..

public <T> long saveAccount(T entity)....

public <T> long saveWithAuditLog(T entity, K entity1)....

public <T> long saveWithAuditLogAndEntries(T entity, K entity, M entity)....

克服这种情况

我在@Controller中使用@Transactional,只需制作一个通用保存方法,并使用这个简单的保存方法保存所有实体/模型.如果任何方法无法保存,则控制器中的所有事务都会成功回滚.

确保@Transactional应与@Controller一起使用的其他情况

在@Controller中:

pt.save(entity1);
pt.save(entity2);
int a = 2/0;
pt.save(entity3);
Run Code Online (Sandbox Code Playgroud)

如果@Transactional on Service,前2个实体成功保存,但第三个不回滚所有事务

如果@Tratroller上的@Transactional,所有事务回滚都会发生异常

为什么堆栈溢出问道,"不要在控制器中进行事务处理.将它们放在服务层类中."? [资源]

Luc*_*cci 26

您询问最佳实践,最佳实践是@Transactional在服务层中进行标记,因为@Controller不应该知道MVC逻辑中的数据持久性.
@Service基于分析生成的用例构建并了解工作单元,并且还实现了重用方面的思考:如果您从Web上下文切换到桌面上(例如,或其他一些视觉前端),其中@Controller图层没有存在你没有问题因为所有都被封装在服务层中.
A @Service是合同,表示层中的修改不应要求重写@Service代码.
但是Spring不关心你的交易边界在哪里,你可以穿上@Controller但你的应用程序可能会更难维护.

我希望这很清楚.对不起,如果不是 英语不是我的母语.


小智 6

为了让其他人知道,不鼓励使用接口注释。

Spring 建议您只使用注解来注解具体类(和具体类的方法)@Transactional,而不是注解接口。您当然可以将@Transactional注释放置在接口(或接口方法)上,但是如果您使用基于接口的代理,这只能像您期望的那样工作。Java注解不是从接口继承的事实意味着,如果你使用基于类的代理(proxy-target-class="true")或基于编织的方面(mode="aspectj"),那么代理和编织基础设施无法识别事务设置,并且对象将不会被包裹在一个事务代理中,这绝对是糟糕的。