2013-08-28 3 views
8

Я видел много комментариев в стек переполнения статей я нашел некоторые вещи, о любом @Transactional использования с @Service или @ControllerПочему @Transactional с @Service вместо с @Controller

«Как правило, на сервисный уровень следует отправить транзакцию».

«Нормальный случай будет аннотировать на уровне слоя сервиса»

«Мозговые сделки относятся на уровне сервиса. Это тот, который знает о единицах работы и случаи использования. Это правильный ответ, если вы есть несколько DAO, введенных в Службу, которые должны работать вместе в одной транзакции ». [Source]

Минусом использовать @Transactional с @service слоем

Если у меня было 2 способами, например saveUser() и saveEmail() (потому что я хранить электронную почту в базе данных, чтобы отправить их позже - как очередь), я бы создал в своей службе метод saveUserAndSendEmail (Пользователь пользователя), который был бы транзакционным. [Source]

Это означает, что я создаю много методов в уровне услуг вместо одного Сохранить шаблонный метод, как следовать

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)....

ПРЕОДОЛЕН эту ситуацию

Пользуюсь @Transactional в @Controller и просто сделать Generic Сохранить метод и сохранить все объекты/модель, используя этот простой метод сохранения. и если какой-либо метод не сможет сэкономить, то все транзакции в откате контроллера будут успешными.

Другая ситуация, убедитесь, что @Transactional следует использовать с @Controller

В @Controller:

pt.save(entity1); 
pt.save(entity2); 
int a = 2/0; 
pt.save(entity3); 

В случае, @Transactional на службе, первые 2 объект успешно сохранен, но третий не откат всех транзакций

В случае, @Transactional на @Controller весь tran откат отката в качестве исключения

Почему переполнение стека спрашивает: «Не делайте транзакций в своем контроллере.Поместите их в классах обслуживания слоя. "? [source]

+0

Пожалуйста, не используйте разметку кода для текста. Вы можете использовать кавычки для котировок, если хотите. – Flexo

+3

Я думаю, что лучшим решением в этом случае является создание другого уровня уровня между «контроллером» и «службой». Как я вижу, «контроллер» обрабатывает вызовы и готовит вары для обработки и ведения логики на них. «Сервис» обрабатывает все файлы базы данных. и модель, которая должна находиться между «контроллером» и «службой», может сделать некоторую логику. В вашем примере выполнение нескольких операций сохранения - это логические действия с данными. что означает, что они помещаются в 'model' и warp' model' с 'транзакционным', если необходимо – oak

+0

Ваши методы' saveUser() 'и' saveEmail() 'должны быть в слое DAO. Затем вы создаете метод 'saveUserAndSendEmail (User user)' в транзакционном слое Service. – xli

ответ

15

Вы спрашиваете о наилучшей практике, а также лучшие практики, чтобы отметить @Transactional в слое службы, поскольку @Controller не должен знать, сохраняемость данных в логике MVC.
@Service построен на прецеденте, полученном при анализе, и знает об устройстве работ, а также реализуется мышление с точки зрения повторного использования: если вы переключитесь с веб-контекста на рабочий стол (например, или на какой-либо другой визуальный интерфейс), где @Controller слой не существует, у вас нет проблем, потому что все инкапсулировано в сервисный уровень.
A @Service - это контракт и модификация в настоящем n не должен требовать перезаписи кода @Service.
Но Spring не заботится о том, где вы разместите свои границы транзакций, вы можете надеть @Controller, но ваше приложение может быть сложнее поддерживать.

Надеюсь, это достаточно ясно. Извините, если нет; Английский не мой родной язык.

0

Контроллер прочно расположен на уровне видимости, который можно изменить в любое время. Служба по-прежнему владеет единицами работы и должна работать правильно независимо от того, к какому виду доступа. Мой ответ here все еще стоит.

+0

Его средства Я должен создать много методов для сохранения, таких как 'saveAccount'' saveAccountAudit'' saveAccountAuditEntries'? –

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; 
    } 
} 
2

только, чтобы другие знают, интерфейс аннотаций обескуражены

Spring рекомендует только аннотацию конкретные классы (и методы конкретных классов) с аннотацией @Transactional, в отличие от аннотирования интерфейсов. Вы, конечно, можете поместить аннотацию @Transactional на интерфейс (или метод интерфейса), но это работает только так, как вы ожидали бы, если вы используете прокси на основе интерфейса. Тот факт, что аннотации Java не наследуются от интерфейсов, означает, что если вы используете прокси-классы на основе класса (proxy-target-class = "true") или аспект, основанный на ткачестве (mode = "aspectj"), тогда параметры транзакции не распознается инфраструктурой проксирования и переплетения, и объект не будет завернут в транзакционный прокси, что будет явно плохо.

Смежные вопросы