Solucionado (ver solução)
Solucionado
(ver solução)
7
respostas

chave <id> no hibernate-mapping para Categoria

Caros, tentei montar o mapping da categoria com o

<generator class="identity"/>

mas o Banco de dados (uso Postgres) criava um id diferente independente do que a View retornava no Form. Era mais estranho ainda, pois para fazer "funcionar" da primeira vez eu tive que adicionar session.Save(produto.Categoria) no ProdutoDAO.

Solucionei todos os problemas removendo o generator e deixando o Form dar o Id para a classe. Está correto?

O mapping ficou assim:

<class name="Categoria">
    <id name="Id">

    </id>
    <property name="Nome"/>
   ...
7 respostas
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="Loja_NHibernate"
                   namespace="Loja_NHibernate.Entidades">
  <class name="Categoria">
    <id name="Id">
      <generator class="identity"/>
    </id>
    <property name="Nome"/>
    <bag name="Produtos" inverse="true">
      <key column="CategoriaId"/>
      <one-to-many class="Produto"/>
    </bag>
  </class>
</hibernate-mapping>

Oi Leonardo

Isso não deveria estar acontecendo. Você poderia postar o erro que aconteceu quando você volta o generator="identity" e tira o session.Save(produto.Categoria)?

Olá Victor, Então, aí que está o problema. O VS não acusa erro, a única coisa que acontece é que o produto se associa com uma categoria que possui Id "sequencial" e não o Id que escolhi no momento do cadastro.

Estou usando o seguinte método para adicionar:

public void Adiciona(Produto produto)
        {

            ITransaction transacao = session.BeginTransaction();

            Categoria novacategoria = produto.Categoria;

            session.Save(novacategoria);

            session.Save(produto);

            transacao.Commit();
        }

Pelo o que eu observei fazendo o debug, quando eu peço para ele adicionar a nova categoria no Save(novacategoria) o BD cria uma nova categoria e coloca um Id sequencial e não o Id que eu especifiquei no form. Assim, quando eu consulto o produto que deveria estar na categoria 1 aparece "Produto2", "preço:10", "categoria: 3"

Aí eu adiciono outro produto na categoria 1. Quando vou consultá-lo aparece: "Produto3", "preço:10", "categoria: 4"

Pelo o que percebi o Postgre está dando o ID sequencial como chave-primária para a categoria independentemente do que eu informo.

Dúvida: será que eu deveria associar outro ID ou colocar outra chave?

Se precisar eu gravo um screen com os passos. Valeu!

OPÇÃO 2: Quando eu removo o save da novacategoria, usando o módulo:

public void Adiciona(Produto produto)
        {            
            session.Save(produto);
        }

E tento salvar um produto numa categoria que não existe:

Ele dá erro de chave do Postgre:

NHibernate.Error:

{"could not insert: [LojaWeb.Entidades.Produto][SQL: INSERT INTO Produto (Id, Nome, Preco, CategoriaId) VALUES (nextval ('hibernate_sequence'), ?, ?, ?) returning Id]"}


Inner Exception:

{"ERRO: 23503: inserção ou atualização em tabela \"produto\" viola restrição de chave estrangeira \"fkad09a82d9d9460e0\""}


Message: 

Chave (categoriaid)=(2) não está presente na tabela "categoria".
solução!

A opção 1 funciona da forma esperada. Quando chamamos o método Save em um objeto que está no estado transient (mesmo com o Id preenchido), o NHibernate considera que esse objeto é uma nova entidade e a insere no banco de dados sobrescrevendo com o Id gerado pelo banco de dados.

A opção 2 também tem o comportamento esperado. Não faz sentido algum tentar associar o produto com uma categoria que não existe no banco de dados e por isso o banco joga uma exceção indicando falha de integridade referencial.

Oi Leonardo

A sua dúvida foi resolvida?

Olá Victor, desculpe-me não ter respondido. Foi sim. Muito obrigado pelo apoio.