172
Hibernate EFETIVO ERROS COMUNS E SOLUÇÕES Rafael Ponte IA-2014

Hibernate efetivo (IA-2014 / Disturbing the Mind)

Embed Size (px)

Citation preview

Page 1: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Hibernate EFETIVOERROS COMUNS E SOLUÇÕES

Rafael Ponte IA-2014

Page 2: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Eu estava me perguntando quando de fato o Hibernate foi criado...

Page 3: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Eu estava me perguntando quando de fato o Hibernate foi criado...

Luca Bastos

O “Boom” foi em 2003!

Page 4: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Mais de uma década! 2014 - 2003 = 11

Page 5: Hibernate efetivo (IA-2014 / Disturbing the Mind)

mas ainda hoje...

Page 6: Hibernate efetivo (IA-2014 / Disturbing the Mind)

mas ainda hoje...

existem devs que subutilizam o framework

Page 7: Hibernate efetivo (IA-2014 / Disturbing the Mind)

mas ainda hoje...

existem devs que subutilizam o framework

problemas de perfomance e escalabilidade

Page 8: Hibernate efetivo (IA-2014 / Disturbing the Mind)

e pra piorar...

Page 9: Hibernate efetivo (IA-2014 / Disturbing the Mind)

culpam o Hibernate

Page 10: Hibernate efetivo (IA-2014 / Disturbing the Mind)

culpam o Hibernate

A culpa é do Banco de Dados!

Sérgio

Page 11: Hibernate efetivo (IA-2014 / Disturbing the Mind)

é fácil culpar o que não se conhece...

Page 12: Hibernate efetivo (IA-2014 / Disturbing the Mind)

um SGDB mal configurado pode ser o problema...

Page 13: Hibernate efetivo (IA-2014 / Disturbing the Mind)

um SGDB mal configurado pode ser o problema...

MAS na maioria das vezes o

problema está na SUA APLICAÇÃO

Page 14: Hibernate efetivo (IA-2014 / Disturbing the Mind)

tabelas sem índices

<3

Page 15: Hibernate efetivo (IA-2014 / Disturbing the Mind)

tabelas sem índices consultas mal-feitas

<3 <3

Page 16: Hibernate efetivo (IA-2014 / Disturbing the Mind)

tabelas sem índices consultas mal-feitas

<3 <3 <3

muitos hits ao banco

Page 17: Hibernate efetivo (IA-2014 / Disturbing the Mind)

tabelas sem índices consultas mal-feitas

muitos hits ao banco

connection leaks

<3 <3 <3

Page 18: Hibernate efetivo (IA-2014 / Disturbing the Mind)

tabelas sem índices consultas mal-feitas

muitos hits ao banco

connection leaks

<3 <3 <3

memory leaks

Page 19: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Não saber tirar proveito framework!

Page 20: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Hibernate Efetivo 6 dicas para não deixar

sua app morrer

Page 21: Hibernate efetivo (IA-2014 / Disturbing the Mind)

@rponte

Page 22: Hibernate efetivo (IA-2014 / Disturbing the Mind)
Page 23: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Fortaleza - Terra do Sol

Page 24: Hibernate efetivo (IA-2014 / Disturbing the Mind)
Page 25: Hibernate efetivo (IA-2014 / Disturbing the Mind)
Page 26: Hibernate efetivo (IA-2014 / Disturbing the Mind)

#1 POOL DE

CONEXÕES

Page 27: Hibernate efetivo (IA-2014 / Disturbing the Mind)

com certeza todos aqui já ouviram falar...

Page 28: Hibernate efetivo (IA-2014 / Disturbing the Mind)

mas nem todos dão a devida atenção...

Page 29: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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

Page 30: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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

ou até receberem um

Page 31: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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

ou até receberem um

org.hibernate.exception.GenericJDBCException: Cannot

open connection

Page 32: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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

Page 33: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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=1234hibernate.connection.pool_size=30  !!

hibernate.properties

Page 34: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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=1234hibernate.connection.pool_size=30  !!

hibernate.properties

Page 35: Hibernate efetivo (IA-2014 / Disturbing the Mind)

a app volta a funcionar bem por um tempo

Page 36: Hibernate efetivo (IA-2014 / Disturbing the Mind)

a app volta a funcionar bem por um tempo

Page 37: Hibernate efetivo (IA-2014 / Disturbing the Mind)

e vão alocando mais conexões com o tempo

hibernate.connection.pool_size=30                                                                40                                                                55                                                                70                                                            ...  

hibernate.properties

Page 38: Hibernate efetivo (IA-2014 / Disturbing the Mind)

o pool PADRÃO do Hibernate

Page 39: Hibernate efetivo (IA-2014 / Disturbing the Mind)

que possui uma impl. RUDIMENTAR

Page 40: Hibernate efetivo (IA-2014 / Disturbing the Mind)

INFO DriverManagerConnectionProvider:64 - Using Hibernate built-in connection pool (not for production use!)!INFO DriverManagerConnectionProvider:65 - Hibernate connection pool size: 20!

Page 41: Hibernate efetivo (IA-2014 / Disturbing the Mind)

INFO DriverManagerConnectionProvider:64 - Using Hibernate built-in connection pool (not for production use!)!INFO DriverManagerConnectionProvider:65 - Hibernate connection pool size: 20!

not for production use!

Page 42: Hibernate efetivo (IA-2014 / Disturbing the Mind)

qual pool utilizar?

Page 43: Hibernate efetivo (IA-2014 / Disturbing the Mind)

temos ótimas opções...

Page 44: Hibernate efetivo (IA-2014 / Disturbing the Mind)

pools como c3p0 ou commons-dbcp

temos ótimas opções...

Page 45: Hibernate efetivo (IA-2014 / Disturbing the Mind)

o Hibernate já vem com c3p0

Page 46: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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

Page 47: Hibernate efetivo (IA-2014 / Disturbing the Mind)

ou melhor ainda...

Page 48: Hibernate efetivo (IA-2014 / Disturbing the Mind)

<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

Page 49: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Pool traz melhoria de performance

Page 50: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Pool traz melhoria de performance

mas não faz milagres

Page 51: Hibernate efetivo (IA-2014 / Disturbing the Mind)

#2 lidando com

LazyInitializationException

Page 52: Hibernate efetivo (IA-2014 / Disturbing the Mind)

quando e por que acontece?

Page 53: Hibernate efetivo (IA-2014 / Disturbing the Mind)

@Entity  class  NotaFiscal  {      …      @OneToMany      List<Item>  itens;  }

Page 54: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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

Percorrendo os itens de uma nota

Page 55: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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();

Page 56: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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

Page 57: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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.

Page 58: Hibernate efetivo (IA-2014 / Disturbing the Mind)

resolver parece fácil, certo?

Page 59: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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

Page 60: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Mas e quando estamos trabalhando na Web?

Page 61: Hibernate efetivo (IA-2014 / Disturbing the Mind)

@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>

Page 62: Hibernate efetivo (IA-2014 / Disturbing the Mind)

@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>

session foi fechada!

Page 63: Hibernate efetivo (IA-2014 / Disturbing the Mind)

@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

Page 64: Hibernate efetivo (IA-2014 / Disturbing the Mind)

e agora? #comofas

Page 65: Hibernate efetivo (IA-2014 / Disturbing the Mind)

e agora? #comofas

Sérgio

passa tudo pra EAGER! ;D

Page 66: Hibernate efetivo (IA-2014 / Disturbing the Mind)

@Entity  class  NotaFiscal  {      …      @OneToMany(fetch=FetchType.EAGER)      List<Item>  itens;  }

Page 67: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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);

Page 68: Hibernate efetivo (IA-2014 / Disturbing the Mind)

mas isso poderia gerar uma sobrecarga...

Page 69: Hibernate efetivo (IA-2014 / Disturbing the Mind)

mas isso poderia gerar uma sobrecarga...

pois os itens da nota não são necessários em

muitos lugares

Page 70: Hibernate efetivo (IA-2014 / Disturbing the Mind)

lembre-se que ter os relacionamentos como LAZY é

uma boa prática

Page 71: Hibernate efetivo (IA-2014 / Disturbing the Mind)

como evitar LIE sem modificar o relacionamento

para EAGER?

Page 72: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Open Session In View

Page 73: Hibernate efetivo (IA-2014 / Disturbing the Mind)

@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

Page 74: Hibernate efetivo (IA-2014 / Disturbing the Mind)

o OSIV só evita LIE no mesmo request!

Page 75: Hibernate efetivo (IA-2014 / Disturbing the Mind)

anti-pattern?

Page 76: Hibernate efetivo (IA-2014 / Disturbing the Mind)

#3 Second Level

Cache

Page 77: Hibernate efetivo (IA-2014 / Disturbing the Mind)

NotaFiscal  nf  =  (NotaFiscal)  session.load(NotaFiscal.class,  42);

Carregando uma nota por ID

Page 78: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Banco de Dados

Session

Page 79: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Banco de Dados

Session

First Level Cache

Page 80: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Banco de Dados

Session Session Session Session

Page 81: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Banco de Dados

????

Session Session Session Session

Page 82: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Banco de Dados

Second Level Cache

Session Session Session Session

Page 83: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Banco de Dados

Second Level Cache

Session Session Session

First Level Cache

Session

Page 84: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Banco de Dados

SessionFactory

Session Session Session Session

Page 85: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Configurar é simples

Page 86: Hibernate efetivo (IA-2014 / Disturbing the Mind)

#1 configuramos o Hibernate

hibernate.cache.use_second_level_cache=true  hibernate.cache.region.factory_class=net.sf.ehcache.hibernate.EhCacheRegionFactory  

hibernate.properties

Page 87: Hibernate efetivo (IA-2014 / Disturbing the Mind)

@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

Page 88: Hibernate efetivo (IA-2014 / Disturbing the Mind)

@Cache(  usage=CacheConcurrencyStrategy.READ_WRITE)

Caching Strategy

READ_ONLY

NONSTRICT_READ_WRITE

READ_WRITE

Page 89: Hibernate efetivo (IA-2014 / Disturbing the Mind)

@Cache(  usage=CacheConcurrencyStrategy.READ_WRITE)

Caching Strategy

READ_ONLY

NONSTRICT_READ_WRITE

READ_WRITE

Melhor performance

Page 90: Hibernate efetivo (IA-2014 / Disturbing the Mind)

@Cache(  usage=CacheConcurrencyStrategy.READ_WRITE)

Caching Strategy

READ_ONLY

NONSTRICT_READ_WRITE

READ_WRITE

Dados não críticos

Page 91: Hibernate efetivo (IA-2014 / Disturbing the Mind)

@Cache(  usage=CacheConcurrencyStrategy.READ_WRITE)

Caching Strategy

READ_ONLY

NONSTRICT_READ_WRITE

READ_WRITE Modificações frequentes

Page 92: Hibernate efetivo (IA-2014 / Disturbing the Mind)

<cache          name="br.com.triadworks.model.Bug"          maxElementsInMemory="10000"          eternal="false"          timeToIdleSeconds="1800"          timeToLiveSeconds="10000"          overflowToDisk="true"          memoryStoreEvictionPolicy="LRU"  />

ehcache.xml

Page 93: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Como 2nd Level Cache funciona?

Page 94: Hibernate efetivo (IA-2014 / Disturbing the Mind)

2nd Level Cache não faz cache das instancias das entidades

Page 95: Hibernate efetivo (IA-2014 / Disturbing the Mind)

2nd Level Cache não faz cache das instancias das entidades

somente dos valores das propriedades

Page 96: Hibernate efetivo (IA-2014 / Disturbing the Mind)

@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;  }

Page 97: Hibernate efetivo (IA-2014 / Disturbing the Mind)

modelo conceitual do cache

Bug Data Cache

17 -> [ “Bug #1”, “ABERTA” , 1 ]!18 -> [ “Bug #2”, “FECHADA”, 2 ]!19 -> [ “Bug #3”, “ABERTA” , 1 ]

Page 98: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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

Page 99: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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

Page 100: Hibernate efetivo (IA-2014 / Disturbing the Mind)

2nd Level Cache não faz cache das associações

Page 101: Hibernate efetivo (IA-2014 / Disturbing the Mind)

@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;  }

Page 102: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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] ]

Page 103: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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

Page 104: Hibernate efetivo (IA-2014 / Disturbing the Mind)

E o que o Hibernate faz com todos estes IDs?

Page 105: Hibernate efetivo (IA-2014 / Disturbing the Mind)

E o que o Hibernate faz com todos estes IDs?

vai no banco de novo! a não ser que

você…

Page 106: Hibernate efetivo (IA-2014 / Disturbing the Mind)

@Entity  @Cache(usage=CacheConcurrencyStrategy.READ_WRITE)  class  Projeto  {      ...  }  !!@Entity  @Cache(usage=CacheConcurrencyStrategy.READ_ONLY)  class  Comentario  {    ...  }

configure o cache das entidades

Page 107: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Devo cachear todas as minhas entidades?

Page 108: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Com 2nd Level Cache tudo funciona bem enquanto buscamos por ID...

session.load(Bug.class,  17);

Page 109: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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();  

Page 110: Hibernate efetivo (IA-2014 / Disturbing the Mind)

#4 Query Cache

Page 111: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Query Cache faz cache do resultado de uma query

Page 112: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Configurando Hibernate para usar Query Cache

hibernate.cache.use_query_cache=true  

hibernate.properties

Page 113: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Query Cache

session    .createQuery("from  Bug  where  status  =  ?")      .setString(0,  status)    .setCacheable(true)    .list();  

Page 114: Hibernate efetivo (IA-2014 / Disturbing the Mind)

modelo conceitual do query cache

Query Cache

[“from Bug where status = ?”, [“ABERTO”]] -> [17, 19]

Page 115: Hibernate efetivo (IA-2014 / Disturbing the Mind)

modelo conceitual do query cache

Query Cache

[“from Bug where status = ?”, [“ABERTO”]] -> [17, 19]

Query + Parâmetros IDs

Page 116: Hibernate efetivo (IA-2014 / Disturbing the Mind)

por isso Query Cache SEM 2nd Level Cache não é de

muita ajuda

Page 117: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Utilize somente em consultas que são executadas repetidas

vezes com os mesmos parâmetros

Page 118: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Utilize somente em consultas que são executadas repetidas

vezes com os mesmos parâmetros

Page 119: Hibernate efetivo (IA-2014 / Disturbing the Mind)

#5 Select n+1

Page 120: Hibernate efetivo (IA-2014 / Disturbing the Mind)

o campeão em prejudicar a performance da

aplicação

Page 121: Hibernate efetivo (IA-2014 / Disturbing the Mind)

NotaFiscal  nf  =  (NotaFiscal)  session.load(NotaFiscal.class,  42);  processaItensDaNota(nf);  

Processando os itens de uma nota

Page 122: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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);

Page 123: Hibernate efetivo (IA-2014 / Disturbing the Mind)

List<NotaFiscal>  notas  =  dao.listaTudo();  for  (NotaFiscal  nf  :  notas)  {          processaItensDaNota(nf);  }  

Processando os itens de varias notas

Page 124: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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);  }

Page 125: Hibernate efetivo (IA-2014 / Disturbing the Mind)

são muitos hits no banco de dados

Page 126: Hibernate efetivo (IA-2014 / Disturbing the Mind)

são muitos hits no banco de dados

mas podemos resolver isso...

Page 127: Hibernate efetivo (IA-2014 / Disturbing the Mind)

3 soluções

Page 128: Hibernate efetivo (IA-2014 / Disturbing the Mind)

#1 EAGER ou join-fetch

Page 129: Hibernate efetivo (IA-2014 / Disturbing the Mind)

@Entity  class  NotaFiscal  {      …      @OneToMany(fetch=FetchType.EAGER)      List<Item>  itens;  }

Utilizando FetchMode=EAGER

Page 130: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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();

Page 131: Hibernate efetivo (IA-2014 / Disturbing the Mind)

antes de definir um mapeamento global deste

tipo você precisa se perguntar...

Page 132: Hibernate efetivo (IA-2014 / Disturbing the Mind)

SEMPRE que uma nota é necessária, todos seus

itens também são necessários?

Page 133: Hibernate efetivo (IA-2014 / Disturbing the Mind)

não?

Page 134: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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

Utilizando Join Fetch

Page 135: Hibernate efetivo (IA-2014 / Disturbing the Mind)

#2 batch-size nas associações

Page 136: Hibernate efetivo (IA-2014 / Disturbing the Mind)

É o meio termo entre EAGER e LAZY

Page 137: Hibernate efetivo (IA-2014 / Disturbing the Mind)

@Entity  class  NotaFiscal  {      …      @OneToMany      @BatchSize(size=10)      List<Item>  itens;  }

@BatchSize

Page 138: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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);  }

Page 139: Hibernate efetivo (IA-2014 / Disturbing the Mind)

@BatchSize também é conhecido como:

Page 140: Hibernate efetivo (IA-2014 / Disturbing the Mind)

@BatchSize também é conhecido como:

otimização de adivinhação cega(blind-guess optimization)

Page 141: Hibernate efetivo (IA-2014 / Disturbing the Mind)

@BatchSize também é conhecido como:

otimização de adivinhação cega(blind-guess optimization)

ou seja, é um palpite

Page 142: Hibernate efetivo (IA-2014 / Disturbing the Mind)

#3 FetchMode SUBSELECT

Page 143: Hibernate efetivo (IA-2014 / Disturbing the Mind)

@Entity  class  NotaFiscal  {      …      @OneToMany      @Fetch(FetchMode.SUBSELECT)      List<Item>  itens;  }

SUBSELECT

Page 144: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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);  }

Page 145: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Qual utilizar?

Page 146: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Qual utilizar?

depende

Page 147: Hibernate efetivo (IA-2014 / Disturbing the Mind)

#6 Processamento

em lote

Page 148: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Imagine que temos que importar 100k produtos para

o banco de dados

Page 149: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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();

Page 150: Hibernate efetivo (IA-2014 / Disturbing the Mind)

em ~50k produtos nós receberíamos um

OutOfMemoryException

Page 151: Hibernate efetivo (IA-2014 / Disturbing the Mind)

por que?

Page 152: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Hibernate faz cache de todas as instâncias dos Produtos

inseridos na Session

Page 153: Hibernate efetivo (IA-2014 / Disturbing the Mind)

mas como melhorar?

Page 154: Hibernate efetivo (IA-2014 / Disturbing the Mind)

!!!

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();

Page 155: Hibernate efetivo (IA-2014 / Disturbing the Mind)

evitamos o OutOfMemoryException

Page 156: Hibernate efetivo (IA-2014 / Disturbing the Mind)

evitamos o OutOfMemoryException

Mas o processamento ainda continua lento!

Page 157: Hibernate efetivo (IA-2014 / Disturbing the Mind)

evitamos o OutOfMemoryException

Mas o processamento ainda continua lento!

Dá pra melhorar?

Page 158: Hibernate efetivo (IA-2014 / Disturbing the Mind)

JDBC puro?

Page 159: Hibernate efetivo (IA-2014 / Disturbing the Mind)

JDBC puro?

código de maxu!

Handerson Frota

Page 160: Hibernate efetivo (IA-2014 / Disturbing the Mind)

StatelessSession

Page 161: Hibernate efetivo (IA-2014 / Disturbing the Mind)

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

Page 162: Hibernate efetivo (IA-2014 / Disturbing the Mind)

!

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();

Page 163: Hibernate efetivo (IA-2014 / Disturbing the Mind)

menos consumo de memória e mais rápida!

Page 164: Hibernate efetivo (IA-2014 / Disturbing the Mind)

menos consumo de memória e mais rápida!

Yuri Adams

dá pra melhorar?

Page 165: Hibernate efetivo (IA-2014 / Disturbing the Mind)

hibernate.jdbc.batch_size=50  

hibernate.properties

Page 166: Hibernate efetivo (IA-2014 / Disturbing the Mind)

CONCLUSÃO

Page 167: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Foi apenas a ponta o iceberg!

Page 168: Hibernate efetivo (IA-2014 / Disturbing the Mind)

cada uma destas dicas são simples, mas requerem mais estudo

Page 169: Hibernate efetivo (IA-2014 / Disturbing the Mind)

cada uma destas dicas são simples, mas requerem mais estudopois depende do projeto

Page 170: Hibernate efetivo (IA-2014 / Disturbing the Mind)

um DBA certamente pode te ajudar em muitos cenários

Page 171: Hibernate efetivo (IA-2014 / Disturbing the Mind)

Hibernate não é seu inimigo, deixem de #mimimi