Estou desenvolvendo uma aplicação utilizando Spring + JPA + Hibernate e me deparei com um problema em persistências concorrentes, ou seja, quando duas ou mais pessoas (maquinas distintas) executam a mesma ação, ao mesmo tempo da um erro em uma das persistencias. Notei esse comportamento quando adicionei this.factory.close(); this.manager.close(); mas não tenho certeza se essa é a causa
Como poderia fazer o tratamento das persistencias concorrentes?
Erro em persistencia concorrente com Spring + JPA
10 Respostas
vc ta dizendo que tem duas apps com hibernate usando um banco só é isso??
Não, a aplicação é a mesma.
A mesma aplicação sendo acessada de máquinas diferentes executando a mesma ação
é uma app web que roda no browser??
Isso, é uma aplicação WEB
A princípio seria interessante você postar o erro que está ocorrendo…
Em relação ao close você deve dar apenas em EntityManagers gerenciados pela aplicação, criados a partir de um EntityManagerFactory e é claro que vc não pode dar um close antes de ter chamado um save por exemplo…
Por este e outros problemas na minha opinião é melhor utilizar um EntityManager gerenciado pelo container(não sei se é o seu caso) pois dessa forma não é necessário ficar dando close, tratar transações, concorrência…
Caro Breno, Infelizmente não é possível deixar o EntityManager gerenciado pelo container, pois tenho vários datasources dinâmicos e são atribuídos pela aplicação. Tenho tb EntityManager gerenciado pelo container, este realmente não dão problemas. O erro realmente só acontece a partir dos um EntityManagerFactory’s criado dentro da aplicação. Notei ainda que o erro só aconte quando depois de um persistencia fecho a sessão com EntityManagerFactory.close. caso não feche não da erro mas fica aberto sessões no banco de dados. Imagina só a cada persistencia uma sessão aberta, não dá!
Lembrando que o problema ocorre qdo 2 máquinas distintas executam o mesmo comando ao mesmo tempo.
Entendi… Mas tbm é possível ter mais de um data source em Entity Managers gerenciados pelo container, basta vc criar as unidades de persistência referentes ao seu data sorce no persistence.xml e na hora da injeção do Entity Manager diferencia-los utilizando o atributo unitName …
Mas enfim, voltando ao seu problema não sei se é a melhor alternativa mas talvez você possa “sincronizar na mão” o acesso na hora de persistir seus dados, nem sempre essa é a melhor alternativa pelo fato de você ter uma perda com o desempenho…
Espero ter ajudado…
Tentei listar meus DS’s (são 9 bancos) no persistence.xml, mas ficou muito pesado pra fazer o deploy, e ainda com o agravante de que se pelo menos 1 banco não estiver no ar compromete a aplicaçã inteira que não carrega.
Quanto a “sincornizar na mão”…como posso fazer isso Breno?
Sincronizar seria algo do tipo:
public synchronized void meuMetodo(){
//faça algo
}
//ou
public void meuMetodo(){
synchronized (meuObjeto){
//faça algo
}
}
Mas como te falei nem sempre é a melhor alternativa…
Com esse número alto de data sources eu pensaria em algo como desacoplar suas entidades específicas e modularizar sua aplicação…
OK, vou ver o que consigo por aqui, obrigado pelas sugestões. Acho realemte que modularizar a aplicação é uma boa tipow, criar um pool de conexões separados e tals, vou amadurecer a idéa . obrigado e abraços.