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

[sourcecode language=”csharp”]
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; }
}
[/sourcecode]

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

Produto.cs

[sourcecode language=”csharp”]
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; }
}
[/sourcecode]

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.

[sourcecode language=”xml”]
<?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>
[/sourcecode]

Produto.hbm.xml

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

[sourcecode language=”xml”]
<?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>
[/sourcecode]

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:

[sourcecode language=”csharp”]
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;
}
}
[/sourcecode]

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!

Sobre Leandro Prado

Leandro Silveira Prado é Premier Field Engineer na Microsoft especializado em Application Lifecycle Management.