Erro em persistencia concorrente com Spring + JPA

10 respostas
J

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?

10 Respostas

nextuser

vc ta dizendo que tem duas apps com hibernate usando um banco só é isso??

J

Não, a aplicação é a mesma.
A mesma aplicação sendo acessada de máquinas diferentes executando a mesma ação

nextuser

é uma app web que roda no browser??

J

Isso, é uma aplicação WEB

B

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…

J

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.

B

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…

J

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?

B

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…

J

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.

Criado 9 de março de 2010
Ultima resposta 11 de mar. de 2010
Respostas 10
Participantes 3