Hibernate 为什么将@Transactional与@Service一起使用,而不是与@Controller一起使用
我在stack overflow的文章中看到了很多评论,我发现了一些关于@Transactional与@Service或@Controller一起使用的东西 通常,应该将事务放在服务层 “通常情况下,在服务层级别进行注释” “认为事务属于服务层。它了解工作单元和用例。如果将多个DAO注入到需要在单个事务中协同工作的服务中,这是正确的答案。” 与@service layer一起使用@transactional的缺点 如果我有两个方法,例如saveUser()和saveEmail()(因为我将电子邮件存储在数据库中,以便以后发送,就像队列一样),我会在我的服务中创建一个方法saveuserandsendmail(用户用户),这将是事务性的 这意味着我在服务层创建了许多方法,而不是像下面那样保存一个通用方法Hibernate 为什么将@Transactional与@Service一起使用,而不是与@Controller一起使用,hibernate,spring-mvc,service,controller,transactional,Hibernate,Spring Mvc,Service,Controller,Transactional,我在stack overflow的文章中看到了很多评论,我发现了一些关于@Transactional与@Service或@Controller一起使用的东西 通常,应该将事务放在服务层 “通常情况下,在服务层级别进行注释” “认为事务属于服务层。它了解工作单元和用例。如果将多个DAO注入到需要在单个事务中协同工作的服务中,这是正确的答案。” 与@service layer一起使用@transactional的缺点 如果我有两个方法,例如saveUser()和saveEmail()(因为我将电子邮
public <T> long save(T entity) throws DataAccessException {
Session session = sessionFactory.getCurrentSession();
long getGenVal=(Long) session.save(entity);
return getGenVal;
}
在@Transactional on Service的情况下,前两个实体成功保存,但第三个实体未回滚所有事务
如果@Controller上的@Transactional发生异常,则所有事务都会回滚
为什么堆栈溢出会问:“不要在控制器中执行事务,将它们放在服务层类中。”?
您询问的是最佳实践,最佳实践是在服务层中标记
@Transactional
,因为@Controller
不应该知道MVC逻辑中的数据持久性。@Service
基于分析生成的用例构建,了解工作单元,并考虑重用:如果您从web上下文切换到桌面上下文(例如,或其他可视前端)如果@Controller
层不存在,则不会出现问题,因为所有这些都封装在服务层中。@Service
是一种契约,表示层中的修改不需要重写@Service
代码。但是Spring并不关心事务边界放在哪里,您可以放在
@Controller
上,但您的应用程序可能更难维护
我希望这足够清楚。对不起,如果没有;英语不是我的母语。控制器位于视图层,可以随时更改。该服务仍然拥有工作单元,无论访问哪个视图,都应正确运行。我的答案仍然有效。我创建了一个使用其他(非事务性)服务的上层服务。上层服务是事务性的
@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;
}
}
正如其他人所知,不鼓励使用接口注释
Spring建议只使用
@Transactional
注释具体类(以及具体类的方法),而不是注释接口。当然,您可以将@Transactional
注释放置在接口(或接口方法)上,但这仅适用于使用基于接口的代理的情况。Java注释不是从接口继承的这一事实意味着,如果您使用基于类的代理(proxy target class=“true”
)或基于编织的方面(mode=“aspectj”
),则代理和编织基础结构无法识别事务设置,并且对象不会被包装在事务代理中,这绝对是不好的。这意味着我必须创建许多保存方法,例如saveAccount
saveAccountAudit
saveAccountAuditEntries
?我认为最好的解决方案是在控制器
和服务
之间创建另一个级别的层。在我看来,controller
只处理调用,并准备vars来处理和执行逻辑。服务
处理所有数据库内容。应该位于控制器
和服务
之间的模型可以执行一些逻辑。在您的示例中,执行少量保存操作是对数据执行操作的逻辑。这意味着将它们放入model
并使用transactional
扭曲model
如果需要,您的saveUser()
和saveEmail()
方法应该在DAO层中。然后,在服务层中使用saveuserandsendmail(User-User)
方法进行事务处理。
@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;
}
}