25

我在 stack-overflow 文章中看到了很多评论我发现了一些关于@Transactional@Service@Controller一起使用的事情

“通常情况下,应该在服务层进行交易。”

“正常情况是在服务层级别进行注释”

“认为事务属于服务层。它了解工作单元和用例。如果您将多个 DAO 注入需要在单个事务中协同工作的服务中,这是正确的答案。” [资源]

将@transactional 与@service 层一起使用的缺点

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

这意味着我在服务层创建了许多方法,而不是一个保存通用方法,如下所示

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 个实体成功保存,但第三个不是它不回滚所有事务

万一,@Controller 上的@Transactional 发生异常时所有事务回滚

为什么 stack-overflow 会问,“不要在你的控制器中做事务。把它们放在你的服务层类中。”? [资源]

4

4 回答 4

32

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

我希望这足够清楚。抱歉,如果没有;英语不是我的母语。

于 2013-08-28T21:51:57.147 回答
7

就像其他人知道的那样,不鼓励使用接口注释。

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

于 2016-02-10T03:04:09.110 回答
2

控制器牢牢地位于视图层,可以随时更改。该服务仍然拥有工作单元,并且无论访问哪个视图都应该正确运行。我在这里的回答仍然有效。

于 2013-08-28T23:36:33.610 回答
2

我创建了一个使用其他(非事务性)服务的上层服务。并且上层服务是事务性的。

@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;
    }
}
于 2015-11-20T14:34:51.203 回答