Uma luz sobre lock pessimista no hibernate pelo amor de deus....  XML
Índice dos Fóruns » Ferramentas, Frameworks e Utilitários
Autor Mensagem
mizael86
Java Ninja

Membro desde: 18/01/2008 10:24:27
Mensagens: 262
Offline

Galera, eu ja to doido aqui de tanto procurar, entao pesso que qualquer informação que possam me dar ja ajuda

Bom, eu gostaria de saber basicamente como que implementaria o lock pessimista no hibernate pra web. O meu grande problema é que quando loco um registro em uma transacao, ele so sera liberado quando eu comitar essa transacao. Porem pra web é dificil guardar uma transacao para ser comitada em outra requisicao. O maior problema mesmo é que se essa transacao nao for comitada o registro continua locado ate que o java libere a instancia dela. Em fim, como eu poderia implementar o lock pessimista na web? Por favor, alguem da uma luz.

Eu implementei o lock pessimista, funciona bem. O usuario nao vai conseguir atualizar se alguem ja atualizou na frente. Mais ai surge o problema de que o coitado do usuario que nao vai poder atualizar poderia ter sido o primeiro a pegar o registro, alterou tudo em sua tela mais nao vai conseguir comitar so pq alguem foi mais rapido que ele. O que eu gostaria eh que quando um usuario marco um registro para ser alterado, ninguem consiga altera-lo ate q o registro seja liberado. Isso em desktop eh facil, agora pra web ta dificil achar uma boa solução. Vlw ae galera, to na aguarda.
thingol
Moderador

Membro desde: 29/07/2004 16:10:13
Mensagens: 17543
Offline

http://www.hibernate.org/hib_docs/reference/en/html/transactions.html

Leia:
11.1.2. Long conversations


[WWW]
mizael86
Java Ninja

Membro desde: 18/01/2008 10:24:27
Mensagens: 262
Offline

thingol, eu ja li que so essa parte mais nao cheguei ao que eu queria, veja so



Versionamento automático - O Hibernate pode fazer o controle automático de concorrência otimista para
você, ele pode automaticamente detectar se uma modificação concorrente ocorreu durante o tempo de interação
do usuário. Geralmente nós verificamos somente no fim da conversação.

? Detached Objects- se você se decidir usar o já discutido pattern session-per-request, todas as instâncias carregadas
estarão no estado destacado durante o tempo em que o usuário estiver pensando. O Hibernate permite
que você reatache os objetos e persita as modificações, esse pattern é chamado sessionper-
request-with-detached-objects. É usado versionamento automatico para isolar as modificações concorrentes.

? session-per-conversation e faz o reatamento uniforme desnecessário. Versionamento automático é usado
para isolar modificações concorrentes e a session-per-conversation usualmente não é permitido para ser nivelado
automaticamente, e sim explicitamente.


A primeira opcao é o lock otimista, que seria versionando, nao é interessante para mim, pois ele so verifica a validade quando se tenta atualizar.

Os outros dois eu nao entendi, se vc puder me explicar eu agradeço.
thingol
Moderador

Membro desde: 29/07/2004 16:10:13
Mensagens: 17543
Offline

Que tipo de aplicação é a sua?
Digamos que o vendedor de uma loja de materiais de construção queira vender 100 metros quadrados de azulejos, e o estoque tenha 150 metros quadrados; além disso, ele possa ir entrando com outros itens (cimento, areia. etc.)
Se ele simplesmente bloquear a atualização do estoque de azulejos, ele não deixará os outros vendedores venderem azulejos.
Em vez disso, ao entrar com o item "azulejos", na verdade ele deixa já reservado no estoque 100 metros quadrados (ou seja, enquanto ele está entrando com os outros itens os outros vendedores só podem contar com 50 metros quadrados no estoque), e só quando ele acabar de entrar com os outros itens, e receber a confirmação da financeira é que a transação será efetivamente concluída (removendo 100 m quadrados do estoque).
Veja se a sua transação não é algo parecido com isso (ou seja, você tem de levar isso explicitamente na aplicação).

Outra forma que foi apontada é essa história de versionamento. Acho que você já ouviu falar - se a versão da transação mudou de uma tela para outra, você aborta a transação, porque a base foi alterada por outra transação.


[WWW]
mizael86
Java Ninja

Membro desde: 18/01/2008 10:24:27
Mensagens: 262
Offline

Certo entendi. Mais o meu caso seria assim:

Eu tenho digamos uma tabela com informacoes de uma cidade. Um usuario vai e seleciona uma cidade para poder editar. Ai digamos que outro usuario tambem faz isso em seguida. Se eu trabalhar com versionamento, apenas o primeiro usuario que salvar as alteracoes poderam de fato alterar. Quando o segundo usuario tentar, vai da erro de versao, pois a versao foi atualizada. O problema é que o cara pode ter pasado 1 hora para digitar os dados e no final nao vai poder atualizar pq alguem foi mais rapido que ele.

O que gostaria é que quando alguem selecionase o registro para edicao, nenhum outro usuario pode-se fazer o mesmo ate q o registro fosse salvo, comitado ou cancelado a edicao entende?? Ai que entra o lock pesimista, ele faz isso, o problema é que como eu persisto uma transacao na web? Pq ai eu teria q abrir uma transacao, locar o registro e aguardar ate o usuario dar um comit nele ou um rool back ou fechar a transacao, mais ai eu teria q persistir essa transacao, como fazer isso?? :/
Mauricio Linhares
Moderador
[Avatar]

Membro desde: 09/01/2005 23:28:22
Mensagens: 3717
Localização: João Pessoa, Paraíba - Brasil
Offline

Você não acha que travar a linha da tabela é uma péssima idéia não?

O ideal seria utilizar o lock otimista e em vez de voce jogar a exceção pro usuário, mostrar a ele que a informação foi atualizada e mostrar as diferenças pra ele.

Meu blog sobre desenvolvimento | My Last.fm | @mauriciojr

Screencast de Introdução a linguagem Objective-C
[WWW]
mizael86
Java Ninja

Membro desde: 18/01/2008 10:24:27
Mensagens: 262
Offline

Sim, é uma opcao tambem. Porem em certos casos no meu contexto seria interessante travar a linha.

Um exemplo:

Digamos que meu sistema seja de uma compania de telefone. Eu tenho meu telefone residencial la. Ai digamos que eu ligue para a central para atualizar a data de vencimento da fatura. E digamos que no mesmo instante minha esposa ligue tambem. Nesse caso o primeiro que salvar realizara a alteração. O segundo ficara conversando no telefone um tempao pra no final receber a mensagem q alguem ja alterou.

O ideal seria que o primeiro q entrar travar o registro, e entao se alguem tentar travar naquele momento receba logo a mensagem que alguem ta tentando alterar o registro, seria mais viavel entende?
mizael86
Java Ninja

Membro desde: 18/01/2008 10:24:27
Mensagens: 262
Offline

O que eu gostaria é teoricamente simples. Seria locar um registro. Posteriomente quando for comitar, saber atravez do numero da versao que fui eu quem locou o registro, e entao liberar o update. A questao é que o banco so sabe quem locou o registro pela sessao da transacao, se a transacao nao for a mesma, vc nunca poderá comitar o registro. Ai eu me pergunto, teria que guardar o objeto Transaction na sessao do usuario HTTPSession? :/ O Hibernate nao teria como recuperar uma transacao por um dado locado pela versao, sei la, algo do tipo?
Mauricio Linhares
Moderador
[Avatar]

Membro desde: 09/01/2005 23:28:22
Mensagens: 3717
Localização: João Pessoa, Paraíba - Brasil
Offline

mizael86 wrote:O ideal seria que o primeiro q entrar travar o registro, e entao se alguem tentar travar naquele momento receba logo a mensagem que alguem ta tentando alterar o registro, seria mais viavel entende?


E se o cara abrir a aplicação, carregar os dados (travando a linha) e for tomar um cafezinho?

Isso acontece bem mais do que você imagina

De qualquer forma, se você quer fazer isso usando o Hibernate, é do jeito que o Thingol já falou, mas você também pode fazer no braço com uma coluna do tipo "sendo_atualizado". Só não se esqueça de um pequeno detalhe, se você estiver usando uma coluna pra fazer o controle e a conexão do cara cair ou acontecer algum problema na aplicação, essa linha nunca mais vai ser liberada e se você estiver usando um banco de dados como SQL Server ou MySQL que começam a travar páginas de dados quando os locks aumentam muito você pode travar outras linhas que não tem nadas haver com a história.

Eu ainda não vi casos onde locks pessimistas são uma boa opção, tenha cuidado com o que você vai fazer.

Meu blog sobre desenvolvimento | My Last.fm | @mauriciojr

Screencast de Introdução a linguagem Objective-C
[WWW]
mizael86
Java Ninja

Membro desde: 18/01/2008 10:24:27
Mensagens: 262
Offline

Mauricio, eu estou ciente desses problemas, e ja encontrei solucao para todos.

Tipo, o hibernate tem um setTimeout para cada transacao, o que evita do usuario ir tomar um cafezinho ehehhe, se ele nao terminar o serviço dele em tantos minutos, ele perde a transacao.

A questao do registro ficar locado pra sempre, isso se resolveria de duas formas: quando o usario logar, eu posso verificar na sessao do oracle se existe algum lock pendente para ele, e entao kila-lo. Junto com essa opcao, seria com o timeout da transacao, entao nao correria tantos riscos. A ideia do "esta atulizando" seria ruim pq ficaria dificil controlar quando o usuario realmente ta atualizando. Se por algum problema ficar sempre TA ATUALIZANDO lasca tudo. O ideial mesmo seria locar e poder recuperar a transacao.
Mauricio Linhares
Moderador
[Avatar]

Membro desde: 09/01/2005 23:28:22
Mensagens: 3717
Localização: João Pessoa, Paraíba - Brasil
Offline

Se você não quer usar locks otimistas, entao coloque a sessão aberta na sessão http do usuário, fazendo um lock nessa linha, não tem outro jeito.

Meu blog sobre desenvolvimento | My Last.fm | @mauriciojr

Screencast de Introdução a linguagem Objective-C
[WWW]
mizael86
Java Ninja

Membro desde: 18/01/2008 10:24:27
Mensagens: 262
Offline

É, to vendo que vai ser a unica solucao. Gerencias as transacoes na sessao de usuario. O lock otimista sera usado, porem pra alguns casos o pesimista tbm é necessario.
danieldestro
Moderador
[Avatar]

Membro desde: 04/09/2002 17:26:16
Mensagens: 6667
Localização: São Paulo / Catanduva
Offline

No JPA tem o "version". No Hibernate não tem isso também? Não ajuda?
Esse é o típico caso complexo que muitos enfrentam e a solução vai depender muito do que o usuário pode ou não aceitar no uso do aplicativo.

gotjava?
Doe sangue
What You See Is What You Get!
Apostilas de Java grátis!
RefsCALL - Bandeira Eletrônica para Árbitro de Futebol
[WWW]
mizael86
Java Ninja

Membro desde: 18/01/2008 10:24:27
Mensagens: 262
Offline

o version versiona o dado, de forma q nao pode ser atualizado com versoes diferente, mais nao tem muito haver com o lock pessimista nao. Resolve alguns casos, outros nao
sergiotaborda
GUJ Expert
[Avatar]

Membro desde: 22/03/2005 20:57:48
Mensagens: 3433
Offline

mizael86 wrote:Certo entendi. Mais o meu caso seria assim:

Eu tenho digamos uma tabela com informacoes de uma cidade. Um usuario vai e seleciona uma cidade para poder editar. Ai digamos que outro usuario tambem faz isso em seguida. Se eu trabalhar com versionamento, apenas o primeiro usuario que salvar as alteracoes poderam de fato alterar. Quando o segundo usuario tentar, vai da erro de versao, pois a versao foi atualizada. O problema é que o cara pode ter pasado 1 hora para digitar os dados e no final nao vai poder atualizar pq alguem foi mais rapido que ele.

O que gostaria é que quando alguem selecionase o registro para edicao, nenhum outro usuario pode-se fazer o mesmo ate q o registro fosse salvo, comitado ou cancelado a edicao entende??


O seu problema não é usar o hibernate é usar lock pessimista. Isso é péssimo.
O problema é que se acontecer algum problema e o lock não for limpo o registro não poderá ser editado nunca mais.

O seu pensamento deve ser proabilitistico. É altamente inprovável que duas pessoas editem o mesmo registro ao mesmo tempo. Se o cara demorou uma hora o problema é dele. Ele pode repetir a operação. Coisa que não pode ser o lock ficar pendurado.

Criando sua própria API de Validação



Blog do MiddleHeaven
[WWW]
 
Índice dos Fóruns » Ferramentas, Frameworks e Utilitários
Ir para:   
Powered by JForum 2.1.8 © JForum Team