Mapeamento One to Many com NHibernate

Quando estamos desenvolvendo sistemas concerteza vamos ter vários relacionamentos entre nossas entidades, um desses relacionamentos é um para muitos e nesse post vamos ver um exemplo de como fazer esse mapeamento usando o NHibernate.

Em nosso exemplo estaremos usando ASP NET MVC 2 com NHibernate 2 e banco de dados MySQL 5, vamos fazer um mapeamento de duas entidades Categoria e Produtos, onde uma Categoria possui vários Produtos, então mão no código. Se você não sabe como realizar a conexão com o NHibernate veja esse post Usando NHibernate com ASP NET MVC.

1) Criando as Entidades

Quando trabalhamos com o NHibernate temos que criar todas a propriedades (gets e sets) como virtual.

Categoria.cs

public class Categoria
{
    public virtual int IdCategoria { get; set; }
    public virtual string Nome { get; set; }
    public virtual string Descricao { get; set; }
    public virtual IList<Produto> Produtos { get; set; }
}

Veja que criamos uma propriedade do tipo IList que vai ter todos os produtos de uma determinada categoria.

Produto.cs

public class Produto
{
    public virtual int IdProduto { get; set; }
    public virtual string Nome { get; set; }
    public virtual string Descricao { get; set; }
    public virtual Categoria Categoria { get; set; }
}

2) Criando os Mapeamentos

Esses são os arquivos XML responsáveis pelo mapeamento das entidades.

Categoria.hbm.xml

Veja que criamos uma propriedade chamada BAG que será responsável por armazenar a nossa lista de produtos.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="ConexaoNHibernate.Entity"
                   namespace="ConexaoNHibernate.Entity" >

  <class name="Categoria" table="tb_categoria">

    <id name="IdCategoria" access="property" column="id_categoria" type="Int32">
      <generator class="native"></generator>
    </id>

    <property name="Nome" not-null="true" access="property" type="String">
      <column name="nome" length="100" />
    </property>

    <property name="Descricao" not-null="true" access="property" type="String">
      <column name="descricao" length="100" />
    </property>

    <bag name="Produtos" cascade="save-update" lazy="true" >
      <key column="id_categoria" />
      <one-to-many class="Produto" />
    </bag>

  </class>

</hibernate-mapping>

Produto.hbm.xml

Aqui temos uma propriedade Many to One onde definimos que um produto possui uma categoria.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="ConexaoNHibernate.Entity"
                   namespace="ConexaoNHibernate.Entity" >

  <class name="Produto" table="tb_produto">

    <id name="IdProduto" access="property" column="id_produto" type="Int32">
      <generator class="native"></generator>
    </id>

    <property name="Nome" not-null="true" access="property" type="String">
      <column name="nome" length="100" />
    </property>

    <property name="Descricao" not-null="true" access="property" type="String">
      <column name="descricao" length="100" />
    </property>

    <many-to-one name="Categoria" column="id_categoria"
                                 class="Categoria" not-null="true" />

  </class>

</hibernate-mapping>

OBS: Depois de criado os arquivos de mapeamento, não esqueça de alterar a propriedade Build Action para Embedded Resource

3) Testando

Vamos criar uma nova categoria, e depois criar os produtos dessa categoria e mandar salvar, veja abaixo o código:

public ActionResult Create()
{
    try
    {
	   IList<Produto> lst = new List<Produto>();

	   ICategoryRepository categoryRepository = new CategoryRepository();
	   Categoria category = new Categoria();
	   category.Nome = "Comida";
	   category.Descricao = "Descrição da categoria comida";
	   category.Produtos = lst;

	   Produto product1 = new Produto();
	   product1.Nome = "Arroz";
	   product1.Descricao = "Descrição do produto arroz";
	   product1.Categoria = category;
 	   lst.Add(product1);

	   Produto product2 = new Produto();
	   product2.Nome = "Feijão";
	   product2.Descricao = "Descrição do produto feijão";
	   product2.Categoria = category;
	   lst.Add(product2);

	   category = categoryRepository.Salvar(category);

	   return View();
    }
    catch (Exception ex)
    {
          log.Debug("ERRO", ex);
          throw ex;
    }
}

Quando executamos o método Salvar passamos o objeto categoria com a lista de produtos, o NHibernate será responsável por realizar a manipulação nas tabelas necessárias.

Veja o resultado da execução no banco de dados

Download do Projeto

Qualquer dúvida, opinião, reclamação mande seu comentário!

Um Abraço!

Leia mais

Sobre Leandro Prado

Leandro Silveira Prado é graduado em Sistemas de Informação pela PUC-PR, trabalho com desenvolvimento WEB desde 2003. Possui uma vasta experiência em integração de sistemas ja prestou serviços a grandes empresas como FBits Fábrica de Software, Instituto Curitiba de Informática, América Latina Logística e atualmente trabalha como Consultor ALM na especificações.com. Fanático por futebol e torcedor do melhor time do paraná - COXA