SlideShare a Scribd company logo
1 of 172
Download to read offline
HibernateEFETIVO
ERROSCOMUNSESOLUÇÕES
RafaelPonte
IA-2014
Eu estava me
perguntando quando de
fato o Hibernate foi
criado...
Eu estava me
perguntando quando de
fato o Hibernate foi
criado...
Luca Bastos
O “Boom” foi em 2003!
Mais de uma década!
2014 - 2003 = 11
mas ainda hoje...
mas ainda hoje...
existem devs que
subutilizam o framework
mas ainda hoje...
existem devs que
subutilizam o framework
problemas de perfomance
e escalabilidade
e pra piorar...
culpam o Hibernate
culpam o Hibernate
A culpa é do Banco de
Dados!
Sérgio
é fácil culpar o que não se
conhece...
um SGDB mal configurado
pode ser o problema...
um SGDB mal configurado
pode ser o problema...
MAS na maioria das vezes o
problema está na SUA
APLICAÇÃO
tabelas sem índices
<3
tabelas sem índices
consultas mal-feitas
<3 <3
tabelas sem índices
consultas mal-feitas
<3 <3 <3
muitos hits ao banco
tabelas sem índices
consultas mal-feitas
muitos hits ao banco
connection leaks
<3 <3 <3
tabelas sem índices
consultas mal-feitas
muitos hits ao banco
connection leaks
<3 <3 <3
memory leaks
Não saber tirar
proveito framework!
Hibernate Efetivo
6 dicas para não deixar
sua app morrer
@rponte
Fortaleza - Terra do Sol
#1
POOL DE
CONEXÕES
com certeza todos aqui
já ouviram falar...
mas nem todos dão a devida atenção...
mas nem todos dão a devida atenção...	

até perceberem a app engasgando
mas nem todos dão a devida atenção...	

até perceberem a app engasgando	

ou até receberem um
mas nem todos dão a devida atenção...	

até perceberem a app engasgando	

ou até receberem um	

org.hibernate.exception.Gener
icJDBCException: Cannot
open connection
daí percebem que não configuraram o
o pool do Hibernate	



hibernate.connection.driver_class=org.postgresql.Driver	
  
hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect	
  
hibernate.connection.url=jdbc:postgresql://localhost:5432/myapp	
  
hibernate.connection.username=postgres	
  
hibernate.connection.password=1234	
  
!
!
!
hibernate.properties
daí percebem que não configuraram o
o pool do Hibernate	



hibernate.connection.driver_class=org.postgresql.Driver	
  
hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect	
  
hibernate.connection.url=jdbc:postgresql://localhost:5432/myapp	
  
hibernate.connection.username=postgres	
  
hibernate.connection.password=1234

hibernate.connection.pool_size=30	
  
!
!
hibernate.properties
daí percebem que não configuraram o
o pool do Hibernate	



hibernate.connection.driver_class=org.postgresql.Driver	
  
hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect	
  
hibernate.connection.url=jdbc:postgresql://localhost:5432/myapp	
  
hibernate.connection.username=postgres	
  
hibernate.connection.password=1234

hibernate.connection.pool_size=30	
  
!
!
hibernate.properties
a app volta a funcionar
bem por um tempo
a app volta a funcionar
bem por um tempo
e vão alocando mais conexões com o
tempo	



hibernate.connection.pool_size=30	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  40	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  55	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  70

	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ...	
  
hibernate.properties
o pool PADRÃO do
Hibernate
que possui uma impl.
RUDIMENTAR
INFO DriverManagerConnectionProvider:64 - Using Hibernate built-in
connection pool (not for production use!)!
INFO DriverManagerConnectionProvider:65 - Hibernate connection pool
size: 20!
INFO DriverManagerConnectionProvider:64 - Using Hibernate built-in
connection pool (not for production use!)!
INFO DriverManagerConnectionProvider:65 - Hibernate connection pool
size: 20!
notforproductionuse!
qual pool utilizar?
temos ótimas opções...
pools como c3p0 ou
commons-dbcp
temos ótimas opções...
o Hibernate já vem
com c3p0
configurando c3p0	



hibernate.connection.driver_class=org.postgresql.Driver	
  
hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect	
  
hibernate.connection.url=jdbc:postgresql://localhost:5432/myapp	
  
hibernate.connection.username=postgres	
  
hibernate.connection.password=1234	
  
hibernate.c3p0.min_size=5	
  
hibernate.c3p0.max_size=20	
  
hibernate.c3p0.timeout=1800	
  
hibernate.c3p0.max_statements=50	
  
hibernate.properties
ou melhor ainda...
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">!
! <!-- access configuration -->!
! <property name="driverClass" value="${jdbc.driverclass}" />!
! <property name="jdbcUrl" value="${jdbc.url}" />!
! <property name="user" value="${jdbc.username}" />!
! <property name="password" value="${jdbc.password}" />!
! <!-- pool sizing -->!
! <property name="initialPoolSize" value="3" />!
! <property name="minPoolSize" value="6" />!
! <property name="maxPoolSize" value="25" />!
! <property name="acquireIncrement" value="3" />!
! <property name="maxStatements" value="0" />!
! <!-- retries -->!
! <property name="acquireRetryAttempts" value="30" />!
! <property name="acquireRetryDelay" value="1000" /> <!-- 1s -->!
! <property name="breakAfterAcquireFailure" value="false" />!
! <!-- refreshing connections -->!
! <property name="maxIdleTime" value="180" /> <!-- 3min -->!
! <property name="maxConnectionAge" value="10" /> <!-- 1h -->!
! <!-- timeouts e testing -->!
! <property name="checkoutTimeout" value="5000" /> <!-- 5s -->!
! <property name="idleConnectionTestPeriod" value="60" /> <!-- 60 -->!
! <property name="testConnectionOnCheckout" value="true" />!
! <property name="preferredTestQuery" value="SELECT 1+1" />!
</bean>!
podemos obter as conexões de um DataSource
Pool traz melhoria de
performance
Pool traz melhoria de
performance
mas não faz milagres
#2
lidando com
LazyInitialization
Exception
quando e por que acontece?
@Entity	
  
class	
  NotaFiscal	
  {	
  
	
  	
  …	
  
	
  	
  @OneToMany	
  
	
  	
  List<Item>	
  itens;	
  
}
NotaFiscal	
  nf	
  =	
  (NotaFiscal)	
  
session.load(NotaFiscal.class,	
  42);	
  
!
List<Item>	
  itens	
  =	
  nf.getItens();	
  
Percorrendo os itens de uma nota
select nf.* from NotaFiscal nf
where nf.id=42
select i.* from Item i
where i.nota_fiscal_id=42
Hibernate executa 2 selects	

NotaFiscal	
  nf	
  =	
  (NotaFiscal)	
  session.load(NotaFiscal.class,	
  42);
List<Item>	
  itens	
  =	
  nf.getItens();
Session	
  session	
  =	
  
sessionFactory.openSession();	
  
!
NotaFiscal	
  nf	
  =	
  (NotaFiscal)	
  
session.load(NotaFiscal.class,	
  42);	
  


session.close();	
  
!
List<Item>	
  itens	
  =	
  nf.getItens();

System.out.println("numero	
  de	
  pedidos:"	
  +	
  
itens.size());	
  
a session do Hibernate foi fechada
Session	
  session	
  =	
  
sessionFactory.openSession();	
  
!
NotaFiscal	
  nf	
  =	
  (NotaFiscal)	
  
session.load(NotaFiscal.


session.close();	
  
!
List<Item>	
  itens	
  =	
  nf.getItens();
System.out.println(
itens.size());
mas ao ler os itens da nota	

org.hibernate.LazyInitializationException:
failed to lazily initialize a collection -

no session or session was closed.
resolver parece fácil, certo?
Session	
  session	
  =	
  
sessionFactory.openSession();	
  
!
NotaFiscal	
  nf	
  =	
  (NotaFiscal)	
  
session.load(NotaFiscal.class,	
  42);	
  
!
List<Item>	
  itens	
  =	
  nf.getItens();

System.out.println("numero	
  de	
  pedidos:"	
  +	
  
itens.size());



session.close();	
  
!
fechar a session ao término do trabalho
Mas e quando estamos
trabalhando na Web?
@Get("/notas/{id}")	
  
public	
  void	
  view(Long	
  id)	
  {

	
  	
  NotaFiscal	
  nf	
  =	
  notaFiscalDao.carrega(id);	
  
	
  	
  result.include("nf",	
  nf);

	
  	
  result.forwardTo("/notas/view.jsp");	
  
}	
  
view.jsp
NotaFiscalController.java
<c:forEach	
  var="item"	
  items="${nf.itens}">	
  
	
  	
  	
  	
  ${item.produto.descricao}<br/>	
  
</c:forEach>
@Get("/notas/{id}")	
  
public	
  void	
  view(Long	
  id)	
  {

	
  	
  NotaFiscal	
  nf	
  =	
  notaFiscalDao.carrega(id);	
  
	
  	
  result.include("nf",	
  nf);

	
  	
  result.forwardTo("/notas/view.jsp");	
  
}	
  
view.jsp
NotaFiscalController.java
<c:forEach	
  var="item"	
  items="${nf.itens}">	
  
	
  	
  	
  	
  ${item.produto.descricao}<br/>	
  
</c:forEach>
sessionfoifechada!
@Get("/notas/{id}")	
  
public	
  void	
  view(Long	
  id)	
  {

	
  	
  NotaFiscal	
  nf	
  =	
  notaFiscalDao.carrega(id);	
  
	
  	
  result.include("nf",	
  nf);

	
  	
  result.forwardTo("/notas/view.jsp");	
  
}	
  
view.jsp
NotaFiscalController.java
<c:forEach	
  var="item"	
  items="${nf.itens}">	
  
	
  	
  	
  	
  ${item.produto.descricao}<br/>	
  
</c:forEach>
LazyInitializationException
e agora? #comofas
e agora? #comofas
Sérgio
passa tudo pra
EAGER! ;D
@Entity	
  
class	
  NotaFiscal	
  {	
  
	
  	
  …	
  
	
  	
  @OneToMany(fetch=FetchType.EAGER)	
  
	
  	
  List<Item>	
  itens;	
  
}
select nf.*, i.* from NotaFiscal
nf left outer join Item i on
nf.id = i.nota_fiscal_id

where nf.id=42
Hibernate executa 1 select	

NotaFiscal	
  nf	
  =	
  (NotaFiscal)	
  session.load(NotaFiscal.class,	
  42);
mas isso poderia gerar
uma sobrecarga...
mas isso poderia gerar
uma sobrecarga...
pois os itens da nota
não são necessários em
muitos lugares
lembre-se que ter os
relacionamentos como LAZY é
uma boa prática
como evitar LIE sem
modificar o relacionamento
para EAGER?
Open Session In
View
@WebFilter(urlPatterns="/*")	
  
public	
  class	
  OpenSessionInViewFilter	
  implements	
  Filter	
  {	
  
!
	
   SessionFactory	
  sessionFactory;	
  
	
   	
  
	
   @Override	
  
	
   public	
  void	
  doFilter(ServletRequest	
  req,	
  ServletResponse	
  res,	
  
FilterChain	
  chain)	
  {	
  
	
   	
   Transaction	
  transaction	
  =	
  null;	
  
	
   	
   try	
  {	
  
	
   	
   	
   Session	
  session	
  =	
  sessionFactory.getCurrentSession();	
  
	
   	
   	
   transaction	
  =	
  session.beginTransaction();	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  	
  chain.doFilter(req,	
  res);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  	
  transaction.commit();	
  
	
   	
   }	
  finally	
  {	
  
	
   	
   	
   if	
  (transaction	
  !=	
  null	
  &&	
  transaction.isActive())	
  {	
  
	
   	
   	
   	
   transaction.rollback();	
  
	
   	
   	
   }	
  
	
   	
   	
   session.close();	
  
	
   	
   }	
  
	
   }	
  
}
Servlet Filter
o OSIV só evita LIE no
mesmo request!
anti-pattern?
#3
Second Level
Cache
NotaFiscal	
  nf	
  =	
  (NotaFiscal)	
  
session.load(NotaFiscal.class,	
  42);
Carregando uma nota por ID
Banco de Dados
Session
Banco de Dados
Session
FirstLevelCache
Banco de Dados
Session Session Session Session
Banco de Dados
????
Session Session Session Session
Banco de Dados
Second Level Cache
Session Session Session Session
Banco de Dados
Second Level Cache
Session Session Session
FirstLevelCache
Session
Banco de Dados
SessionFactory
Session Session Session Session
Configurar é simples
#1 configuramos o Hibernate


hibernate.cache.use_second_level_cache=true	
  
hibernate.cache.region.factory_class=net.sf.ehcac
he.hibernate.EhCacheRegionFactory	
  
hibernate.properties
@Entity	
  
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)	
  
class	
  Bug	
  {	
  
	
  @Id	
  
	
  	
  private	
  Long	
  id;	
  
	
  private	
  String	
  descricao;	
  
private	
  String	
  status;	
  
	
  @ManyToOne	
  
private	
  Projeto	
  projeto;	
  
	
  	
  @OneToMany	
  
	
  	
  private	
  List<Comentario>	
  comentarios;	
  
}
#2 configuramos as entidades
@Cache(	
  
usage=CacheConcurrencyStrategy.READ_WRITE)
Caching Strategy	

READ_ONLY
NONSTRICT_READ_WRITE
READ_WRITE
@Cache(	
  
usage=CacheConcurrencyStrategy.READ_WRITE)
Caching Strategy	

READ_ONLY
NONSTRICT_READ_WRITE
READ_WRITE
Melhor performance
@Cache(	
  
usage=CacheConcurrencyStrategy.READ_WRITE)
Caching Strategy	

READ_ONLY
NONSTRICT_READ_WRITE
READ_WRITE
Dados não críticos
@Cache(	
  
usage=CacheConcurrencyStrategy.READ_WRITE)
Caching Strategy	

READ_ONLY
NONSTRICT_READ_WRITE
READ_WRITE Modificações frequentes
<cache	
  
	
  	
  	
  	
  name="br.com.triadworks.model.Bug"	
  
	
  	
  	
  	
  maxElementsInMemory="10000"	
  
	
  	
  	
  	
  eternal="false"	
  
	
  	
  	
  	
  timeToIdleSeconds="1800"	
  
	
  	
  	
  	
  timeToLiveSeconds="10000"	
  
	
  	
  	
  	
  overflowToDisk="true"	
  
	
  	
  	
  	
  memoryStoreEvictionPolicy="LRU"	
  
/>
ehcache.xml
Como 2nd Level Cache
funciona?
2nd Level Cache não faz cache
das instancias das entidades
2nd Level Cache não faz cache
das instancias das entidades
somente dos valores
das propriedades
@Entity	
  
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)	
  
class	
  Bug	
  {	
  
	
  @Id	
  
	
  	
  private	
  Long	
  id;	
  
	
  private	
  String	
  descricao;	
  
private	
  String	
  status;	
  
	
  @ManyToOne	
  
private	
  Projeto	
  projeto;	
  
	
  	
  @OneToMany	
  
	
  	
  private	
  List<Comentario>	
  comentarios;	
  
}
modelo conceitual do cache 	

Bug Data Cache
17 -> [ “Bug #1”, “ABERTA” , 1 ]!
18 -> [ “Bug #2”, “FECHADA”, 2 ]!
19 -> [ “Bug #3”, “ABERTA” , 1 ]
modelo conceitual do cache 	

Bug Data Cache
17 -> [ “Bug #1”, “ABERTA” , 1 ]!
18 -> [ “Bug #2”, “FECHADA”, 2 ]!
19 -> [ “Bug #3”, “ABERTA” , 1 ]
id descricao status
id do
projeto
modelo conceitual do cache 	

Bug Data Cache
17 -> [ “Bug #1”, “ABERTA” , 1 ]!
18 -> [ “Bug #2”, “FECHADA”, 2 ]!
19 -> [ “Bug #3”, “ABERTA” , 1 ]
não é uma árvore de objetos,
mas sim um Map de Arrays
2nd Level Cache não faz cache
das associações
@Entity	
  
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)	
  
class	
  Bug	
  {	
  
	
  @Id	
  
	
  	
  private	
  Long	
  id;	
  
	
  private	
  String	
  descricao;	
  
private	
  String	
  status;	
  
	
  @ManyToOne	
  
private	
  Projeto	
  projeto;	
  
	
  	
  @OneToMany	
  
	
  	
  @Cache(usage=CacheConcurrencyStrategy.READ_WRITE)	
  
	
  	
  private	
  List<Comentario>	
  comentarios;	
  
}
modelo conceitual do cache 	

Bug Data Cache
17 -> [ “Bug #1”, “ABERTA” , 1, [1,2] ]!
18 -> [ “Bug #2”, “FECHADA”, 2, [] ]!
19 -> [ “Bug #3”, “ABERTA” , 1, [3] ]
modelo conceitual do cache 	

Bug Data Cache
17 -> [ “Bug #1”, “ABERTA” , 1, [1,2] ]!
18 -> [ “Bug #2”, “FECHADA”, 2, [] ]!
19 -> [ “Bug #3”, “ABERTA” , 1, [3] ]
ids dos
comentarios
E o que o Hibernate faz com
todos estes IDs?
E o que o Hibernate faz com
todos estes IDs?
vai no banco de
novo! a não ser que
você…
@Entity	
  
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)	
  
class	
  Projeto	
  {	
  
	
  	
  ...	
  
}	
  
!
!
@Entity	
  
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY)	
  
class	
  Comentario	
  {	
  
	
  ...	
  
}
configure o cache das entidades
Devo cachear todas as
minhas entidades?
Com 2nd Level Cache tudo funciona bem
enquanto buscamos por ID...
session.load(Bug.class,	
  17);
Com 2nd Level Cache tudo funciona bem
enquanto buscamos por ID...
...mas e quando precisamos de uma
consulta um pouco diferente?
session.load(Bug.class,	
  17);
session

	
  	
  .createQuery("from	
  Bug	
  where	
  status	
  =	
  ?")	
  
	
  	
  .setString(0,"ABERTO")

	
  	
  .list();	
  
#4
Query Cache
Query Cache faz cache do
resultado de uma query
Configurando Hibernate para
usar Query Cache


hibernate.cache.use_query_cache=true	
  
hibernate.properties
Query Cache	

session

	
  	
  .createQuery("from	
  Bug	
  where	
  status	
  =	
  ?")	
  
	
  	
  .setString(0,	
  status)

	
  	
  .setCacheable(true)

	
  	
  .list();	
  
modelo conceitual do query cache 	

Query Cache
[“from Bug where status = ?”, [“ABERTO”]] -> [17, 19]
modelo conceitual do query cache 	

Query Cache
[“from Bug where status = ?”, [“ABERTO”]] -> [17, 19]
Query + Parâmetros IDs
por isso Query Cache SEM
2nd Level Cache não é de
muita ajuda
Utilize somente em consultas
que são executadas repetidas
vezes com os mesmos
parâmetros
Utilize somente em consultas
que são executadas repetidas
vezes com os mesmos
parâmetros
#5
Select n+1
o campeão em prejudicar
a performance da
aplicação
NotaFiscal	
  nf	
  =	
  (NotaFiscal)	
  
session.load(NotaFiscal.class,	
  42);	
  


processaItensDaNota(nf);	
  
Processando os itens de uma nota
select nf.* from NotaFiscal nf
where nf.id=42
select i.* from Item i
where i.nota_fiscal_id=42
Hibernate executa 2 selects	

NotaFiscal	
  nf	
  =	
  (NotaFiscal)	
  session.load(NotaFiscal.class,	
  42);
processaItensDaNota(nf);
List<NotaFiscal>	
  notas	
  =	
  dao.listaTudo();	
  
for	
  (NotaFiscal	
  nf	
  :	
  notas)	
  {	
  
	
  	
  	
  	
  processaItensDaNota(nf);	
  
}	
  
Processando os itens de varias notas
select nf.* from NotaFiscal nf
select i.* from Item i where i.nota_fiscal_id=?	
select i.* from Item i where i.nota_fiscal_id=?	
select i.* from Item i where i.nota_fiscal_id=?	
select i.* from Item i where i.nota_fiscal_id=?	
select i.* from Item i where i.nota_fiscal_id=?	
...
Hibernate executa n+1 selects	

List<NotaFiscal>	
  notas	
  =	
  dao.listaTudo();
for	
  (NotaFiscal	
  nf	
  :	
  notas)	
  {	
  
	
  	
  	
  	
  processaItensDaNota(nf);	
  
}
são muitos hits no banco de
dados
são muitos hits no banco de
dados
mas podemos resolver
isso...
3 soluções
#1 EAGER ou join-
fetch
@Entity	
  
class	
  NotaFiscal	
  {	
  
	
  	
  …	
  
	
  	
  @OneToMany(fetch=FetchType.EAGER)	
  
	
  	
  List<Item>	
  itens;	
  
}
Utilizando FetchMode=EAGER
select nf.*, i.* from NotaFiscal
nf left outer join Item i on
nf.id = i.nota_fiscal_id

Hibernate executa 1 select	

List<NotaFiscal>	
  notas	
  =	
  dao.listaTudo();
antes de definir um
mapeamento global deste
tipo você precisa se
perguntar...
SEMPRE que uma nota é
necessária, todos seus
itens também são
necessários?
não?
session

	
  	
  .createQuery("from	
  NotaFiscal	
  n	
  
left	
  join	
  fetch	
  n.itens")

	
  	
  .list();	
  
Utilizando Join Fetch
#2 batch-size nas
associações
É o meio termo entre
EAGER e LAZY
@Entity	
  
class	
  NotaFiscal	
  {	
  
	
  	
  …	
  
	
  	
  @OneToMany	
  
	
  	
  @BatchSize(size=10)	
  
	
  	
  List<Item>	
  itens;	
  
}
@BatchSize
select nf.* from NotaFiscal nf
select i.* from Item i where i.nota_fiscal_id
in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)	
select i.* from Item i where i.nota_fiscal_id
in (?, ?, ?, ?, ?)
Hibernate executa n/10+1 selects	

List<NotaFiscal>	
  notas	
  =	
  dao.listaTudo();
for	
  (NotaFiscal	
  nf	
  :	
  notas)	
  {	
  
	
  	
  	
  	
  processaItensDaNota(nf);	
  
}
@BatchSize também é
conhecido como:
@BatchSize também é
conhecido como:
otimização de adivinhação cega

(blind-guess optimization)
@BatchSize também é
conhecido como:
otimização de adivinhação cega

(blind-guess optimization)
ou seja, é um palpite
#3 FetchMode
SUBSELECT
@Entity	
  
class	
  NotaFiscal	
  {	
  
	
  	
  …	
  
	
  	
  @OneToMany	
  
	
  	
  @Fetch(FetchMode.SUBSELECT)	
  
	
  	
  List<Item>	
  itens;	
  
}
SUBSELECT
select nf.* from NotaFiscal nf
select i.* from Item i where
i.nota_fiscal_id in (select nf.id from
NotaFiscal nf)	
Hibernate executa 2 selects	

List<NotaFiscal>	
  notas	
  =	
  dao.listaTudo();
for	
  (NotaFiscal	
  nf	
  :	
  notas)	
  {	
  
	
  	
  	
  	
  processaItensDaNota(nf);	
  
}
Qual utilizar?
Qual utilizar?
depende
#6
Processamento
em lote
Imagine que temos que
importar 100k produtos para
o banco de dados
Session	
  session	
  =	
  sf.openSession();	
  
Transaction	
  tx	
  =	
  session.beginTransaction();	
  
	
   	
   	
  
for	
  (	
  int	
  i=0;	
  i	
  <	
  100000;	
  i++	
  )	
  {	
  
	
   Produto	
  produto	
  =	
  new	
  Produto(...);	
  
	
   session.save(produto);	
  
}	
  
	
   	
   	
  
tx.commit();	
  
session.close();
em ~50k produtos nós
receberíamos um
OutOfMemoryException
por que?
Hibernate faz cache de todas
as instâncias dos Produtos
inseridos na Session
mas como melhorar?
!
!
!
Session	
  session	
  =	
  sf.openSession();	
  
Transaction	
  tx	
  =	
  session.beginTransaction();	
  
	
   	
   	
  
for	
  (	
  int	
  i=0;	
  i	
  <	
  100000;	
  i++	
  )	
  {	
  
	
   Produto	
  produto	
  =	
  new	
  Produto(...);	
  
	
   session.save(produto);	
  
	
  	
  if	
  (i	
  %	
  100	
  ==	
  0)	
  {	
  
	
  	
  	
  	
  session.flush();	
  
	
  	
  	
  	
  session.clear();	
  
	
  	
  }	
  
}	
  
	
   	
   	
  
tx.commit();	
  
session.close();
evitamos o OutOfMemoryException
evitamos o OutOfMemoryException
Mas o processamento ainda
continua lento!
evitamos o OutOfMemoryException
Mas o processamento ainda
continua lento!
Dá pra melhorar?
JDBC puro?
JDBC puro?
código de maxu!
Handerson Frota
StatelessSession
StatelessSession
sem 1st Level Cache
sem 2nd Level Cache
sem dirty-checking
sem cascade
Collections são ignorados
sem modelo de
eventos
sem interceptors
próxima ao jdbc
API mais baixo nível
mapeamento básico
!StatelessSession	
  session	
  =	
  
sf.openStatelessSession();	
  
Transaction	
  tx	
  =	
  session.beginTransaction();	
  
	
   	
   	
  
for	
  (	
  int	
  i=0;	
  i	
  <	
  100000;	
  i++	
  )	
  {	
  
	
   Produto	
  produto	
  =	
  new	
  Produto(...);	
  
	
   session.insert(produto);	
  
}	
  
	
   	
   	
  
tx.commit();	
  
session.close();
menos consumo de memória
e mais rápida!
menos consumo de memória
e mais rápida!
Yuri Adams
dá pra melhorar?


hibernate.jdbc.batch_size=50	
  
hibernate.properties
CONCLUSÃO
Foi apenas a ponta o iceberg!
cada uma destas dicas são simples,
mas requerem mais estudo
cada uma destas dicas são simples,
mas requerem mais estudo
pois depende do projeto
um DBA certamente pode te
ajudar em muitos cenários
Hibernate não é seu inimigo,
deixem de #mimimi
Rafael Ponte
rponte@triadworks.com.br

More Related Content

What's hot

Evento Front End SP - Arquitetura de Front
Evento Front End SP - Arquitetura de FrontEvento Front End SP - Arquitetura de Front
Evento Front End SP - Arquitetura de FrontMichel Ribeiro
 
Desenvolvimento de jogos com HTML5 e javascript
Desenvolvimento de jogos com HTML5 e javascriptDesenvolvimento de jogos com HTML5 e javascript
Desenvolvimento de jogos com HTML5 e javascriptWillian Molinari
 
Zabbix Conference LatAm 2019 - Automação: Ganhando produtividade
Zabbix Conference LatAm 2019 - Automação: Ganhando produtividadeZabbix Conference LatAm 2019 - Automação: Ganhando produtividade
Zabbix Conference LatAm 2019 - Automação: Ganhando produtividadeIgor Nicoli
 
Javascript no SAPO e libsapojs
Javascript no SAPO e libsapojsJavascript no SAPO e libsapojs
Javascript no SAPO e libsapojscodebits
 
Dicas para Interfaces Performáticas no seu App Android
Dicas para Interfaces Performáticas no seu App AndroidDicas para Interfaces Performáticas no seu App Android
Dicas para Interfaces Performáticas no seu App AndroidUbiratan Soares
 
Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017 Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017 Luis Gustavo Almeida
 
JS Experience 2017 - Web APIs que você provavelmente não sabia que existiam
JS Experience 2017 - Web APIs que você provavelmente não sabia que existiamJS Experience 2017 - Web APIs que você provavelmente não sabia que existiam
JS Experience 2017 - Web APIs que você provavelmente não sabia que existiamiMasters
 
JS Experience 2017 - Javascript Funcional
JS Experience 2017 - Javascript FuncionalJS Experience 2017 - Javascript Funcional
JS Experience 2017 - Javascript FuncionaliMasters
 
Curso de WebServlets (Java EE 7)
Curso de WebServlets (Java EE 7)Curso de WebServlets (Java EE 7)
Curso de WebServlets (Java EE 7)Helder da Rocha
 
Node.js - #7 - Core Modules - http - Parte 1 - Rodrigo Branas
Node.js - #7 - Core Modules - http - Parte 1 - Rodrigo BranasNode.js - #7 - Core Modules - http - Parte 1 - Rodrigo Branas
Node.js - #7 - Core Modules - http - Parte 1 - Rodrigo BranasRodrigo Branas
 

What's hot (18)

Evento Front End SP - Arquitetura de Front
Evento Front End SP - Arquitetura de FrontEvento Front End SP - Arquitetura de Front
Evento Front End SP - Arquitetura de Front
 
Dependency injection
Dependency injectionDependency injection
Dependency injection
 
JavaScript Hacks
JavaScript HacksJavaScript Hacks
JavaScript Hacks
 
Acessando o MySql com o Python
Acessando o MySql com o PythonAcessando o MySql com o Python
Acessando o MySql com o Python
 
Introdução ao Apache Ant
Introdução ao Apache AntIntrodução ao Apache Ant
Introdução ao Apache Ant
 
Desenvolvimento de jogos com HTML5 e javascript
Desenvolvimento de jogos com HTML5 e javascriptDesenvolvimento de jogos com HTML5 e javascript
Desenvolvimento de jogos com HTML5 e javascript
 
Zabbix Conference LatAm 2019 - Automação: Ganhando produtividade
Zabbix Conference LatAm 2019 - Automação: Ganhando produtividadeZabbix Conference LatAm 2019 - Automação: Ganhando produtividade
Zabbix Conference LatAm 2019 - Automação: Ganhando produtividade
 
Javascript no SAPO e libsapojs
Javascript no SAPO e libsapojsJavascript no SAPO e libsapojs
Javascript no SAPO e libsapojs
 
Dicas para Interfaces Performáticas no seu App Android
Dicas para Interfaces Performáticas no seu App AndroidDicas para Interfaces Performáticas no seu App Android
Dicas para Interfaces Performáticas no seu App Android
 
Doctrine2 Seminário PHP
Doctrine2 Seminário PHPDoctrine2 Seminário PHP
Doctrine2 Seminário PHP
 
Java www
Java wwwJava www
Java www
 
Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017 Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017
 
Java 08
Java 08Java 08
Java 08
 
JS Experience 2017 - Web APIs que você provavelmente não sabia que existiam
JS Experience 2017 - Web APIs que você provavelmente não sabia que existiamJS Experience 2017 - Web APIs que você provavelmente não sabia que existiam
JS Experience 2017 - Web APIs que você provavelmente não sabia que existiam
 
JS Experience 2017 - Javascript Funcional
JS Experience 2017 - Javascript FuncionalJS Experience 2017 - Javascript Funcional
JS Experience 2017 - Javascript Funcional
 
Curso de WebServlets (Java EE 7)
Curso de WebServlets (Java EE 7)Curso de WebServlets (Java EE 7)
Curso de WebServlets (Java EE 7)
 
Node.js - #7 - Core Modules - http - Parte 1 - Rodrigo Branas
Node.js - #7 - Core Modules - http - Parte 1 - Rodrigo BranasNode.js - #7 - Core Modules - http - Parte 1 - Rodrigo Branas
Node.js - #7 - Core Modules - http - Parte 1 - Rodrigo Branas
 
Java script aula 07 - j-query
Java script   aula 07 - j-queryJava script   aula 07 - j-query
Java script aula 07 - j-query
 

Similar to HibernateEFETIVOERROSCOMUNSESOLUÇÕES

LambdaDay: Backbone.js
LambdaDay: Backbone.jsLambdaDay: Backbone.js
LambdaDay: Backbone.jsGiovanni Bassi
 
JasperReports Tecnicas de geracao_de_relatorios1
JasperReports  Tecnicas de geracao_de_relatorios1JasperReports  Tecnicas de geracao_de_relatorios1
JasperReports Tecnicas de geracao_de_relatorios1Sliedesharessbarbosa
 
Dicas para Turbinar o servidor de Aplicações JBoss 7
Dicas para Turbinar o servidor de Aplicações JBoss 7Dicas para Turbinar o servidor de Aplicações JBoss 7
Dicas para Turbinar o servidor de Aplicações JBoss 7Claudio Miranda
 
Backbone.js nas trincheiras
Backbone.js nas trincheirasBackbone.js nas trincheiras
Backbone.js nas trincheirasLambda 3
 
Redis um banco chave valor
Redis um banco chave valorRedis um banco chave valor
Redis um banco chave valorKinn Julião
 
Livropythonmysql 091022073751-phpapp01
Livropythonmysql 091022073751-phpapp01Livropythonmysql 091022073751-phpapp01
Livropythonmysql 091022073751-phpapp01julianabdpaiva
 
Offline Web com Service Workers - Sérgio Lopes
Offline Web com Service Workers - Sérgio LopesOffline Web com Service Workers - Sérgio Lopes
Offline Web com Service Workers - Sérgio LopesCaelum
 
Como Perder Peso (no browser)
Como Perder Peso (no browser)Como Perder Peso (no browser)
Como Perder Peso (no browser)Zeno Rocha
 
Mongo Db - PHP Day Workshop
Mongo Db - PHP Day WorkshopMongo Db - PHP Day Workshop
Mongo Db - PHP Day WorkshopDiego Sana
 
RubyMasters 2011 - Beyond Ruby with NodeJS
RubyMasters 2011 - Beyond Ruby with NodeJSRubyMasters 2011 - Beyond Ruby with NodeJS
RubyMasters 2011 - Beyond Ruby with NodeJSEmerson Macedo
 
Joomla Day Brasil 2010: Customizações para grandes portais
Joomla Day Brasil 2010: Customizações para grandes portaisJoomla Day Brasil 2010: Customizações para grandes portais
Joomla Day Brasil 2010: Customizações para grandes portaisrafaelberlanda
 
Desenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine OrmDesenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine OrmGuilherme Blanco
 
Desenvolvendo aplicacoes mobile_com_html_css_
Desenvolvendo aplicacoes mobile_com_html_css_Desenvolvendo aplicacoes mobile_com_html_css_
Desenvolvendo aplicacoes mobile_com_html_css_Rodrigo Urubatan
 
Persistência Java: Hibernate e JPA
Persistência Java: Hibernate e JPAPersistência Java: Hibernate e JPA
Persistência Java: Hibernate e JPACaelum
 
Técnicas e recursos para desenvolvimento Web em cenários de grande escala
Técnicas e recursos para desenvolvimento Web em cenários de grande escalaTécnicas e recursos para desenvolvimento Web em cenários de grande escala
Técnicas e recursos para desenvolvimento Web em cenários de grande escalaAlexandre Tarifa
 
WebSocket com Node.js ( socketstream && coffeescript ) X RoR ( Juggernaut )
WebSocket com Node.js ( socketstream && coffeescript ) X RoR ( Juggernaut )WebSocket com Node.js ( socketstream && coffeescript ) X RoR ( Juggernaut )
WebSocket com Node.js ( socketstream && coffeescript ) X RoR ( Juggernaut )João Moura
 
SOLID através de BDD: um guia prático para rubistas
SOLID através de BDD: um guia prático para rubistasSOLID através de BDD: um guia prático para rubistas
SOLID através de BDD: um guia prático para rubistaslucashungaro
 

Similar to HibernateEFETIVOERROSCOMUNSESOLUÇÕES (20)

LambdaDay: Backbone.js
LambdaDay: Backbone.jsLambdaDay: Backbone.js
LambdaDay: Backbone.js
 
JasperReports Tecnicas de geracao_de_relatorios1
JasperReports  Tecnicas de geracao_de_relatorios1JasperReports  Tecnicas de geracao_de_relatorios1
JasperReports Tecnicas de geracao_de_relatorios1
 
Dicas para Turbinar o servidor de Aplicações JBoss 7
Dicas para Turbinar o servidor de Aplicações JBoss 7Dicas para Turbinar o servidor de Aplicações JBoss 7
Dicas para Turbinar o servidor de Aplicações JBoss 7
 
Backbone.js nas trincheiras
Backbone.js nas trincheirasBackbone.js nas trincheiras
Backbone.js nas trincheiras
 
Redis um banco chave valor
Redis um banco chave valorRedis um banco chave valor
Redis um banco chave valor
 
Livropythonmysql 091022073751-phpapp01
Livropythonmysql 091022073751-phpapp01Livropythonmysql 091022073751-phpapp01
Livropythonmysql 091022073751-phpapp01
 
Offline Web com Service Workers - Sérgio Lopes
Offline Web com Service Workers - Sérgio LopesOffline Web com Service Workers - Sérgio Lopes
Offline Web com Service Workers - Sérgio Lopes
 
MongoDB + PHP
MongoDB + PHPMongoDB + PHP
MongoDB + PHP
 
Como Perder Peso (no browser)
Como Perder Peso (no browser)Como Perder Peso (no browser)
Como Perder Peso (no browser)
 
Mongo Db - PHP Day Workshop
Mongo Db - PHP Day WorkshopMongo Db - PHP Day Workshop
Mongo Db - PHP Day Workshop
 
Realtime com node.js e socket.io
Realtime com node.js e socket.ioRealtime com node.js e socket.io
Realtime com node.js e socket.io
 
RubyMasters 2011 - Beyond Ruby with NodeJS
RubyMasters 2011 - Beyond Ruby with NodeJSRubyMasters 2011 - Beyond Ruby with NodeJS
RubyMasters 2011 - Beyond Ruby with NodeJS
 
Ruby On Rails Regis
Ruby On Rails RegisRuby On Rails Regis
Ruby On Rails Regis
 
Joomla Day Brasil 2010: Customizações para grandes portais
Joomla Day Brasil 2010: Customizações para grandes portaisJoomla Day Brasil 2010: Customizações para grandes portais
Joomla Day Brasil 2010: Customizações para grandes portais
 
Desenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine OrmDesenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine Orm
 
Desenvolvendo aplicacoes mobile_com_html_css_
Desenvolvendo aplicacoes mobile_com_html_css_Desenvolvendo aplicacoes mobile_com_html_css_
Desenvolvendo aplicacoes mobile_com_html_css_
 
Persistência Java: Hibernate e JPA
Persistência Java: Hibernate e JPAPersistência Java: Hibernate e JPA
Persistência Java: Hibernate e JPA
 
Técnicas e recursos para desenvolvimento Web em cenários de grande escala
Técnicas e recursos para desenvolvimento Web em cenários de grande escalaTécnicas e recursos para desenvolvimento Web em cenários de grande escala
Técnicas e recursos para desenvolvimento Web em cenários de grande escala
 
WebSocket com Node.js ( socketstream && coffeescript ) X RoR ( Juggernaut )
WebSocket com Node.js ( socketstream && coffeescript ) X RoR ( Juggernaut )WebSocket com Node.js ( socketstream && coffeescript ) X RoR ( Juggernaut )
WebSocket com Node.js ( socketstream && coffeescript ) X RoR ( Juggernaut )
 
SOLID através de BDD: um guia prático para rubistas
SOLID através de BDD: um guia prático para rubistasSOLID através de BDD: um guia prático para rubistas
SOLID através de BDD: um guia prático para rubistas
 

More from Rafael Ponte

TechDay: 10 Features do Oracle que voce nao conhecia - CONNECT BY CLAUSE
TechDay: 10 Features do Oracle que voce nao conhecia - CONNECT BY CLAUSETechDay: 10 Features do Oracle que voce nao conhecia - CONNECT BY CLAUSE
TechDay: 10 Features do Oracle que voce nao conhecia - CONNECT BY CLAUSERafael Ponte
 
TechDay Retrospectiva 2018
TechDay Retrospectiva 2018TechDay Retrospectiva 2018
TechDay Retrospectiva 2018Rafael Ponte
 
Arquitetura Java - Escalando além do Hype
Arquitetura Java - Escalando além do HypeArquitetura Java - Escalando além do Hype
Arquitetura Java - Escalando além do HypeRafael Ponte
 
Como treinar seu estagiario
Como treinar seu estagiarioComo treinar seu estagiario
Como treinar seu estagiarioRafael Ponte
 
Lidando com o Caos: Testando Código PLSQL em um Projeto Critico
Lidando com o Caos: Testando Código PLSQL em um Projeto CriticoLidando com o Caos: Testando Código PLSQL em um Projeto Critico
Lidando com o Caos: Testando Código PLSQL em um Projeto CriticoRafael Ponte
 
Como Apresentar Codigo em Slides - Javou #7 - 2016
Como Apresentar Codigo em Slides - Javou #7 - 2016Como Apresentar Codigo em Slides - Javou #7 - 2016
Como Apresentar Codigo em Slides - Javou #7 - 2016Rafael Ponte
 
Importancia dos Testes Automatizados no dia a dia FIC-Estacio 2015
Importancia dos Testes Automatizados no dia a dia FIC-Estacio 2015Importancia dos Testes Automatizados no dia a dia FIC-Estacio 2015
Importancia dos Testes Automatizados no dia a dia FIC-Estacio 2015Rafael Ponte
 
Importancia dos Testes Automatizados no dia a dia (Don't Panic)
Importancia dos Testes Automatizados no dia a dia (Don't Panic)Importancia dos Testes Automatizados no dia a dia (Don't Panic)
Importancia dos Testes Automatizados no dia a dia (Don't Panic)Rafael Ponte
 
Importância dos testes automatizados no dia a dia
Importância dos testes automatizados no dia a diaImportância dos testes automatizados no dia a dia
Importância dos testes automatizados no dia a diaRafael Ponte
 
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)Rafael Ponte
 
Migrations for Java
Migrations for JavaMigrations for Java
Migrations for JavaRafael Ponte
 
Importância dos testes automatizadoss
Importância dos testes automatizadossImportância dos testes automatizadoss
Importância dos testes automatizadossRafael Ponte
 
Greenbar - Testes automatizados na sua empresa
Greenbar - Testes automatizados na sua empresaGreenbar - Testes automatizados na sua empresa
Greenbar - Testes automatizados na sua empresaRafael Ponte
 
Desafios de um desenvolvedor JSF
Desafios de um desenvolvedor JSFDesafios de um desenvolvedor JSF
Desafios de um desenvolvedor JSFRafael Ponte
 
Curso de Java server faces (JSF)
Curso de Java server faces (JSF)Curso de Java server faces (JSF)
Curso de Java server faces (JSF)Rafael Ponte
 
Boas Práticas com JavaServer Faces (Jsf)
Boas Práticas com JavaServer Faces (Jsf)Boas Práticas com JavaServer Faces (Jsf)
Boas Práticas com JavaServer Faces (Jsf)Rafael Ponte
 
JavaServer Faces - Desenvolvendo aplicações web com produtividade
JavaServer Faces - Desenvolvendo aplicações web com produtividadeJavaServer Faces - Desenvolvendo aplicações web com produtividade
JavaServer Faces - Desenvolvendo aplicações web com produtividadeRafael Ponte
 
Entendendo Domain-Driven Design
Entendendo Domain-Driven DesignEntendendo Domain-Driven Design
Entendendo Domain-Driven DesignRafael Ponte
 
Anatomia do JSF, JavaServer Faces
Anatomia do JSF, JavaServer FacesAnatomia do JSF, JavaServer Faces
Anatomia do JSF, JavaServer FacesRafael Ponte
 

More from Rafael Ponte (19)

TechDay: 10 Features do Oracle que voce nao conhecia - CONNECT BY CLAUSE
TechDay: 10 Features do Oracle que voce nao conhecia - CONNECT BY CLAUSETechDay: 10 Features do Oracle que voce nao conhecia - CONNECT BY CLAUSE
TechDay: 10 Features do Oracle que voce nao conhecia - CONNECT BY CLAUSE
 
TechDay Retrospectiva 2018
TechDay Retrospectiva 2018TechDay Retrospectiva 2018
TechDay Retrospectiva 2018
 
Arquitetura Java - Escalando além do Hype
Arquitetura Java - Escalando além do HypeArquitetura Java - Escalando além do Hype
Arquitetura Java - Escalando além do Hype
 
Como treinar seu estagiario
Como treinar seu estagiarioComo treinar seu estagiario
Como treinar seu estagiario
 
Lidando com o Caos: Testando Código PLSQL em um Projeto Critico
Lidando com o Caos: Testando Código PLSQL em um Projeto CriticoLidando com o Caos: Testando Código PLSQL em um Projeto Critico
Lidando com o Caos: Testando Código PLSQL em um Projeto Critico
 
Como Apresentar Codigo em Slides - Javou #7 - 2016
Como Apresentar Codigo em Slides - Javou #7 - 2016Como Apresentar Codigo em Slides - Javou #7 - 2016
Como Apresentar Codigo em Slides - Javou #7 - 2016
 
Importancia dos Testes Automatizados no dia a dia FIC-Estacio 2015
Importancia dos Testes Automatizados no dia a dia FIC-Estacio 2015Importancia dos Testes Automatizados no dia a dia FIC-Estacio 2015
Importancia dos Testes Automatizados no dia a dia FIC-Estacio 2015
 
Importancia dos Testes Automatizados no dia a dia (Don't Panic)
Importancia dos Testes Automatizados no dia a dia (Don't Panic)Importancia dos Testes Automatizados no dia a dia (Don't Panic)
Importancia dos Testes Automatizados no dia a dia (Don't Panic)
 
Importância dos testes automatizados no dia a dia
Importância dos testes automatizados no dia a diaImportância dos testes automatizados no dia a dia
Importância dos testes automatizados no dia a dia
 
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
 
Migrations for Java
Migrations for JavaMigrations for Java
Migrations for Java
 
Importância dos testes automatizadoss
Importância dos testes automatizadossImportância dos testes automatizadoss
Importância dos testes automatizadoss
 
Greenbar - Testes automatizados na sua empresa
Greenbar - Testes automatizados na sua empresaGreenbar - Testes automatizados na sua empresa
Greenbar - Testes automatizados na sua empresa
 
Desafios de um desenvolvedor JSF
Desafios de um desenvolvedor JSFDesafios de um desenvolvedor JSF
Desafios de um desenvolvedor JSF
 
Curso de Java server faces (JSF)
Curso de Java server faces (JSF)Curso de Java server faces (JSF)
Curso de Java server faces (JSF)
 
Boas Práticas com JavaServer Faces (Jsf)
Boas Práticas com JavaServer Faces (Jsf)Boas Práticas com JavaServer Faces (Jsf)
Boas Práticas com JavaServer Faces (Jsf)
 
JavaServer Faces - Desenvolvendo aplicações web com produtividade
JavaServer Faces - Desenvolvendo aplicações web com produtividadeJavaServer Faces - Desenvolvendo aplicações web com produtividade
JavaServer Faces - Desenvolvendo aplicações web com produtividade
 
Entendendo Domain-Driven Design
Entendendo Domain-Driven DesignEntendendo Domain-Driven Design
Entendendo Domain-Driven Design
 
Anatomia do JSF, JavaServer Faces
Anatomia do JSF, JavaServer FacesAnatomia do JSF, JavaServer Faces
Anatomia do JSF, JavaServer Faces
 

HibernateEFETIVOERROSCOMUNSESOLUÇÕES