Pessoal, quero manter um objeto em lock com o hibernate de modo que uma outra aplicação que utiliza a mesma base de dados não consiga utilizar ele enquanto estou na minha aplicação.
Ok, utilizo o comando meuDAO.get(id,true) e fica em lock. O problema é quando termina o meu método o objeto perde o estado e não sei como manter em lock depois de terminar o método.
Não seria pq vc esta fechando a sessão…
Não estou fechando a sessão no código, mas quando termina o método o VRaptor já dá todos os commits e tal. E aí perde o estado do meu objeto.
Estou com o livro do hibernate aqui do meu lado, mas até agora não saí do lugar
Entao… quando acontece esses comits e tal… a sessao é fechada…
Acho que vai ser meio complicado manter a sessao… e ainda o lock abertos por tanto tempo… parece que vc quer retornar o html pro cara… e só depois quando o usuario resolver a vida dele… é que que vai fechar a sessao e lock… se for isso mesmo… sua aplicacao vai ter sérios problemas… pense em outra solucao
Tem alguma sugestão? É um webservice que enquanto está rodando, uma outra aplicação que utiliza a mesma base não pode usar o registro
A situacao é assim:
-
Cliente faz chamada no web service
-
Servidor pega o registro e dá lock
-
Servidor faz o processamento
-
Servidor termina o processamento e libera o lock
-
Cliente recebe os dados…
A sequencia é essa?
Analisando aqui o problema vai ser um pouco maior.
- Cliente faz a chamada no webservice.
- Servidor pega o registro e dá lock e retorna xml para o cliente com os dados.
- Cliente altera dados na aplicação e faz outra chamada no webservice para salvar os dados alterados.
- Salva os dados e libera o lock
Essa é a situação real que acontece
É… entao é o jeito mais complicado mesmo…
Voce poderia pegar o lock… e alterar o valor de uma coluna chama emuso por exemplo… e colocar valor true nela
Quanto o cliente for salvar e terminar com o registro coloca valor false…
Mas nao to achando essa solucao muito interessante de qualquer forma nao…
Mesmo porque… se o cliente nao retornar com a chamada aquele registro vai ficar com true pra sempre… se vc nao fizer outro mecanismo de timeout …
Nao daria pra na tentativa de salvar os dados… caso outra pessoa tivesse alterado… soltar uma exceção nao?
De qualquer jeito… funcionalmente nao to achando muito interessante essa funcionalidade…
Imagina…
Um cliente pegou o registro
Um segundo cliente tenta pegar o registro mas nao consegue porque ele está em uso por outra pessoa
O segundo cliente vai ter que esperar a boa vontade do primeiro para poder alterar o registro…
O segundo acho que vai ficar puto…
Num fica uma funcionalidade boa… entende?
[quote=yuripodho]Analisando aqui o problema vai ser um pouco maior.
- Cliente faz a chamada no webservice.
- Servidor pega o registro e dá lock e retorna xml para o cliente com os dados.
- Cliente altera dados na aplicação e faz outra chamada no webservice para salvar os dados alterados.
- Salva os dados e libera o lock
Essa é a situação real que acontece[/quote]
E se no momento que o cliente altera os dados na aplicação…
[list]Ele morreu de infarto :?: [/list][list]Caiu a conexão da internet :?: [/list][list]Deu apagão na luz :?: [/list][list]Resolveu sair pra almoçar :?: [/list][list]Foi dar uma xeretada no site do GUJ :?: [/list]
Ninguém mais tem acesso ao banco … :thumbdown:
[color=red]DEADLOCK [/color]neles :!:
[quote=Java Lover][quote=yuripodho]Analisando aqui o problema vai ser um pouco maior.
- Cliente faz a chamada no webservice.
- Servidor pega o registro e dá lock e retorna xml para o cliente com os dados.
- Cliente altera dados na aplicação e faz outra chamada no webservice para salvar os dados alterados.
- Salva os dados e libera o lock
Essa é a situação real que acontece[/quote]
E se no momento que o cliente altera os dados na aplicação…
[list]Ele morreu de infarto :?: [/list][list]Caiu a conexão da internet :?: [/list][list]Deu apagão na luz :?: [/list][list]Resolveu sair pra almoçar :?: [/list][list]Foi dar uma xeretada no site do GUJ :?: [/list]
Ninguém mais tem acesso ao banco … :thumbdown:
[color=red]DEADLOCK [/color]neles :!: [/quote]
Concordo…
Porém a solicitação foi essa mesma, o que estava acontecendo era de vários usuários estarem alterando o mesmo registro ao mesmo tempo. Então se um usuário estiver alterando deve lançar uma exception para os outros saberem que já está sendo utilizado.
Complexo. Se vc colocar o status como boolean, e o cara desistir da edição, vc fica com o registro travado no banco.
O que vc pode fazer é quando um usuário solicita edição do registro, vc verificar se há outro usuário editando esse mesmo registro, e retornar ele somente leitura.
Ao invés de usar o boleano para travar o registro, usava um date, e configurava um timeout , sei lá, 5 mim para edição, depois diso já era, pode editar de novo.
Se o primeiro usuário passar do tempo de edição, (demorar 6 minutos por exemplo) invalida a operação com um erro de timeout. ou melhor ainda, checa se alguém tentou editar o registro ao mesmo tempo, se sim dá timeout, se não confirma a alteração.
Mas é só uma idéia, acho que deve haver jeitos melhores pra solucionar isso.
Eu estava escrevendo uma sugestão pra vc…
Mas fiquei na dúvida…
[list]A base de dados é acessada por vários aplicativos ?[/list][list]Vários aplicativos acessam seu aplicativo que acessa a base de dados ?[/list][list]Usuários acessam o seu aplicativo que acessa a base de dados ?[/list]
Sim, são vários aplicativos (em Delphi) utilizando a mesma base. Uma delas consome o meu webservice. As aplicações em Delphi já colocam em lock, ou seja, se um deles está usando o meu webservice não consegue pegar o registro. Agora tem que fazer o contrário, quando acessa pelo webservice, as outras aplicações não podem usar esse registro.
Seu problema é alta concorrência.
Por ser um banco com acessos heterogênios cada aplicação deve manter seu lock pessimista.
A minha pergunta é: “Vc sabe programar Threads ?”
Vc sabe que atualmente vc só consegue dar lock enquanto estiver com a sessão do hibernate correto ?
A solução é que enquanto vc estiver na sessão do hibernate, lançar uma thread de verificação do tempo de inatividade da sua sessão http, lockando o mesmo campo numa outra sessão do hibernate.
Na segunda chamada pra atualização, vc usa NotifyAll e acorda essa thread e ela libera o lock em seguida vc pega o campo com outra sessão do hibernate e atualiza o dado, no fim do commit seu lock é liberado.
Isso impede os sistemas em Delphi de pegar o banco mas pra chamadas em seu webservice vc tem que implementar através de variável de sessão.