true transaction transacciones requires_new data java spring aspectj spring-aop

java - transacciones - transaction spring data



La llamada al método Spring @Transaction por el método dentro de la misma clase, ¿no funciona? (5)

Con Spring 4, es posible Autoconexionarse

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

Soy nuevo en Spring Transaction. Algo que encontré realmente extraño, probablemente entendí esto correctamente. Quería tener un nivel de método transaccional y tengo un método de llamada dentro de la misma clase y parece que no le gusta, tiene que ser llamado desde la clase separada. No entiendo cómo es eso posible. Si alguien tiene una idea de cómo resolver este problema, lo agradecería enormemente. Me gustaría utilizar la misma clase para llamar al método transaccional anotado.

Aquí está el código:

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


El problema aquí es que los proxies AOP de Spring no se extienden sino que envuelven su instancia de servicio para interceptar llamadas. Esto tiene el efecto de que cualquier llamada a "esto" desde su instancia de servicio se invoca directamente en esa instancia y no puede ser interceptada por el proxy de envoltura (el proxy ni siquiera es consciente de dicha llamada). Una solución ya se menciona. Otro ingenioso sería simplemente hacer que Spring inserte una instancia del servicio en el servicio mismo, y llame a su método en la instancia inyectada, que será el proxy que maneja sus transacciones. Pero tenga en cuenta que esto puede tener efectos secundarios negativos también, si su servicio bean no es un singleton:

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


Es una limitación con Spring AOP. (objetos dinámicos y CGLIB)

Si configura Spring para usar AspectJ para manejar las transacciones, su código funcionará.

La mejor y más sencilla alternativa es refactorizar tu código. Por ejemplo, una clase que maneja usuarios y otra que procesa a cada usuario. Entonces el manejo predeterminado de las transacciones con Spring AOP funcionará.

Consejos de configuración para manejar transacciones con AspectJ

Para permitir que Spring use AspectJ para las transacciones, debe establecer el modo en AspectJ:

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

Si está utilizando Spring con una versión anterior a la 3.0, también debe agregar esto a su configuración de Spring:

<bean class="org.springframework.transaction.aspectj .AnnotationTransactionAspect" factory-method="aspectOf"> <property name="transactionManager" ref="transactionManager" /> </bean>


Esta es mi solución para la auto invocación.

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


Puede autoenlazar BeanFactory dentro de la misma clase y hacer una

getBean(YourClazz.class)

Automatizará automáticamente tu clase y tendrá en cuenta tu @Transactional u otra anotación aop.