There are already a few questions about the topic, but no response at all really provides arguments in order to explain why we shouldn't make a Spring MVC controller
TLDR: this is because only the service layer in the application has the logic needed to identify the scope of a database/business transaction. The controller and persistence layer by design can't/shouldn't know the scope of a transaction.
The controller can be made
@Transactional, but indeed it's a common recommendation to only make the service layer transactional (the persistence layer should not be transactional either).
The reason for this is not technical feasibility, but separation of concerns. The controller responsibility is to get the parameter requests, and then call one or more service methods and combine the results in a response that is then sent back to the client.
So the controller has a function of coordinator of the request execution, and transformer of the domain data to a format the client can consume such as DTOs.
The business logic resides on the service layer, and the persistence layer just retrieve / stores data back and forth from the database.
The scope of a database transaction is really a business concept as much as a technical concept: in an account transfer an account can only be debited if the other is credited etc., so only the service layer that contains the business logic can really know the scope of a bank account transfer transaction.
The persistence layer cannot know what transaction it's in, take for example a method
customerDao.saveAddress. Should it run in it's own separate transaction always? there is no way to know, it depends on the business logic calling it. Sometimes it should run on a separate transaction, sometimes only save it's data it the
saveCustomer also worked, etc.
The same applies to the controller: should
saveErrorMessages go in the same transaction? You might want to save the customer and if that fails then try to save some error messages and return a proper error message to the client, instead of rolling back everything including the error messages you wanted to save on the database.
In non transactional controllers, methods returning from the service layer return detached entities because the session is closed. This is normal, the solution is to either use
OpenSessionInViewor do queries that eager fetch the results the controller knows it needs.
Having said that, it's not a crime to make controllers transactional, it's just not the most frequently used practice.