66
Programação OO com NHibernate Humberto Cardoso Marchezi 2010

NHibernate

Embed Size (px)

Citation preview

Programação OO com NHibernate

Humberto Cardoso Marchezi

2010

Programação OO com NHibernate

Agenda

Dia 1: Fundamentos de NHibernate

Para que serve ?

Quais as vantagens ?

O que é mapeamento objeto-relacional ?

Como funciona o mapeamento objeto-relacional no NHibernate ?

Exercícios (Mapeando uma classe simples – apenas propriedades)

Programação OO com NHibernate

Agenda

Dia 2: Associações no NHibernate

Como implementar uma associação vários-para-um (simples) ?

Exercício

Como implementar uma associação vários-para-um (posse) ?

Exercício

Como implementar uma associação um-para-vários ?

Exercício

Programação OO com NHibernate

Agenda

Dia 3: Associações no Nhibernate e Herança

Como implementar uma associação vários-para-vários ?

Exercício

Herança

Uma Tabela para cada Classe

Exercício

Uma Tabela para Toda a Herança

Exercício

Programação OO com NHibernate

Agenda

Dia 4: Objetos de Valor

Objetos de Valor e Entidades

Como implementar um objetos de valor

Exercício

Fundamentos de NH

Para que serve ? Automatizar a relação entre dois mundos: As tabelas/visões do banco relacional ( dados )

As classes do mundo dos objetos ( domínio do problema )

NHibernate

Modelo de Objetos Modelo de Dados

class Documento

class PessoaFisica

class Endereco

class TipoDocumento

session .SaveUpdate(p);

session .Remove(p);

selectinsertupdateremove

table Documento

table PessoaFisica

table Endereco

table TipoDocumento

Fundamentos de NH

Para que serve ? Geração Automática de Comandos SQL

TipoDocumento tp = new TipoDocumento();tp.Descricao = “Tipo Doc Qualquer”;

insert into Geral_TipoDocumento( descricao ) values( “Tipo Doc Qualquer” )

tp.Descricao = “Outro Tipo Doc”;update Geral_TipoDocumento tpset tp.descricao = “Outro Tipo Doc”where tp.codTipoDocumento = 12

select tp.codTipoDocumento, tp.descricaofrom Geral_TipoDocumento tpwhere tp.codTipoDocumento = 12

session.SaveOrUpdate(tp);

delete Geral_TipoDocumento where tp.codTipoDocumento = 12

TipoDocumento tp = session .Get<TipoDocumento>(12);

session.SaveOrUpdate(tp);

session.Delete(tp);

Fundamentos de NH

Vantagens POO – Abstrair

complexidade das regras de negócio (Escrever código que parece fácil)

Isso (Programação OO)

PessoaFisica p=new PessoaFisica( nome, new DocumentoCPF(numCPF), new Endereco(numCEP, numEndereco)); session.Save(p);

Ao invés disso (Programação comum)

if (nome == string.Empty){ throw new Exception(“nome vazio”);}if (numCPF == null){ throw new Exception(“cpf não foi informado”);}......... Lógica para validar o CPF..........if (numCEP == null){ throw new Exception(“CEP não informado”);}............. Lógica para validar o CEP ............................ Lógica para trazer endereco pelo CEP..string sql = “insert into Pessoa (nome, cpf, numero, cep, codLogradouro, codBairro, codLocalidade, codEstado, codPais) values (“nome + ”,” + cpf + ”,” + numero + ”,” + cep + ”,” + codLogr.................................SqlCommand sql = new SqlCommand(sql);.......... Continua e nem cabe aqui o código .......

Fundamentos de NH

Vantagens Essa relação não precisa ser 1 classe = 1

tabela havendo um espaço para flexibilidade entre os dois modelos

Modelo de Objetos Modelo de Dados

Pessoa

Pessoa Pessoa

Documento

Taxa

ValorFinanceiro

TabPessoa

TabDocumento

TabDocumento

Fundamentos de NH

Vantagens Permite que o DBA se concentre na melhor

forma de modelar os dados e os Analistas/Programadores se concentrem na melhor forma de representar as entidades e regras do problema a ser modelado

Fundamentos de NH

Vantagens Classes podem ser escritas em C# puro sem

qualquer tipo de implementação específica como herdar de classe específica ou interfacepublic class ImpostoX

{ protected decimal _valor; protected ImpostoX() { } public ImpostoX(decimal valor) { _valor = valor; } public decimal Valor { get { return _valor; } }}

public class ImpostoX{ protected decimal _valor; public ImpostoX() { } public decimal Valor { get { return _valor; } set { _valor = value; } }}

public class ImpostoX{ protected decimal _valor; public ImpostoX() { } public void AtribuirValor (decimal valor) { _valor = valor; } public decimal ObterValor( ) { return _valor; }}

Fundamentos de NH

Vantagens Reuso de código ao invés de copy/paste Garantia de qualidade: testes unitários Legibilidade, manutenibilidade, extensibilidade, etc.

Fundamentos de NH

O que é mapeamento objeto-relacional ? Técnica que consiste em traduzir (criar um tipo

“de .... - para ... “) entre as classes e suas propriedades no modelo-de-objetos e as tabelas/visões e suas colunas no modelo de dados

No NHibernate esse mapeamento é feito através de arquivos no padrão XML ( *.hbm.xml )

A partir desses arquivos, o NHibernate sabe como gerar os SQLs automatizados para as classes

Fundamentos de NH

O que é mapeamento objeto-relacional ?

public class TipoHistorico{

protected TipoHistorico( ) { } public TipoHistorico (string descricao) { _descricao = descricao; } protected long _id; public long Id { get { return _id; } set { _id = value; } } protected string _descricao; public string Descricao { get { return _descricao; } set { _descricao = value; }}

tabela Geral_TipoHistorico

codTipoHistorico int PK

descricao varchar(50)

Fundamentos de NHibernate

Como funciona o mapeamento objeto-relacional no NHibernate ?

TipoDocumento.cs

using System;

namespace ControleCorporativo.ControleGeral.DP{

public class TipoDocumento{

private long _id;public long Id{ get { return _id; } set { _id = value; } }

private string _descricao;public string Descricao{ get { return _descricao; } set { _descricao =

value; } }}

}

Fundamentos de NHibernate

Como funciona o mapeamento objeto-relacional no NHibernate ?

Tabela Geral_TipoDocumento

create table Geral_TipoDocumento(

codTipoDocumento INT primary key,descricao varchar(60)

)

Fundamentos de NHibernate

Como funciona o mapeamento objeto-relacional no NHibernate ?

TipoDocumento.hbm.xml

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

<class name="ControleCorporativo.ControleGeral.DP.TipoDocumento" table="Geral_TipoDocumento">

<id name="Id" column="codTipoDocumento"><generator class="identity"/>

</id>

<property name="Descricao" column="descricao" access="field.camelcase-underscore"/>

</class></hibernate-mapping>

Fundamentos de NHibernate

Como funciona o mapeamento objeto-relacional no NHibernate ?

Configuração: ( necessário na primeira vez )Criando uma classe de configuração para o NHibernate

using System;using NHibernate.Cfg;

namespace SistemaX.Persistencia { public class ConfiguracaoNH { public static Configuration CriarConfiguracao() { Configuration config = new Configuration(); config.Properties["query.substitutions"] = "true 1,false 0"; config.Properties["connection.provider"] = "NHibernate.Connection.DriverConnectionProvider"; config.Properties["dialect"] = "NHibernate.Dialect.MsSql2000Dialect"; config.Properties["connection.driver_class"] = "NHibernate.Driver.SqlClientDriver";config.Properties["connection.connection_string"] = "server=Colibri\\SQL2005;database=bdcurso;user id=usr_aluno;"+ "password=aluno;connect timeout=60"; config.AddAssembly("SistemaX.Dominio"); return config; } }}

Fundamentos de NHibernate

Como funciona o mapeamento objeto-relacional no NHibernate ?

Configuração: ( necessário na primeira vez )Criando um singleton para a ISessionFactory (NHibernateHelper.cs)

using NHibernate;

namespace SistemaX.Persistencia{ public class NHibernateHelper { // A ISessionFactory é unica para toda a aplicação e // é responsável por processar todos os mapeamentos // do NHibernate private static readonly ISessionFactory sessionFactory = ConfiguracaoNH.CriarConfiguracao().BuildSessionFactory();

public static ISessionFactory ObterSessaoFactory() { return sessionFactory; } }}

Fundamentos de NHibernate

Como funciona o mapeamento objeto-relacional no NHibernate ?

Inserindo

// Abre a sessao com o bancoISession sessao = NHibernateHelper.ObterSessaoFactory().OpenSession();

// Cria um tipo de documentoTipoDocumento tp = new TipoDocumento() { Descricao = “Novo Tipo Documento” };

// Inicia TransaçãoITransaction tx = sessao.BeginTransaction();

// Salva o tipo de documentosessao.Save(tp);

// Confirma Transaçãotx.Commit();

// Fecha a sessão com o bancosessao.Close();

Fundamentos de NHibernate

Como funciona o mapeamento objeto-relacional no NHibernate ?

Alterando

// Abre a sessao com o bancoISession sessao = NHibernateHelper.ObterSessaoFactory().OpenSession();

// Cria um tipo de documentoTipoDocumento tp = sessao.Get<TipoDocumento>(10);

// Inicia TransaçãoITransaction tx = sessao.BeginTransaction();

// Salva o tipo de documentosessao.Update(tp);

// Confirma Transaçãotx.Commit();

// Fecha a sessão com o bancosessao.Close();

Fundamentos de NHibernate

Como funciona o mapeamento objeto-relacional no NHibernate ?

Removendo

// Abre uma sessão com o bancoISession session = NHibernateHelper.ObterSessaoFactory().OpenSession();

// Inicia uma transaçãoITransaction transacao = session.BeginTransaction();

// Recupera um tipo de documento com chave = 10TipoDocumento tipoDocumento = session.Get<TipoDocumento>(10);

// Deletando um tipo de documentosession.Delete(tipoDocumento);

// Confirma a transaçãotransacao.Commit();

// Fecha a sessão com o bancosession.Close();

Fundamentos de NHibernate

Como funciona o mapeamento objeto-relacional no NHibernate ?

Consultando (com HQL)

// Abre uma sessão com o bancoISession session = NHibernateHelper.ObterSessaoFactory().OpenSession();

// Executa uma consulta em HQL, resultado como lista de objetosstring strHQL = “from TipoDocumento tp where tp.Descricao like '%CP%'”;IList<TipoDocumento> lstResultado = session.CreateQuery(strHQL)

.List<TipoDocumento>();

string strMensagem = string.Empty;foreach(TipoDocumento tp in lstResultado){

strMensagem += “ Id = “ + tp.Id + “ Desc = “ + tp.Descricao + “\n”;}

MessageBox.Show(strMensagem);

// Fecha a sessão com o bancosession.Close();

Fundamentos de NHibernate

Como funciona o mapeamento objeto-relacional no NHibernate ?

Consultando (com HQL)

// Abre uma sessão com o bancoISession session = NHibernateHelper.ObterSessaoFactory().OpenSession();

// Executa uma consulta em HQL, resultado como lista de objetosIList<TipoDocumento> lstResultado = (from tp in session.Linq<TipoDocumento>()

where tp.Descricao.Contains(“CP”)

select tp).ToList();

string strMensagem = string.Empty;foreach(TipoDocumento tp in lstResultado){

strMensagem += “ Id = “ + tp.Id + “ Desc = “ + tp.Descricao + “\n”;}

MessageBox.Show(strMensagem);

// Fecha a sessão com o bancosession.Close();

Fundamentos de NHibernate

Como funciona o mapeamento objeto-relacional no NHibernate ?

Template de mapeamento<?xml version="1.0" encoding="utf-8" ?><hibernate-mapping xmlns="urn:nhibernate-mapping-2.2 " assembly="[DLL onde está a classe] " namespace="[namespace da classe (using)] ">

<class name="[nome da classe] " table="[nome da tabela] " lazy="true"> <id name="[propriedade de id] " column="[chave primária] " type="[nome do tipo na classe] "> <generator class="[ native | identity | sequence | assigned | outros ] "/> </id>

<property name="[campo1 da classe] " type="[tipo na classe] " column="[coluna1 na tabela] " accessor ="field.camelcase-underscore " /><property name="[campo2 da classe] " type="[tipo na classe] " column="[coluna2 na tabela] " accessor ="field.camelcase-underscore " /><property name="[campo3 da classe] " type="[tipo na classe] " column="[coluna3 na tabela] " accessor ="field.camelcase-underscore " /> : : : : : : : : : : : : <property name="[campoN da classe] " type="[tipo na classe] " column="[colunaN na tabela]"accessor ="field.camelcase-underscore " />

</class>

</hibernate-mapping >

Fundamentos de NHibernate

Exercício Dada a classe Pessoa ( em pseudo código ) e a tabela Pessoa abaixo, criar uma mini-

aplicação web de cadastro utilizando NHibernate.

class Orgao { public long Id {get;set;}; public string Descricao {get;set;}; }

create table Orgao (codOrgao INT primary key, descricao varchar(50) NOT NULL )

Campos da mini aplicação web: Nome:

Id:

Id: Nome:

txtDescr

Incluir

txtDescr

Pesquisar

ListBox

txtId Remover

txtId AlterartxtDescr

Associações no NHibernate

DIA 2

Associações no NHibernate

Convenção para notação de classes em C#.NETTipoDocumento.cs (Completo) TipoDocumento.cs (Simplificado)

using System;namespace ControleCorporativo.ControleGeral.DP{

public class TipoDocumento{

private long _id;public virtual long Id{

get { return _id; }protected set { _id = value; }

}private string _descricao;public string Descricao{

get { return _descricao; }set { _descricao = value; }

}}

}

public class TipoDocumento{

public long Id { get; set; }public string Descricao {get;

set; }}

Associações no NHibernate

Como implementar mapeamento sem associacões ?C#.NET SQL

public class Orgao{ public long Id { get; set; } public string Descricao {get; set;}}

create table Orgao( codOrgao INT primary key, descricao varchar(50))

Orgao.hbm.xml

<?xml version="1.0" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SistemaX.Dominio"> <class name="SistemaX.Dominio.Orgao" table="Orgao">

<id name="Id" column="codOrgao"> <generator class="identity"/> </id>

<property name="Descricao" column="descricao" access="field.camelcase-underscore"/>

</class>

</hibernate-mapping>

Associações no NHibernate

Associação vários-para-um (Associação)

C#.NET SQL

public class Pessoa{

public long Id { get; set; }public string Nome { get; set; }public Orgao Lotacao { get; set; }

}

public class Orgao{

public long Id { get; set; }public string Descricao { get; set; }

}

create table Pessoa(

codPessoa INT primary key,nome varchar(50),codOrgao INT

)

create table Orgao(

codOrgao INT primary key,descricao varchar(50)

)

Associações no NHibernate

Associação vários-para-um (Associação)

<?xml version="1.0" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="[assembly]">

<class name="SistemaX.Dominio.Pessoa" table="Pessoa">

<id name="Id" column="codPessoa"><generator class="identity" />

</id>

<property name="Nome" column="nome" access="field.camelcase-underscore"/>

<many-to-one name=”Lotacao” class="Orgao" column=”codOrgao” access="field.camelcase-underscore"/>

</class></hibernate-mapping>

Pessoa.hbm.xml

Associações no NHibernate

Associação vários-para-um (Associação)

Exemplo de código C# para alteração do Orgão onde uma Pessoa esta lotada:

ISession sessao = NHibernateHelper.ObterSessaoFactory().OpenSession();ITransaction trans = sessao.BeginTransaction();

// Obtem um orgao do banco-de-dadosOrgao orgao = sessao.Get<Orgao>((long)45);

// Cria uma nova pessoaPessoa p = sessao.Get<Pessoa>((long)70);

p.Lotacao = orgao; // Salva a pessoasessao.Save(p);

trans.Commit();sessao.Close();

Associações no NHibernate

Exercício (vários-para-um) (associação) Incluir Pessoa

Nome txtNome Orgao cmbbxOrgao

Alterar Pessoa

Pelo Id txtIdPessoa Nome txtNome Orgao cmbbxOrgao

Remover Pessoa

Pelo Id txtIdPessoa

Incluir

Alterar

Remover

Associações no NHibernate

Associação vários-para-um (composição)C#.NET SQL

public class Pessoa{

public long Id { get; set; }public string Nome { get; set; }private Endereco _endereco =

new Endereco();public Endereco Endereco { get; }

}

public class Endereco{

public long Id { get; set; }public string Localidade { get; set; }

}

create table Pessoa(

codPessoa INT primary key,nome varchar(50),codEndereco INT

)

create table Endereco(

codEndereco INT primary key,

localidade varchar(50))

Associações no NHibernate

Associação vários-para-um (Posse)

<?xml version="1.0" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="[assembly]">

<class name="SistemaX.Dominio.Pessoa" table="Pessoa">..................... outros mapeamentos ..........................

<many-to-one name=”Endereco” class="Endereco" column=”codEndereco” access="field.camelcase-underscore" cascade="all"/>

</class></hibernate-mapping>

Pessoa.hbm.xml

Endereco.hbm.xml

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

<class name="SistemaX.Dominio.Endereco" table="Endereco">

<id name="Id" column="codEndereco"> <generator class="identity"/> </id>

<property name="Localidade" column="localidade" access="field.camelcase-underscore"/>

</class></hibernate-mapping>

Associações no NHibernate

Associação vários-para-um (Posse)ISession sessao = NHibernateHelper.ObterSessaoFactory().OpenSession();ITransaction trans = sessao.BeginTransaction();

Exemplo de código C# para inclusão de Pessoa com Endereco:

// Cria uma nova pessoa com EnderecoPessoa p = new Pessoa( ) p.Nome=”Nova Pessoa”;p.Endereco.Localidade = “Anchieta”;sessao.Save(p);

Exemplo de código C# de alteração de endereço de uma Pessoa existente no banco:

// Alterando a localidade de uma pessoa grvada em bancoPessoa p2 = sessao.Get<Pessoa>((long)70);p2.Endereco.Localidade = “Outra Localidade”;sessao.Update(p);

trans.Commit();sessao.Close();

Associações no NHibernate

Exercício (associação vários-para-um) Incluir Pessoa

Id da Pessoa txtIdPessoa Nome txtNome Localidade txtLocalidade

Alterar Pessoa

Id da Pessoa txtIdPessoa Nome txtNome Localidade txtLocalidade

Remover Pessoa

Id da Pessoa txtIdPessoa

Incluir

Alterar

Remover

Associações no NHibernate

Associação um-para-vários C#.NET

SQLpublic class Pessoa{ public long Id { get; set; } public string Nome { get; set; } private IList<Documento> _documentos = new List<Documento>(); public IList<Documento> Documentos { get; }}

public class Documento{ public long Id { get; set; } public string Numero { get; set; } public Pessoa Pessoa { get; }}

create table Pessoa( codPessoa INT primary key, nome varchar(50))

create table Pessoa_Documento( codDocumento INT primary key, numero varchar(50), codPessoa int)

Associações no NHibernate Associação um-para-vários

Documento.hbm.xml<?xml version="1.0" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="[DLL]" namespace="[namespace]">

<class name="DocumentoPessoa" table="Pessoa_DocumentoPessoa" lazy="true"><id name="Id" column="codDocumentoPessoa" type="Int64">

<generator class="identity" /></id><property name="numero" column="numero" type="string" access="field.camelcase-underscore"/>

<many-to-one name="relPessoa" class="Pessoa" column="codPessoa" access="field.ca..." not-null="true"/> </class>

</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?><hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SistemaX.Dominio"> <class name="SistemaX.Dominio.Pessoa" table="Pessoa">

: : : outros mapeamentos : : : : : <bag name="Documentos" access="field.camelcase-underscore" cascade="all-delete-orphan" inverse="true"> <key column="codPessoa"/> <one-to-many class="SistemaX.Dominio.Documento"/> </bag>

</class></hibernate-mapping>

Pessoa.hbm.xml

Associações no NHibernate

Associação um-para-vários

Exemplo de código C# para inclusão de Documento em Pessoa Existente no Banco

ISession sessao = NHibernateHelper.ObterSessaoFactory().OpenSession();ITransaction trans = sessao.BeginTransaction(); // Obtem uma pessoa do banco-de-dadosPessoa p = sessao.Get<Pessoa>((long)44); // Adiciona um documento na PessoaDocumento d = new Documento() { Numero = “00009900” , Pessoa = p };p.Documentos.Add(d); // Altera o primeiro documento da Pessoap.Documentos[0].Numero = “000900”;// Remove o terceiro documento da Pessoap.Documentos.Remove( p.Documentos[2] );

// Salva a pessoa e todas alterações nos documentos de uma só vezsessao.Update(p);

trans.Commit();sessao.Close();

Associações no NHibernate

Exercício (associação um-para-vários) Incluir Documento

Id da Pessoa txtIdPessoa Desc. Doc. txtDescrDocumento

Alterar Documento

Id da Pessoa txtIdPessoa Id do Doc. txtIdDoc Desc.doc. txtDescrDocumento

Remover Documento

Id da Pessoa txtIdPessoa Id do Doc. txtIdDoc

Incluir

Alterar

Remover

Associações no NHibernate

Dia4

Associações no NHibernate

Associação vários-para-vários

C#.NET SQLpublic class Pessoa{ public long Id { get; set; } public string Nome { get; set; }}

public class Tarefa{ public long Id { get; set; } public string Descricao {get; set;} public IList<Pessoa> Pessoas {get; set;}}

create table Pessoa( codPessoa INT primary key, nome varchar(50) )

create table PessoaTarefa( codPessoa INT, codTarefa INT)

create table Tarefa( codDocumento INT primary key, descricao varchar(50), codPessoa INT)

Associações no NHibernate Associação vários-para-vários

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

<class name="SistemaX.Dominio.Tarefa" table="Tarefa" lazy="true">

<id name="Id" column="codTarefa"> <generator class="identity"/> </id>

<property name="Descricao" column="descricao" access="field.camelcase-underscore"/>

<bag name="Pessoas" table="Pessoa_Tarefa" access="field.camelcase-underscore" lazy="true" inverse = "false" cascade="all"> <key column="codTarefa"/> <many-to-many class="SistemaX.Dominio.Pessoa" column="codPessoa"/> </bag>

</class>

</hibernate-mapping>

Tarefa.hbm.xml

Associações no NHibernate

Exercício (associação Vários-para-vários) Incluir Tarefa

Nome txtDescricao

Alterar Tarefa

Pelo Id txtIdTarefa Descricao txtDescricao

Remover Tarefa

Pelo Id txtIdTarefa

Incluir Pessoa na Tarefa

Tarefa txtIdTarefa Pessoa txtIdPessoa

Remover Pessoa da Tarefa

Tarefa txtIdTarefa Pessoa txtIdPessoa

Incluir

Alterar

Remover

Incluir

Remover

Associações no NHibernate Template de mapeamento: (Resumo)

Template de classe

using System;namespace AlgumNamespace{

public class AlgumaClasse {

private long _id;public virtual long Id { get { return this._id; } protected set { this._id = value; } }

protected tipo _campo; public virtual tipo Campo

{ get { return this._campo; } set { this._campo = value; } }

protected OutraClasse _associacao; public virtual OutraClasse Associacao

{ get { return this._associacao; } set { this._associacao = value; } }

protected IList<MaisOutraClasse> _associacaoLista; public virtual IList<MaisOutraClasse> AssociacaoLista

{ get { return this._associacaoLista; } set { this._associacaoLista = value; } } } }

Associações no NHibernate Template de mapeamento: (Resumo)

Template de mapeamento<?xml version="1.0" encoding="utf-8" ?><hibernate-mapping xmlns="urn:nhibernate-mapping-2.2 " assembly="[DLL da classe] " namespace="[namespace] "> <class name="[nome da classe] " table="[nome da tabela] " lazy="true"> <id name="[propriedade de id] " column="[chave primária] " type="[tipo na classe] "> <generator class="[ native | identity | sequence | assigned | outros ] "/> </id>

<property name="[campo da classe] " type="[tipo do campo] " column="[coluna na tabela] " accessor="field.camelcase-underscore " />

<many-to-one name="[assoc. da classe] " class="[tipo da assoc.] " column="[chaveFK] " cascade="[none | all | save-update] " access="field.camelcase-underscore" />

<bag name="[lista na classe] " lazy="true" cascade="[ all-delete-orphan | save-update | none ] " inverse="true" access="field.camelcase-underscore"> <key column="[chave FK na tabela filho] "/>

<one-to-many class="[tipo de cada elemento na lista1] "/> </bag>

<bag name="[lista da classe] " table="[tabela agregada da associac.] " lazy="true" access="field.camelcase-underscore" cascade="[ all-delete-orphan | save-update | none ] ">

<key column="[chave FK para a tabela filho] "/><many-to-many class="[tipo de cada elemento na listaN+1] " column="[chave FK para a tabela pai] "/>

</bag>

</class></hibernate-mapping >

HerançaEstrutura em árvore composta por uma classe pai (genérica) e as classes filhas (específicas)Herança de classe pode ter várias formas no Modelo de DadosUma tabela para toda a hierarquia de classesUma tabela por classeUma tabela cada cada classe concreta

Herança Uma tabela para toda a hierarquia Modelo de Classe Modelo de Dados

create table Pessoa( codPessoa INT primary key, nome varchar(50), sexo char, objetoSocial varchar(50), tipoPessoa char)

public abstract class Pessoa{ public long Id { get; set; } public string Nome { get; set; }}

public class PessoaFisica : Pessoa{ public char Sexo { get; set; }}

public class Pessoa Juridica : Pessoa{ public string ObjetoSocial { get; set; }}

Herança Uma tabela para toda a hierarquia

Pessoa.hbm.xml<?xml version="1.0" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SistemaX.Dominio">

<class name="SistemaX.Dominio.Pessoa" table="Pessoa" lazy="true"><id name="Id" column="codPessoa" type="Int64">

<generator class="identity" /></id><discriminator column=”tipoPessoa” type=”char”/><property name="Nome" column="nome" type="string" access="field.camelcase-underscore"/>

</class></hibernate-mapping>

PessoaFisica.hbm.xml<?xml version="1.0" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SistemaX.Dominio" namespace="SistemaX.Dominio">

<subclass name=”PessoaFisica” discriminator-value=”f” extends="Pessoa"><property name=”CPF” column=”cpf” access="field.camelcase-underscore"/>

</subclass></hibernate-mapping>

PessoaJuridica.hbm.xml<?xml version="1.0" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SistemaX.Dominio" namespace="SistemaX.Dominio">

<subclass name=”PessoaJuridica” discriminator-value=”j” extends="Pessoa"><property name=”CNPJ” column=”cnpj” access="field.camelcase-underscore"/>

</subclass></hibernate-mapping>

Herança Uma tabela por classe Modelo de Classe Modelo de Dados

create table Pessoa( codPessoa INT primary key, nome varchar(50), )

create table PessoaFisica( codPessoa INT primary key, sexo char(50),)

create table PessoaJuridica( codPessoa INT primary key, objetoSocial varchar(50),)

public abstract class Pessoa{ public long Id { get; set; } public string Nome { get; set; }}

public class PessoaFisica : Pessoa{ public char Sexo { get; set; }}

public class Pessoa Juridica : Pessoa{ public string ObjetoSocial { get; set; }}

Herança Uma tabela por classe

Pessoa.hbm.xml<?xml version="1.0" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SistemaX.Dominio" >

<class name="SistemaX.Dominio.Pessoa" table="Pessoa" lazy="true"><id name="Id" column="codPessoa" type="Int64">

<generator class="identity" /></id><property name="Nome" column="nome" type="string" access="field.camelcase-

underscore"/></class>

</hibernate-mapping>

PessoaFisica.hbm.xml<?xml version="1.0" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SistemaX.Dominio" namespace="SistemaX.Dominio">

<joined-subclass name=”PessoaFisica” table=”PessoaJuridica” lazy="true" extends="Pessoa"><key column=”codPessoa”/><property name=”Sexo” column=”sexo” access="field.camelcase-underscore"/>

</joined-subclass></hibernate-mapping>

PessoaJuridica.hbm.xml<?xml version="1.0" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SistemaX.Dominio" namespace="SistemaX.Dominio">

<joined-subclass name=”PessoaJuridica” table=”PessoaJuridica” lazy="true" extends="Pessoa"><key column=”codPessoa”/><property name=”ObjetoSocial” column=”objetoSocial” access="field.camelcase-underscore"/>

</joined-subclass></hibernate-mapping>

HerançaExercício (Herança -> 1 tabela para a hierarquia )Escrever um mapeamento NHibernate para a herança de documentos abaixo:

Fazer uma tela web de consultar objetos via HQL:

txtHQL btExecutar

listBoxResultado

public class Documento{

public long Id { get; set; }public string Numero { get; set; }

}public class DocumentoCI : Documento{

public string Estado { get; set; }}public class DocumentoCNH : Documento{

public string Categoria { get; set; }}

create table Documento(

codDocumento INT primary key,

numero varchar(50),estado varchar(50),categoria varchar(50),tipoDocumento varchar(50)

)

HerançaExercício (Herança ->1 tabela por classe)

Utiliar a mesma tela web de consulta para verificar os mapeamentos

txtHQL btExecutar

listBoxResultado

public abstract class Pessoa{

public long Id { get; set; }...

}public class PessoaFisica : Pessoa{

public string Sexo { get; set; }}public class PessoaJuridica : Pessoa{

public string ObjetoSocial { get; set; }}

create table Pessoa(

codPessoa INT primary key,...

)create table PessoaFisica(

codDocumento INT,sexo varchar(50)

)create table PessoaJuridica(

codDocumento INT,objetoSocial varchar(50)

)

Objetos de Valor

Dia4

Objetos de Valor e Entidades

Entidade: Toda classe cujo objeto precisa de um Id para identif.

Normalmente esta mapeada para 1 ou mais tabelas

Ex: Pessoa, Logradouro, InscricaoCadastral

Objeto de Valor:

Também é classe mas não possui Id de identificação

Representa um conceito importante do negócio

É imutável, não pode ser alterado, apenas subtituído

Ex: Dinheiro (valor + unid. Ref.), Endereco (alguns casos)

Objetos de Valor e Entidades Exemplo:

Modelo de Dados Modelo de Classes

create table Taxa( codTaxa INT primary key, descricao varchar(50), codUnidadeReferencia INT, valorTaxa numeric(12,4))

create table UnidadeReferencia( codUnidadeReferencia INT primary key, descricao varchar(50))

public class Taxa{

public long Id { get; set; }public string Descricao { get; set; }public UnidadeReferencia

UnidadeReferencia { get; set; } public decimal ValorTaxa { get; set; }}

public class UnidadeReferencia{

public long Id { get; set; }public string Descricao { get; set; }

}

Objetos de Valor e Entidades Exemplo: (Funciona, mas vamos pensar melhor ... )

Modelo de Dados Modelo de Classes

create table Taxa( codTaxa INT primary key, descricao varchar(50), codUnidadeReferencia INT, valorTaxa numeric(12,4))

create table UnidadeReferencia( codUnidadeReferencia INT primary key, descricao varchar(50))

public class Taxa{

public long Id { get; set; }public string Descricao { get; set; }public UnidadeReferencia

UnidadeReferencia { get; set; } public decimal ValorTaxa { get; set; }}

public class UnidadeReferencia{

public long Id { get; set; }public string Descricao { get; set; }

}

Objetos de Valor e Entidades Exemplo: (Vamos pensar melhor ... )

Modelo de Dados Modelo de Classes

create table Taxa( codTaxa INT primary key, descricao varchar(50), codUnidadeReferencia INT, valorTaxa numeric(12,4))

create table UnidadeReferencia( codUnidadeReferencia INT primary key, descricao varchar(50))

Essas duas colunas aparecem juntasem várias tabelas sugerindo um conceito importante de valor financeiro.

Objetos de Valor e Entidades Exemplo: ( Incluir conceito de negócio )

Modelo de Dados Modelo de Classescreate table Taxa( codTaxa INT primary key, descricao varchar(50), codUnidadeReferencia INT, valorTaxa numeric(12,4))

create table UnidadeReferencia( codUnidadeReferencia INT primary key, descricao varchar(50))

public class Taxa{

public long Id { get; set; }public string Descricao { get; set; }public ValorFinanc Valor { get; set; }

}public class ValorFinanc{ public ValorFinanc (UnidadeReferencia uf, decimal v) public UnidadeReferencia { get; } public decimal Valor { get; } public ValorFinanc static Adicionar( ValorFinanc fator1, ValorFinanc fator2, UnidadeReferencia result); public ValorFinanc static Subtr( ValorFinanc subtraendo, ValorFinanc subtrator, UnidadeReferencia result); public ValorFinanc Conversao(UnidadeReferencia result);}public class UnidadeReferencia{

public long Id { get; set; }public string Descricao { get; set; }

}

Objetos de Valor e Entidades Exemplo: ( Incluir conceito de negócio )

Mapeamento da classe Taxa<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="[DLL]" namespace="[namespace]">

<class name="Taxa" table="Taxa" lazy="true">

<id name="Id" column="codTaxa" type="Int64"><generator class="identity"/>

</id>

<property name=“Descricao" type="String" column="descricao" not-null="true" accessor="field.camelcase-underscore" />

<component name=“Valor” class=“ValorFinanc”><property name=“Valor” type=“String” column=“valorTaxa”/><many-to-one name=“UnidadeReferencia”

class=“UnidadeReferencia” column=“codUnidadeReferencia”/>

</component>

</class></hibernate-mapping>

Exercício

class PessoaEspecial{

public long Id { get; set; }public long Nome { get; set; }public EnderecoEspecial Endereco{ get; }

}

class EnderecoEspecial{

public string Localidade { get; set; }public string Numero { get; set; }

}

create table PessoaEspecial(

codPessoaEspecial INT primary key,

nome varchar(50),localidade varchar(50),numero varchar(50)

)

Mapear a classe PessoaEspecial

Testar a inclusão e a consulta de uma pessoa especial em C#

ObservaçõesProjeto Fluent Nhibernate permite escrever mapeamentos em C#

1. <?xml version="1.0" encoding="utf-8" ?> 2. <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 3. namespace="QuickStart" assembly="QuickStart"> 4. 5. <class name="Cat" table="Cat"> 6. <id name="Id"> 7. <generator class="identity" /> 8. </id> 9. 10. <property name="Name"> 11. <column name="Name" length="16" not-null="true" /> 12. </property> 13. <property name="Sex" /> 14. <many-to-one name="Mate" /> 15. <bag name="Kittens"> 16. <key column="mother_id"/> 17. <one-to-many class="Cat"/> 18. </bag> 19. </class> 20. </hibernate-mapping>

1. public class CatMap : ClassMap<Cat> 2. { 3. public CatMap() 4. { 5. Id(x => x.Id); 6. Map(x => x.Name) 7. .WithLengthOf(16) 8. .Not.Nullable(); 9. Map(x => x.Sex); 10. References(x => x.Mate); 11. HasMany(x => x.Kittens); 12. } 13. }

Observações

Consultas em Linq-to-NHibernate

Recursos geo-espaciais (MsSQLSpatial, PostGIS)

IList<TipoDocumento> lstResultado = (from tp in session.Linq<TipoDocumento>() where tp.Descricao.Contains(“CP”) select tp).ToList();

// Encontra um país localizado em uma coordenadaCountry country = session.CreateCriteria(typeof(Country)) .Add(SpatialExpression.Contains("Boundaries", new Point(-70.40, -33.24))) .UniqueResult() as Country;

// Encontra as cidades de uma área exceto aquelas localizadas em algumas coords.Town[] towns = Town.FindAll( SpatialExpression.Filter("Boundaries", new Envelope(-70, -68, -32, -34)), Expression.Not(SpatialExpression.Contains("Boundaries", new Point(-70.40, -33.24))));

Observações

Vantagens só aparecem com Programação OO

Pessoa p = new Pessoa(strNome,new DocumentoCPF(strCPF),new Endereco(strCEP));

session.SaveOrUpdate(p);

if ((strNome == null)||(strNome == string.Empty)){ .....Erro ... }if ((strCPF == null)||(strCPF == string.Empty)){ ... Erro ... }if ((strCEP == null)||(strCEP == string.Empty)){ ... Erro ... }IList<Pessoa> lstPessoas = ... consulta para achar ... outra pessoa com ... mesmo nome e CPFif (lstPessoas.Count > 0) { ..... Erro ......... }CEP cep = ... consulta de CEP pelo numeroif (cep == null ) { ........ Erro ....... }Localidade localidade = cep.Localidade;Pessoa p = new Pessoa( );p.Nome = strNome;p.Documentos.Add(new DocumentoCPF(strCPF));p.Endereco.Localidade = localidade;session.SaveOrUpdate(p);

Isso Ao invés disso

Perguntas

Contacte o autor, se preferir ...●http://www.linkedin.com/in/hcmarchezi●http://hcmarchezi.blogspot.com.br/