La chiamata al metodo Spring @Transaction dal metodo all’interno della stessa class, non funziona?

Sono nuovo di Spring Transaction. Qualche cosa che ho trovato davvero strano, probabilmente l’ho capito bene. Volevo avere una transazione attorno al livello del metodo e ho un metodo chiamante all’interno della stessa class e sembra che non gli piaccia, deve essere chiamato dalla class separata. Non capisco come sia ansible. Se qualcuno ha un’idea su come risolvere questo problema, sarei molto grato. Vorrei usare la stessa class per chiamare il metodo transazionale annotato.

Ecco il codice:

public class UserService { @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 users) { for (User user : users) { addUser(user.getUserName, user.getPassword); } } } 

È un limite di Spring AOP (oggetti dinamici e cglib ).

Se configuri Spring per utilizzare AspectJ per gestire le transazioni, il tuo codice funzionerà.

L’alternativa semplice e probabilmente migliore è quella del refactoring del codice. Ad esempio una class che gestisce gli utenti e una che elabora ciascun utente. Funzionerà quindi la gestione della transazione predefinita con Spring AOP.


Suggerimenti per la configurazione per la gestione delle transazioni con AspectJ

Per consentire a Spring di utilizzare AspectJ per le transazioni, è necessario impostare la modalità su AspectJ:

  

Se utilizzi Spring con una versione precedente alla 3.0, devi aggiungerlo alla tua configurazione di Spring:

    

Il problema qui è che i proxy AOP di Spring non si estendono ma piuttosto avvolgono l’istanza del servizio per intercettare le chiamate. Ciò ha l’effetto che qualsiasi chiamata a “this” dall’interno dell’istanza del servizio viene invocata direttamente su quell’istanza e non può essere intercettata dal proxy wrapping (il proxy non è nemmeno a conoscenza di tale chiamata). Una soluzione è già menzionata. Un altro elegante sarebbe semplicemente avere Spring iniettare un’istanza del servizio nel servizio stesso e chiamare il metodo sull’istanza iniettata, che sarà il proxy che gestisce le transazioni. Ma sappi che questo può avere anche effetti collaterali negativi, se il tuo bean di servizio non è un singleton:

   ...  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 users) { for (User user : users) { self.addUser(user.getUserName, user.getPassword); } } } 

Questa è la mia soluzione per l’ auto-invocazione :

 private SBMWSBL self; @Autowired private ApplicationContext applicationContext; @PostConstruct public void postContruct(){ self = applicationContext.getBean(SBMWSBL.class); } 

Con Spring 4 è ansible auto-potenziato

 @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 } } 

Puoi autowired BeanFactory all’interno della stessa class e fare a

getBean(YourClazz.class)

Verificherà automaticamente la tua class e terrà conto della tua annotazione @Transactional o di altro tipo.

Il problema è legato al modo in cui le classi di carico delle molle e i proxy. Non funzionerà, finché non scrivi il tuo metodo / transazione interiore in un’altra class o vai in un’altra class e poi di nuovo nella tua class e poi scrivi il metodo di trascrizione annidato interno.

Per riassumere, i proxy di spring non consentono gli scenari che stai affrontando. devi scrivere il secondo metodo di transazione in un’altra class