Relacionamento <one-to-many> com Hibernate

2 respostas
marciosdc

Gostaria que vocês pudessem me ajudar com o relacionamento <one-to-many> pois estou tendo um probleminha que eu não sei mais o que fazer… talvez precise descansar um pouco para solucionar :)…

Fiz os sequintes mapeamentos:

&lt;class name="Cliente"&gt;
    
        &lt;id name="codigo" type="integer"&gt;
        	&lt;generator class="sequence"&gt;
        		&lt;param name="sequence"&gt;sequencia_cliente&lt;/param&gt;
        	&lt;/generator&gt;
        &lt;/id&gt;
    
        &lt;property name="nome"								type="string"/&gt;
        &lt;property name="CPFCNPJ"							type="string"/&gt;
        &lt;property name="identidade"							type="string"/&gt;
        &lt;property name="telefone"							type="string"/&gt;
        
        ...
		
        &lt;set name="Endereco"
        	 table="endereco"
        	 cascade="save-update, delete"
        	 inverse="true"&gt;
        	 
			&lt;key column="codigo_cliente" not-null="true"/&gt;
			&lt;one-to-many class="business.cliente.Endereco" /&gt;
		&lt;/set&gt;
		
    &lt;/class&gt;

e

&lt;class name="Endereco"&gt;
    
        &lt;id name="codigo" type="integer"&gt;
        	&lt;generator class="sequence"&gt;
        		&lt;param name="sequence"&gt;sequencia_endereco&lt;/param&gt;
        	&lt;/generator&gt;
        &lt;/id&gt;
    
        &lt;property name="endereco"							type="string"/&gt;
        &lt;property name="complemento"						type="string"/&gt;
        &lt;property name="numero"								type="integer"/&gt;
        &lt;property name="bairro"								type="string"/&gt;
        &lt;property name="CEP"								type="string"/&gt;
        &lt;property name="cidade"								type="string"/&gt;
        &lt;property name="estado"								type="string"/&gt;
        &lt;property name="pais"								type="string"/&gt;
        
        &lt;many-to-one
			class="business.cliente.Cliente"
			name="Cliente"
			not-null="true"&gt;
			
			&lt;column name="codigo_cliente" /&gt;
		&lt;/many-to-one&gt;       
        
    &lt;/class&gt;

Bom, até aqui eu acho que está tudo bem… eu consigo recuperar os endereços de um cliente apenas solicitando Cliente sem precisar nenhuma linha de código a mais para recuperar os endereços. No entanto quando eu crio um novo Cliente e adiciono um endereço e peço para gravar o cliente, o seguinte processo ocorre:

Hibernate salva o cliente;

Hibernate: 
    select
        nextval ('sequencia_endereco')
Hibernate: 
    insert 
    into
        Cliente
        (nome, CPFCNPJ, identidade, telefone, codigo_tipo, codigo) 
    values
        (?, ?, ?, ?, ?, ?)

Hibernate salva o endereço utilizando o relacionamento que foi montado;

Hibernate: 
    insert 
    into
        Endereco
        (endereco, complemento, numero, bairro, CEP, cidade, estado, pais, codigo_cliente, codigo) 
    values
        (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

Porém o JDBC retorna a seguinte mensagem:

Caused by: java.sql.BatchUpdateException: Entrada em lote 0 insert into 
Endereco (endereco, complemento, numero, bairro, CEP, cidade, estado, pais, codigo_cliente, codigo) 
values     (Não tem, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, 21) foi abortada.

Como vocês podem perceber, a coluna codigo_cliente responsável por identificar o endereço por cliente não foi preenchido, ou seja, quando eu adicionei um cliente novo o hibernate não atualizou o codigo_cliente para a entidade endereço.

Bom, o que estou fazendo de errado?

2 Respostas

H

De acordo com seu mapeamento, o relacionamento só deve ser persistido quando o update ocorrer no endereço. Veja:

<set name="Endereco"  
             table="endereco"  
             cascade="save-update, delete"  
             inverse="true">  //aqui 


            <key column="codigo_cliente" not-null="true"/>   
            <one-to-many class="business.cliente.Endereco" />   
        </set>

Se você configurou este lado do relacionamento como inverso, para que seja persistido (até onde eu sei),

//você deve criar um Endereco
Endereco end = new Endereco();
...
end.setCliente();

Outra coisa que me chamou atenção, foi o nome das suas propriedades esterm fora do padrão (não começam com letra minúscula), pelo que está nos xml.

<property name="CEP"                                type="string"/>   

...

many-to-one   
            class="business.cliente.Cliente"  
            name="Cliente"  //aqui  
            not-null="true">   
               
            <column name="codigo_cliente" />   
        </many-to-one>          
           
...

<set name="Endereco"  //aqui
             table="endereco"  
             cascade="save-update, delete"  
             inverse="true">   
                
            <key column="codigo_cliente" not-null="true"/>   
            <one-to-many class="business.cliente.Endereco" />   
        </set>

Dá uma olhada nesses pontos e vê o que acontece…

marciosdc

Obrigado hadilson,

o que estava realmente faltando era configurar o outro lado do relacionamento, o que é obvio pois como é que o endereço iria saber qual o codigo do cliente a qual ele pertence? A princípio eu não tinha colocado essa informação pois achava que como eu estava utilizando o objeto endereço ( Para mim ) seria logico que o hibernate coletasse essa informação, no entanto as coisa nem sempre são flores na vida de um homem como diria o antigo amigo meu.

Obrigado mesmo hadilson.

Criado 29 de agosto de 2007
Ultima resposta 1 de set. de 2007
Respostas 2
Participantes 2