Upload
ricardo-peres
View
67
Download
2
Embed Size (px)
Citation preview
Ricardo Peres
Introdução ao NHibernate
DEV308
Critical Software
weblogs.asp.net/ricardoperes
Copyright (c) Ricardo Peres 2010
Introdução ao NHibernate como ferramenta de O/RM alternativa
Principais capacidadesComparativo com outros O/RMsProjectos relacionadosQ&As a qualquer altura
Agenda
Copyright (c) Ricardo Peres 2010
Introdução ao NHibernate
O que é o NHibernate? Um O/RM carrega dados de tabelas de bases de
dados para objectos .NET e vice-versa Com o NHibernate, focamos-nos nas classes, não na
base de dados – até pode ser gerada para nós Construído pela comunidade, inspirado pelo Java
Hibernate O que o NHibernate não é?
Uma framework de desenvolvimento genérica Um API de regras de negócio Uma ferramenta de ETL ou inserções em massa
Copyright (c) Ricardo Peres 2010
Independente da base de dados As tabelas são geradas e actualizadas a partir das classes Não requer classes ou interfaces base (POCO) Suporta uma abordagem Domain-Driven Design Lazy loading de entidades associadas, colecções e
propriedades Detecção automática de alterações nas entidades SQL ou stored procedures podem ser usados em todas as
operações Múltiplos geradores de chaves primárias Muitas opções para controlo de concorrência API extensível Open source Baseado em Design Patterns
Principais Funcionalidades
Copyright (c) Ricardo Peres 2010
O/RM
Aplicação
BD
O/RMNegócioApresentação
Copyright (c) Ricardo Peres 2010
Domain-Driven Design: An approach to developing software for complex
needs by deeply connecting the implementation to an evolving model of the core business concepts
OR/M:A programming technique for converting data
between incompatible type systems in relational databases and object-oriented programming languages
Wikipedia
Patterns (1 de 5)
Copyright (c) Ricardo Peres 2010
Active Record: An object that wraps a row in a database table or view, encapsulates the
database access, and adds domain logic on that data Association Table Mapping:
Saves an association as a table with foreign keys to the tables that are linked by the association
Class Table Inheritance: Represents an inheritance hierarchy of classes with one table for each class
Concrete Table Inheritance: Represents an inheritance hierarchy of classes with one table per concrete
class in the hierarchy Data Mapper:
A layer of Mappers that moves data between objects and a database while keeping them independent of each other and the mapper itself
Dependent Mapping: Has one class perform the database mapping for a child class
Martin Fowler, Patterns of Enterprise Application Integration
Patterns (2 de 5)
Copyright (c) Ricardo Peres 2010
Domain Model: An object model of the domain that incorporates both behavior and data
Embedded Value: Maps an object into several fields of another object's table
Foreign Key Mapping: Maps an association between objects to a foreign key reference between
tables Identity Field:
Saves a database ID field in an object to maintain identity between an in-memory object and a database row
Identity Map: Ensures that each object gets loaded only once by keeping every loaded
object in a map. Looks up objects using the map when referring to them Inheritance Mappers:
A structure to organize database mappers that handle inheritance hierarchies
Martin Fowler, Patterns of Enterprise Application Integration
Patterns (3 de 5)
Copyright (c) Ricardo Peres 2010
Lazy Load: An object that doesn't contain all of the data you need but knows how to get
it Metadata Mapping:
Holds details of object-relational mapping in metadata Mapper:
An object that sets up a communication between two independent objects Optimistic Offline Lock:
Prevents conflicts between concurrent business transactions by detecting a conflict and rolling back the transaction
Pessimistic Offline Lock: Prevents conflicts between concurrent business transactions by allowing
only one business transaction at a time to access data Query Object:
An object that represents a database query
Martin Fowler, Patterns of Enterprise Application Integration
Patterns (4 de 5)
Copyright (c) Ricardo Peres 2010
Single Table Inheritance: Represents an inheritance hierarchy of classes as a single table that has
columns for all the fields of the various classes Unit of Work:
Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems
Value Object: A small simple object, like money or a date range, whose equality isn't
based on identity
Martin Fowler, Patterns of Enterprise Application Integration
Patterns (5 de 5)
Copyright (c) Ricardo Peres 2010
DB2 Ingres PostgreSQL 7+ MySQL 3+ Oracle 8+ Sybase Adaptive Server Enterprise Sybase Adaptive Server Anywhere SQL Server 7+ (including Azure) Firebird SQLLite Ingres 3+ Azure Genérica (SQL 99) Bases de dados personalizadas
Bases de Dados Suportadas
Copyright (c) Ricardo Peres 2010
Ficheiros HBM.XML Classes são POCO, sem referências ao NHibernate Podem ou não ser incluídos como embedded resources
Atributos São aplicados atributos nas classes e propriedades
Fluent NHibernate Classes são POCO, sem referências ao NHibernate API fluente
As entidades não são tabelas e as propriedades não são colunas!
O NHibernate constroi o modelo em memória e pode gerar os scripts DDL de criação
Descrição do Modelo
Copyright (c) Ricardo Peres 2010
O NHibernate suporta uma abordagem model-first (primeiro as classes, depois a BD)
Nesta abordagem, a persistência é apenas um aspecto, o modelo é simplesmente POCO, sem preocupações de como os dados vão ser persistidos
Alguns conceitos são: entidades (com chave) e valores (sem chave), agregados e associações
Domain-Driven Design
Copyright (c) Ricardo Peres 2010
Table per Class Hierarchy (discriminator + subclass) Uma tabela contém todas as colunas para todas as sub-classes Classes diferentes são distinguidas por uma coluna discriminatória
Table per Subclass (joined-subclass) Uma tabela para cada classe mãe e uma para cada sub-classe A tabela para a classe mãe contém as colunas partilhadas
Table per Concrete Class (union-subclass) Uma tabela para cada classe concreta Cada tabela contém todas as colunas de todas as sub-classes As chaves nunca podem ser iguais
Misto (join)
Mapeamento de Heranças
Copyright (c) Ricardo Peres 2010
DemoMapeamento de Heranças
Copyright (c) Ricardo Peres 2010
One to One Uma entidade em cada
extremo One to Many / Many to
One Colecção num extremo,
entidade no outro Many to Many
Colecção em ambos os extremos
Any / Many to Any Não é preciso uma classe base,
apenas uma propriedade conhecida
Ternary Muitos para um ou um para
muitos ou muitos para muitos onde o indexador é uma entidade
Property Array Primitive Array Bag
Não ordenado com repetição Id Bag
Identificador por relação List
Lista ordenada com uma coluna indexadora de tipo inteiro
Set Sem repetição de elementos
Map Elementos ordenados indexados
por uma coluna de qualquer tipo, incluindo entidades
Associações
Geradores de Chaves
Gerador Propósito
Increment Independente da BD
Identity SQL Server, MySQL, DB2, Sybase
Sequence Oracle, PostgreSQL, DB2, Firebird
Hi / Lo Independente da BD, precisa de uma tabela especial
Sequence Hi / Lo Precisa de uma tabela especial
Native Identity, Sequence or Hi / Lo, dependendo da BD
UUID String GUID, independente da BD
GUID GUID, independente da BD
GUID Comb GUID, independente da BD
Assigned Independente da BD
Foreign Entidade um para um relacionada é a chave
Copyright (c) Ricardo Peres 2010
Estratégias de Carregamento
Join fetching É usado um JOIN para obter as
entidades associadas
Select fetching É usado um segundo SELECT
para obter as entidades seleccionadas
Subselect fetching É usado um segundo SELECT
para obter as entidades seleccionadas
Lazy collection fetching A colecção é carregada como um
todo quando é acedida
Extra-lazy collection fetching Cada um dos elementos de uma
colecção é carregado da BD quando acedido
Proxy fetching Uma entidade associada é
carregada quando uma das suas propriedades não chave é acedida
Lazy properties Uma propriedade individual é
carregada quando acedida (para CLOBs ou BLOBs)
Copyright (c) Ricardo Peres 2010
Session Factories
As session factories (ISessionFactory) são criadas por objectos Configuration (um por aplicação)
As sessões são criadas por session factories
Tipicamente apenas uma session factory é necessária, mas podem ser criadas várias, a apontar para BDs diferentes
As session factories são pesadas, contêm todo o modelo
Thread-safe
Copyright (c) Ricardo Peres 2010
Sessões
Todo o acesso à BD é feito através de sessões (pattern Unit of Work)
Dois tipos de sessões:Normal (ISession)Stateless (IStatelessSession):
Não suporta lazy loading Não reconhece as alterações Não levanta eventos Não usa a cache
As conexões à BD apenas são abertas quando necessário
São leves e não thread-safe Todas as operações são feitas numa sessão As entidades carregadas por uma sessão estão presas
a ela, mas podem ser desligadas e ligadas a outra
Copyright (c) Ricardo Peres 2010
Get / Load: carregar uma entidade / proxy Refresh: refrescar uma entidade Save / Update / SaveOrUpdate: guardar uma entidade SaveOrUpdateCopy: igual a SaveOrUpdate, mas
funciona com entidades não persistidas Merge: copia o estado de uma entidade não persistida
para uma entidade persistida com o mesmo id Persist: torna uma entidade persistente Delete: apagar uma entidade Replicate: guardar uma entidade numa nova BD Lock / Unlock: bloquear / desbloquear uma entidade Evict / Clear: remover uma entidade / todas as entidades
da cache de primeiro nível
Operações da Sessão
Copyright (c) Ricardo Peres 2010
DemoSession Factories e Sessões
Copyright (c) Ricardo Peres 2010
ID Por chave primária
HQL Independente da BD, similar a SQL
mas object-oriented Criteria API
Usa objectos para representar as condições de filtragem, projecções, ordenamento, joins, etc (Query Object pattern)
Por Exemplo Dado uma entidade exemplo com
alguns valores nas suas propriedades, procura entidades similares
Query Over Idêntico ao Criteria API mas usando
expressões LINQ
Named Queries Queries pré-compiladas, HQL ou
SQL LINQ
Querying fortemente tipado SQL
SQL NHibernate Search
Integração com Lucene.NET
Querying (1 de 4)
Copyright (c) Ricardo Peres 2010
Querying (2 de 4)
LINQ to NHibernatevar cats = from a in
session.Query<Cat> where a.Id = 1 select a;
HQLvar cats =
session.CreateQuery<Cat>(“from Cat c where id(c) = 1”).List<Cat>();
var cats = new DetachedQuery(“from Cat c where id© = 1”).GetExecutableQuery(session).List<Cat>();Criteria API
var cats = session.CreateCriteria<Cat>(). Add(Restrictions.IdEq(1)).List<Cat>()
var cats = DetachedCriteria.For<Cat>().Add(Restrictions.IdEq(1)).GetExecutableCriteria(session).List<Cat>();
Query Overvar cats =
QueryOver.Of<Cat>().Where(a => a.Id == 1).GetExecutableQueryOver(session).List<Cat>();
Copyright (c) Ricardo Peres 2010
Querying (3 de 4)
Por ExemploCat example = new Cat {Name =
“Felix”};var cats =
session.CreateCriteria<Cat>().Add(Example.Create(example)).List<Cat>();
By Idvar cat = session.Get<Cat>(1);var catProxy =
session.Load<Cat>(1);
Named Queries SQLvar cats =
session.CreateSQLQuery(“SELECT * FROM cat WHERE id = 1”).List<Cat>();
var cats = session.GetNamedQuery(“GetCats").SetParameter(“name", “Felix”).List<Cat>();
Querying (4 de 4)
NHibernate Searchvar cats =
searchSession.CreateFullTextQuery<Cat>(“Id:1").List<Cat>();
Multi Criteria / Multi Query / Futuresvar cats = session.CreateMultiQuery().Add<Cat>(“from Cat c where c.Name = ‘Felix’”).Add<Cat>(“from Cat c where c.Name = ‘Tom’”).List();
var cats = session.CreateMultiCriteria().Add<Cat>(Restrictions.Eq(“Name”, “Felix”)).Add<Cat>(Restrictions.Eq(“Name”, “Tom”)).List();
var futureCats = session.CreateQuery(“from Cat c where c.Name = ‘Felix’”).Future<Cat>();
var futureCats = session.CreateCriteria<Cat>(Restrictions.Eq(“Name”, “Felix”)).Future<Cat>();
Copyright (c) Ricardo Peres 2010
É possível deferir a execução de uma query para um momento posterior
Podem ser chamadas tanto queries que devolvem listas como um único elemento: Future<T> e FutureValue<T>
As queries futuras são todas enviadas em bloco
Suportadas em SQL Server, SQL Server CE, MySQL, PostgreSQL e SQLLite
Valores Futuros
Copyright (c) Ricardo Peres 2010
Podem ser especificados filtros para entidades e colecções
Um filtro pode estar activado (inicialmente estão desactivados) ou não e ter um ou mais valores (filtro composto)
Um filtro tem um tipo associadoEspecificados nos ficheiros de mapeamento
Filtros
Copyright (c) Ricardo Peres 2010
DemoQuerying
Copyright (c) Ricardo Peres 2010
Alterar Dados (1 de 2)
As alterações em entidades são detectadas automaticamente, o NHibernate sabe quando um objecto mudou (snapshot)
O NHibernate também sabe se um objecto veio da BD ou não
Podem ser usados stored procedures para todas as operações DML e para carregar entidades (loader, sql-insert, sql-update, sql-delete, sql-query, sql-delete-all)
Podem ser especificadas regras de cascata para todas as colecções associadas (all, none, save-update, all-delete-orphan)
Pode ser usado HQL para todas as operações DML (INSERT, UPDATE, DELETE)
Copyright (c) Ricardo Peres 2010
Alterar Dados (2 de 2)
Todas as operações DML são suportadas (UPDATE, DELETE, INSERT)
Pode ser especificado o batch-size para aplicação em bloco
Podem ser gerado SQL apenas para as colunas modificadas (dynamic-update)
As alterações são aplicadas (flushed) em determinados momentos
O flushing é configurável por sessão:No commit (FlushMode.Commit)Automaticamente (FlushMode.Auto)Em todas as queries (FlushMode.Always)Nunca (FlushMode.Never)
Copyright (c) Ricardo Peres 2010
Controlo de Concorrência
Várias estratégias de controlo de concorrência:Pessimista: lock de registos ou tabela, específico da
BDOptimista:
Versão: numérico, data e hora, ROWVERSION (SQL Server)
Todos/Sujos: todos os campos ou apenas os modificadosPropriedades individuais podem ser configuradas para
entrar no controlo de concorrência Uma transacção deve ser sempre criada Um ou mais registos podem ser
explicitamente bloqueados (Lock) É lançada uma excepção no caso de uma
violação de concorrência
Interceptors e Listeners
Interceptors recebem notificações quando certos eventos ocorrem
Cancelar uma operação (delete, update, insert) é possível pelo retorno de um valor de veto
Apenas um interceptor por sessão
Listeners recebem notificações quando certos eventos ocorreram ou vão ocorrer
Apenas é possível cancelar lançando uma excepção
O NHibernate Validator depende de listeners
Interceptors (IInterceptor) e listeners (IxxxListener) podem ser aplicados ao nível da session factory ou da sessão
Outra opção consiste em implementar as interfaces IValidator e ILifecycle
Um listener pode ser registado em código ou no ficheiro .config
Eventos Interceptor
AfterTransactionBegin AfterTransactionCompleti
on BeforeTransactionCompl
etion OnCollectionRecreate OnCollectionRemove OnCollectionUpdate OnDelete
OnFlushDirty OnLoad OnPrepareStatement OnSave PostFlush PreFlush
Eventos Listener
Auto-Flush Create Create-OnFlush Delete Dirty-Check Evict Flush Flush-Entity Load Load-Collection Lock Merge Pre-Update Post-Load Post-Insert Post-Update Post-Delete
Post-Commit-Delete Post-Commit-Insert Post-Commit-Update Pre-Load Pre-Delete Pre-Insert Pre-Collection-Recreate Pre-Collection-Remove Pre-Collection-Update Post-Collection-Recreate Post-Collection-Remove Post-Collection-Update Refresh Replicate Save Save-Update Update
Copyright (c) Ricardo Peres 2010
DemoInterceptors e Listeners
Copyright (c) Ricardo Peres 2010
Tipos Personalizados
É possível definir carregadores para tipos personalizaos (tipos simples, IUserType, tipos compostos, ICompositeUserType), com os quais o NHibernate não sabe lidar (imagens, por exemplo)
Em tipos compostos até é possível fazer queries pelas propriedades declaradas nos tipos personalizados
Copyright (c) Ricardo Peres 2010
DemoTipos Personalizados
Copyright (c) Ricardo Peres 2010
Cache de Primeiro Nível
Associada à sessãoAs sessões stateless não usam CPNPode ser desactivado em sessões
normaisAs entidades carregadas são colocadas
na CPN, e posteriormente são sempre daí obtidas (excepto quando forem refrescadas)
Uma implementação do pattern Identity Map
Cache de Segundo Nível
Associada à session factory Activada entidade a entidade Aplica-se tanto a entidades como a queries Vários fornecedores disponíveis (NHContrib):
Fornecedor Descrição
SysCache Uses System.Web.Caching.Cache as the cache provider
SysCache 2 Similar to NHibernate.Caches.SysCache, uses ASP.NET cache plus SQL dependencies
Prevalence uses Bamboo.Prevalence as the cache provider, a .NET implementation of the object prevalence concept brought to life by Klaus Wuestefeld in Prevayler
MemCache Uses memcached, a high-performance, distributed memory object caching system, generic in nature, but intended for use in speeding up dynamic web applications by alleviating database load. Basically a distributed hash table
Velocity Uses Microsoft Velocity which is a highly scalable in-memory application cache for all kinds of data
SharedCache High-performance, distributed and replicated memory object caching system
Projectos Relacionados
Projecto Descrição
NHibernate Attributes (NHContrib) Mapeamento por atributos
NHibernate Search (NHContrib) Integração com Lucene.NET
NHibernate Validator (NHContrib) Validação de estado
NHibernate Burrow (NHContrib) Conversações e persistência entre pedidos em aplicações web
NHibernate Caches (NHContrib) Fornecedores de cache de 2º nível
NHibernate Proxy Generators (NHContrib)
Pré-geração de classes proxy
NHibernate Spatial (NHContrib) Suporte para tipos de dados geo-referenciados (SQL Server, PostgreSQL)
NHibernate Shards (NHContrib) Particionamento horizontal de BDs
NHibernate User Types (NHContrib) Tipos de dados específicos do Oracle e SQL Server
NHibernate Tasks (HBM to .NET, HBM to DDL) (NHContrib)
Geração de classes .NET a partir dos mapeamentos HBM.XML
Outros O/RMs
Microsoft Microsoft LINQ to SQL
Gratuito POCOs Apenas SQL Server Physical mapping to tables, not a conceptual
model Apenas BD primeiro Apenas suporta a estratégia table per class
hierarchy Microsoft Entity Framework
Gratuito Por agora, apenas SQL Server, Oracle e
MySQL são possíveis POCOs e não POCOs Modelo conceptual Código primeiro ou BD primeiro Todas as estratégias de mapeamento de
heranças são suportadas
Non-Microsoft Castle ActiveRecord
Open Source Baseado no NHibernate Faz algumas assumpções sobre o modelo Não POCOs Todas as estratégias de mapeamento de
heranças são suportadas SubSonic
Gratuito POCOs e não POCOs SQL Server, Oracle, MySQL, PostgreSQL,
Vista DB, SQL Server CE e SQL Lite Apenas BD primeiro Apenas suporta a estratégia table per class
hierarchy LLBLGen Pro
Comercial Múltiplas BDs suportadas Não POCOs Apenas BD primeiro Apenas suporta a estratégia table per class
hierarchy
Copyright (c) Ricardo Peres 2010
Uma framework O/RM maturaAltamente extensívelVasta comunidade de utilizadoresProjectos relacionados muito interessantesCapaz de ombrear com outros produtos
O/RM estabelecidos
Conclusão
Copyright (c) Ricardo Peres 2010
Referências
Ayende @ Rahien Bamboo.Prevalence Catalog of Patterns of Enterprise Application Architecture First and Second Level Caching in NHibernate Fluent NHibernate NHibernate Forge HunabKu Memcached NHibernate Contrib NHibernate Mapping - Inheritance NHibernate Users Mailing List uNhAddins Using NHibernate With Stored Procedures Velocity (AppServer Fabric Caching)
Copyright (c) Ricardo Peres 2010
Ricardo [email protected]://weblogs.asp.net/ricardopereshttp://pontonetpt.com/blogs/ricardoperes
Contactos
Copyright (c) Ricardo Peres 2010
Q & A
Copyright (c) Ricardo Peres 2010
A sua opinião é importante!Complete o questionário de avaliação e devolva-o à saida.
A sua opinião é importante!Complete o questionário de avaliação e devolva-o à saida.
Copyright (c) Ricardo Peres 2010
Copyright (c) Ricardo Peres 2010