我在堆栈溢出文章中看到很多评论我发现 @Transactional 与 @Service 或 @Controller 一起使用的某些内容
“通常,应该在服务层放置一个事务。”
“正常情况是在服务层级注释”
“认为交易属于服务层。它是了解工作单位和用例的人。如果你有几个DAO注入服务需要在一个交易中协同工作,那么这是正确的答案。” [Source]
使用带有@service图层的@transactional
如果我有2个方法,例如saveUser()和saveEmail()(因为我将电子邮件存储在数据库中以便稍后发送 - 就像一个队列)我会在我的服务中创建一个方法saveUserAndSendEmail(用户用户)是交易的。 [Source]
这意味着我在服务层创建了许多方法而不是一个Save Generic Method,如下所示
public <T> long save(T entity) throws DataAccessException {
Session session = sessionFactory.getCurrentSession();
long getGenVal=(Long) session.save(entity);
return getGenVal;
}
根据上述解决方案,这意味着我们有很多方法,如以下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);
如果@Transactional on Service,前2个实体成功保存,但第三个不是不回滚所有交易
如果@Tratroller上的@Transactional所有事务回滚都发生异常
为什么堆栈溢出问道,“不要在控制器中进行事务处理。将它们放在服务层类中。”? [source]答案 0 :(得分:24)
您询问最佳做法,最佳做法是在服务层中标记@Transactional
,因为@Controller
不应该知道MVC逻辑中的数据持久性。
@Service
是基于分析生成的用例构建的,并且知道工作单元,并且还实现了重用方面的思考:如果从Web上下文切换到桌面上下文(例如,或其他一些视觉前端) )在@Controller
层不存在的情况下,您没有问题,因为所有层都封装在服务层中
@Service
是合同,表示层中的修改不需要重写@Service
代码。
但是Spring并不关心你的交易边界在哪里,你可以放在@Controller
但你的应用程序可能会更难维护。
我希望这很清楚。对不起,如果不是英语不是我的母语。
答案 1 :(得分:4)
正如其他所知,不鼓励界面注释
Spring建议您只使用@Transactional注释来注释具体类(以及具体类的方法),而不是注释接口。您当然可以将@Transactional注释放在接口(或接口方法)上,但这只能在您使用基于接口的代理时按预期工作。 Java注释不是从接口继承的事实意味着如果您使用基于类的代理(proxy-target-class =&#34; true&#34;)或基于编织的方面(mode =&#34; aspectj& #34;),然后代理和编织基础设施无法识别事务设置,并且该对象将不会被包装在事务代理中,这将是非常糟糕的。
答案 2 :(得分:1)
控制器牢固地位于视图层中,可以随时更改。该服务仍然拥有工作单元,无论访问哪个视图,都应该正常运行。我的回答here仍然存在。
答案 3 :(得分:1)
我创建了一个使用其他(非事务性)服务的上层服务。而上层服务是交易性的。
@Service
public class Service1Impl implements Servcie1 {
public Object method11(){...}
public Object method12(){...}
}
@Service
public class Service2Impl implements Service2 {
public method21(){...}
}
public interface Service1 {
public Object method11();
public Object method12();
}
public interface Service2 {
public Object method21();
}
@Transactional
public interface UpperLayerService {}
@Service
public class UpperLayerServiceImpl implements UpperLayerService {
@Autowired
private Service2 service2;
@Autowired
private Service3 service3;
public Object doWork() {
Object o1 = service1.method11();
Object o2 = service1.method12();
Object o3 = service2.method21();
....
Object res = null;//...Any code
return res;
}
}