Eu sou novo na Spring Transaction. Algo que achei muito estranho, provavelmente entendi direito.
Eu queria ter um método transacional em torno do nível de método e tenho um método chamador na mesma classe e parece que não gosta disso, tem que ser chamado de uma classe separada. Não entendo como isso é possível.
Se alguém tiver uma ideia de como resolver esse problema, eu ficaria muito grato. Eu gostaria de usar a mesma classe para chamar o método transacional anotado.
Aqui está o 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);
}
}
}
java
spring
aspectj
spring-aop
Mike
fonte
fonte
TransactionTemplate
abordagem: stackoverflow.com/a/52989925/355438Respostas:
É uma limitação do Spring AOP (objetos dinâmicos e cglib ).
Se você configurar o Spring para usar AspectJ para lidar com as transações, seu código funcionará.
A alternativa simples e provavelmente a melhor é refatorar seu código. Por exemplo, uma classe que lida com usuários e outra que processa cada usuário. Então, o tratamento padrão da transação com Spring AOP funcionará.
Dicas de configuração para lidar com transações com AspectJ
Para permitir que o Spring use AspectJ para transações, você deve definir o modo para AspectJ:
Se você estiver usando o Spring com uma versão anterior à 3.0, você também deve adicionar isso à configuração do Spring:
fonte
O problema aqui é que os proxies AOP do Spring não estendem, mas envolvem sua instância de serviço para interceptar chamadas. Isso tem o efeito de que qualquer chamada para "this" de dentro de sua instância de serviço é chamada diretamente nessa instância e não pode ser interceptada pelo proxy de agrupamento (o proxy nem mesmo está ciente de tal chamada). Uma solução já foi mencionada. Outro ótimo seria simplesmente fazer com que o Spring injetasse uma instância do serviço no próprio serviço e chamasse seu método na instância injetada, que será o proxy que manipulará suas transações. Mas esteja ciente de que isso também pode ter efeitos colaterais negativos, se seu bean de serviço não for um singleton:
fonte
UserService
tiver escopo singleton? E se for o mesmo objeto?Com o Spring 4 é possível autowired
fonte
A partir do Java 8, há outra possibilidade, que prefiro pelos motivos abaixo:
Essa abordagem tem as seguintes vantagens:
1) Pode ser aplicado a métodos privados . Portanto, você não precisa interromper o encapsulamento tornando um método público apenas para satisfazer as limitações do Spring.
2) O mesmo método pode ser chamado em diferentes propagações de transações e cabe ao chamador escolher o adequado. Compare estas 2 linhas:
3) É explícito, portanto mais legível.
fonte
TransactionHandler
como uma subclasse, e a subclasse chamar esses dois métodos naTransactionHandler
superclasse, ainda poderei obter os benefícios@Transactional
pretendidos?Esta é minha solução para auto-invocação :
fonte
Você pode autowired BeanFactory dentro da mesma classe e fazer um
getBean(YourClazz.class)
Ele automaticamente fará o proxy de sua classe e levará em consideração sua anotação @Transactional ou outra anotação aop.
fonte
O problema está relacionado a como classes de carregamento de mola e proxies. Não funcionará, até que você escreva seu método / transação interno em outra classe ou vá para outra classe e, em seguida, volte para sua classe e, em seguida, escreva o método de transcação aninhado interno.
Para resumir, os proxies spring não permitem os cenários que você está enfrentando. você tem que escrever o segundo método de transação em outra classe
fonte
Aqui está o que eu faço para pequenos projetos com uso apenas marginal de chamadas de método dentro da mesma classe. A documentação no código é altamente recomendada, pois pode parecer estranha para os colegas. Mas funciona com singletons , é fácil de testar, simples, rápido de conseguir e me poupa da instrumentação AspectJ completa. No entanto, para um uso mais intenso, aconselho a solução AspectJ conforme descrito na resposta do Espens.
fonte