Duvida Cruel com Hibernate

6 respostas
kemperacc

Primeiro, antes de entenderem a minha duvida, voces terao de entender o cenario (que nao tem como mudar).

Tenho uma aplicacao desenvolvida sobre RMI, sendo que a GUI eh swing e o server eh java + hibernate + mysql, mais ou menos assim:

LADO CLIENTE                                                   LADO SERVIDOR
GUI SWING  <--------------------- RMI -----------------------> SERVER JAVA <-> HIBERNATE <->MYSQL

A aplicacao é ultra rápida nas buscas, edições, salvamentos, etc. Porém estou com um problema estrutural que é o seguinte:

  1. Usuário fulano abre o cadastro de um cliente para edição (um cliente que ja estava na base)
  2. fulano faz alteraçoes no cadastro
  3. Enquanto fulano ainda estava alterando os dados do cliente, outro usuario (cilano) abre o mesmo cliente para edição.
  4. Usuário fulano salva o registro que estava em edição.
  5. Usuário ciclano salva o registro que estava em edição.

Moral da história, o usuário fulano perdeu o serviço, pois os dados que vão prevalecer são os do último salvamento.

A pergunta é a seguinte: Há alguma forma de travar o objeto no banco de dados usando o hibernate mesmo depois de session.close()? Porque hoje pra cada chamada RMI é criada uma sessão, executado o procedimento e a sessão é fechada.

Então, ao ler um Cliente, logo em seguida a sessão é fechada. Ai quando vamos salvar o cliente, uma nova sessão é criada, salva-se o Cliente e fecha-se a sessao.

Este cenário de sessões eu nao posso mudar.

Alguém tem alguma sugestão?

Obrigado

6 Respostas

M

Veja se isso te atende:
http://docs.jboss.org/hibernate/stable/annotations/reference/en/html/entity.html
topico 2.2.1.2. Versioning for optimistic locking

Abracos,
Marco.

fabiocsilva

Tem vários materiais na net sobre lock. Dá um saque aqui:

http://www.google.com.br/search?hl=pt-BR&q=lock+otimista+hibernate&meta=&aq=f&aqi=&aql=&oq=

kemperacc

To comecando a entender o funcionamento, vejam se eh por ai:

Crio uma coluna no banco de dados (versao por ex. do tipo int), e na classe correspondente a esta tabela crio um campo do tipo Integer e mapeio.

E tenho que usar tambem o Lock Optimistic, porem estou usando o mapeamento atraves de xml, entao, como mapear este lock optimistic no xml?

Obrigado novamente

mrrbigu

Você pode utilizar o lock otimista ou o pessimista, se você usar o lock otimista, não haverá bloqueio do registro, mas o usuário poderá perder seu trabalho, pois no momento de salvar sua alteração é que haverá a comparação das versões, se a versão do banco já estiver mudado, não será permitido que o usuário salve.

A escolha entre um e outro vai depender da solução, ambos possuem pontos positivos e negativos.

kemperacc

Então, o que eu quero é o Otimista, se alguem ja tiver atualizado o registro no banco, ele nao permitirá que outra pessoa altere.

Agora, como mapear no XML?

Se alguem puder ajudar com um exemplo (pode ser so o xml)

Obrigado.

kemperacc

Otimo, funcionou perfeito:

Fiz assim:

Na classe Cliente criei o campo campo versao:

private Long versao = 0l;

//gets e sets....

E coloquei assim no mapeamento:

<hibernate-mapping>
    <class name="br.com.omegacodigos.ultra.modulos.cliente.Cliente" table="cliente" optimistic-lock="version">
        <id name="id" column="id_cliente" unsaved-value="0" type="java.lang.Long">
            <generator class="native" />
        </id>

        <version name="versao" access="field" column="versao" type="java.lang.Long"/>

        <!-- MAIS UMA PORRADA DE CAMPOS DA TABELA... -->
    
    </class>
</hibernate-mapping>

E na hora de salvar o registro, cerquei assim:

public Cliente salva(Cliente cliente) throws  RegistroModificadoException, RemoteException {


        Session sessao = super.getSession();
        Transaction tx = sessao.beginTransaction();

        try {


            sessao.saveOrUpdate(cliente);

            tx.commit();

        } catch (StaleObjectStateException ex) {

            tx.rollback();
            throw new RegistroModificadoException("Cliente modificado por outro usuario");

        } catch (HibernateException ex) {

            tx.rollback();
            throw new RemoteException( ex.getMessage());
        }

        return cliente;

    }

Nao posso passar as exceptions do HB para a gui swing porque la nao tem o hibernate.jar.

Funcionando perfeito, e o return Cliente é porque ai ja volta para a GUI a nova versao da classe, la eu chamo assim no JDialog:

this.cliente = this.ifacecliente.salva(this.cliente);

Obrigado pelas respostas.

Criado 15 de março de 2010
Ultima resposta 15 de mar. de 2010
Respostas 6
Participantes 4