Почему весной уровень распространения транзакций `REQUIRES_NEW` не работает? [Дубликат]

В качестве альтернативы вы можете использовать gem Protected Attributes gem , однако это наносит ущерб требованию сильных параметров. Однако, если вы обновляете более старое приложение, защищенные атрибуты предоставляют простой путь для обновления до тех пор, пока вы не сможете реорганизовать attr_accessible на сильные параметры.

70
задан Gray 30 October 2012 в 22:47
поделиться

6 ответов

С пружиной 4 возможно автоподключение

@Service
@Transactional
public class UserServiceImpl implements UserService{
    @Autowired
    private  UserRepositroy repositroy;

    @Autowired
    private UserService userService;

    @Override
    public void update(int id){
       repository.findOne(id).setName("ddd");
    }

    @Override
    public void save(Users user) {
        repositroy.save(user);
        userService.update(1)l
    }
}
2
ответ дан Almas Abdrazak 18 August 2018 в 18:47
поделиться

Это ограничение с Spring AOP. (динамические объекты и CGLIB)

Если вы настроите Spring на использование AspectJ для обработки транзакций, ваш код будет работать.

Простая и, вероятно, лучшая альтернатива - реорганизовать ваш код. Например, один класс, который обрабатывает пользователей, и один, обрабатывающий каждого пользователя. Тогда обработка транзакций по умолчанию с Spring AOP будет работать.

Советы по настройке для обработки транзакций с AspectJ

Чтобы включить Spring для использования AspectJ для транзакций, вы должны установить режим AspectJ:

<tx:annotation-driven mode="aspectj"/>

Если вы используете Spring с более старой версией, чем 3.0, вы также должны добавить это в свою конфигурацию Spring:

<bean class="org.springframework.transaction.aspectj
        .AnnotationTransactionAspect" factory-method="aspectOf">
    <property name="transactionManager" ref="transactionManager" />
</bean>
71
ответ дан Elnur Abdurrakhimov 18 August 2018 в 18:47
поделиться
  • 1
    Спасибо за информацию. Я переработал код на данный момент, но не могли бы вы прислать мне пример использования AspectJ или предоставить мне полезные ссылки. Заранее спасибо. Майк. – Mike 9 August 2010 в 17:54
  • 2
    В моем ответе добавлена ​​специфическая конфигурация AspectJ для транзакции. Я надеюсь, что это помогает. – Espen 10 August 2010 в 15:42
  • 3
    Спасибо, Эспен за вашу помощь. Оно работает!! – Mike 16 August 2010 в 14:19
  • 4
    Это хорошо! Кстати: Было бы неплохо, если бы вы могли отметить мой вопрос как лучший ответ, чтобы дать мне несколько моментов. (зеленая галочка) – Espen 16 August 2010 в 19:31
  • 5
    Это не работает для весны 4 ( – gstackoverflow 13 November 2015 в 13:14

Это мое решение для самозапуска.

private SBMWSBL self;
@Autowired private ApplicationContext applicationContext;

@PostConstruct
public  void postContruct(){
    self =applicationContext.getBean(SBMWSBL.class);
}
5
ответ дан Hlex 18 August 2018 в 18:47
поделиться

Проблема заключается в том, что прокси-серверы AOP Spring не распространяются, а скорее завершают ваш экземпляр службы, чтобы перехватывать вызовы. Это приводит к тому, что любой вызов «этого» из вашего экземпляра службы непосредственно вызывается в этом экземпляре и не может быть перехвачен прокси-сервером (прокси-сервер даже не знает о таком вызове). Уже упоминалось одно решение. Еще одним из излюбленных было бы просто заставить Spring вставить экземпляр службы в саму службу и вызвать ваш метод на введенном экземпляре, который будет прокси-сервером, который обрабатывает ваши транзакции. Но имейте в виду, что это может иметь и плохие побочные эффекты, если ваш сервисный компонент не является одиночным:

<bean id="userService" class="your.package.UserService">
  <property name="self" ref="userService" />
    ...
</bean>

public class UserService {
    private UserService self;

    public void setSelf(UserService self) {
        this.self = self;
    }

    @Transactional
    public boolean addUser(String userName, String password) {
        try {
        // call DAO layer and adds to database.
        } catch (Throwable e) {
            TransactionAspectSupport.currentTransactionStatus()
                .setRollbackOnly();

        }
    }

    public boolean addUsers(List<User> users) {
        for (User user : users) {
            self.addUser(user.getUserName, user.getPassword);
        }
    } 
}
46
ответ дан Kai 18 August 2018 в 18:47
поделиться
  • 1
    Если вы решите пойти по этому маршруту (будь то хороший дизайн или нет, это другое дело) и не используйте инъекцию конструктора, убедитесь, что вы также видите этот вопрос – Jeshurun 11 April 2012 в 23:25

Вы можете авторизовать BeanFactory внутри одного класса и делать

getBean(YourClazz.class)

. Он автоматически проксимизирует ваш класс и учитывает вашу @Transactional или другую аннотацию aop.

0
ответ дан LionH 18 August 2018 в 18:47
поделиться
  • 1
    Это считается плохой практикой. Даже инъекция bean-рекурсивно в себя лучше. Использование getBean (clazz) - это плотная связь и сильная зависимость от весенних классов ApplicationContext внутри вашего кода. Кроме того, получение bean-класса по классу может не работать в случае весенней упаковки компонента (класс может быть изменен). – Vadim Kirilchuk 28 September 2015 в 08:48

Проблема связана с тем, как классы весенней нагрузки и прокси. Это не сработает, пока вы не напишете свой внутренний метод / транзакцию в другом классе или не перейдете к другому классу, а затем снова придете к вашему классу и затем напишите внутренний метод вложенной транскокации.

Подводя итог, весенние прокси делают не разрешайте сценарии, с которыми вы сталкиваетесь. вам необходимо написать второй метод транзакции в другом классе

0
ответ дан Ujjwal Choudhari 18 August 2018 в 18:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: