Why use @Transactional with @Service instead of with @Controller

流过昼夜 提交于 2019-11-28 18:49:33
Luca Basso Ricci

You are asking about best practice, and best practice is to mark @Transactional in the service layer because a @Controller should not be aware of data persistence in a MVC logic.
@Service is constructed on use-case generated from analysis and knows about unit of works and is also realized thinking in terms of reuse: if you switch from a web context to a desktop one (for example, or some other visual frontend) where @Controller layer doesn't exist you don't have problems because all is encapsulated in service layer.
A @Service is a contract and a modification in presentation layer should not require a rewrite of @Service code.
But Spring don't care about where you put your your transaction boundaries, you can put on @Controller but your application may will be harder to be maintained.

I hope this is clear enough. Sorry if not; English is not my native language.

just so other know, interface annotations are discouraged

Spring recommends that you only annotate concrete classes (and methods of concrete classes) with the @Transactional annotation, as opposed to annotating interfaces. You certainly can place the @Transactional annotation on an interface (or an interface method), but this works only as you would expect it to if you are using interface-based proxies. The fact that Java annotations are not inherited from interfaces means that if you are using class-based proxies ( proxy-target-class="true") or the weaving-based aspect ( mode="aspectj"), then the transaction settings are not recognized by the proxying and weaving infrastructure, and the object will not be wrapped in a transactional proxy, which would be decidedly bad.

duffymo

Controller is firmly in the view layer, which can be changed at any time. The service still owns units of work and should operate correctly regardless of which view is accessing. My answer here still stands.

Yan Khonski

I created an upper-layer service which uses other (non-transactional) services. And the upper-layer service is transactional.

@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;
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!