Mapeamento Many to Many com NHibernate

No post passado, Mapeamento One to Many com NHibernate, descrevi como fazer uma mapeamento One to Many (um para muitos), hoje vamos ver como fazer uma mapeamento Many to Many (muitos para muitos).

Nosso exemplo de hoje será uma entidade Livro e outra entidade Autor, onde um livro pode ser escrito por vários autores, e um autor pode escrever vários livros, dessa forma temos um relacionamento entre as entidades de muitos para muitos, dessa forma devemos criar uma tabela auxiliar contendo somente as chaves de cada entidade.

1) Criando as Entidades

Autor.cs

A entidade Autor possui uma lista de Livros

[sourcecode language=”csharp”]
public class Autor
{
public virtual int IdAutor { get; set; }
public virtual string Nome { get; set; }
public virtual DateTime DataNascimento { get; set; }
public virtual IList<Livro> Livros { get; set; }
}
[/sourcecode]

Livro.cs

A entidade Livro possui uma lista de Autores

[sourcecode language=”csharp”]
public class Livro
{
public virtual int IdLivro { get; set; }
public virtual string Nome { get; set; }
public virtual DateTime DataLancamento { get; set; }
public virtual IList<Autor> Autores { get; set; }
}
[/sourcecode]

2) Criando os Mapeamentos

Autor.hbm.xml

Criamos um BAG que onde vamos criar a tabela auxiliar (tb_livro_autor) e criamos uma propriedade muitos para muitos com a tabela livro

[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="Autor" table="tb_autor">

<id name="IdAutor" access="property" column="id_autor" 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="DataNascimento" not-null="true" access="property"
type="DateTime">
<column name="data_nascimento" />
</property>

<bag name="Livros" table="tb_livro_autor" cascade="save-update">
<key column="id_autor" />
<many-to-many class="Livro" column="id_livro" not-found="ignore" />
</bag>

</class>

</hibernate-mapping>
[/sourcecode]

Livro.hbm.xml

Criamos um BAG que onde vamos criar a tabela auxiliar (tb_livro_autor) e criamos uma propriedade muitos para muitos com a tabela autor

[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="Livro" table="tb_livro">

<id name="IdLivro" access="property" column="id_livro" 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="DataLancamento" not-null="true" access="property"
type="DateTime">
<column name="data_lancamento" />
</property>

<bag name="Autores" table="tb_livro_autor" cascade="save-update">
<key column="id_livro" />
<many-to-many class="Autor" column="id_autor" not-found="ignore" />
</bag>

</class>

</hibernate-mapping>
[/sourcecode]

3) Testando

Vamos cadastrar um novo Autor com seus Livros

[sourcecode language=”csharp”]
public ActionResult Create()
{
try
{
IList<Livro> livros = new List<Livro>();

Autor autor = new Autor();
autor.Nome = "Nome do autor";
autor.DataNascimento = DateTime.Now;

Livro livro1 = new Livro();
livro1.Nome = "Nome do livro 1";
livro1.DataLancamento = DateTime.Now;
livros.Add(livro1);

Livro livro2 = new Livro();
livro2.Nome = "Nome do livro 2";
livro2.DataLancamento = DateTime.Now;
livros.Add(livro2);

autor.Livros = livros;

_autorRepository.Salvar(autor);

return View();

}
catch (Exception ex)
{
log.Debug("ERRO", ex);
throw ex;
}
}
[/sourcecode]

Veja o objeto Autor criado com sua lista de Livros

Vamos ver se os registros foram gravados corretamente no BD

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.