Your SlideShare is downloading. ×
0
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Hibernate Efetivo (QCONSP-2012)
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Hibernate Efetivo (QCONSP-2012)

14,840

Published on

Mesmo anos após o lançamento do Hibernate ainda é fácil encontrar projetos utilizando o framework de maneira ineficiente, podendo leva-lo a problemas sérios de performance ou até inviabilizar a …

Mesmo anos após o lançamento do Hibernate ainda é fácil encontrar projetos utilizando o framework de maneira ineficiente, podendo leva-lo a problemas sérios de performance ou até inviabilizar a aplicação. O uso não efetivo do Hibernate está intimamente ligado a erros comuns e más práticas em sua utilização, que vão desde pool de conexões, select n+1, configuração de cache, batch-size até o uso indevido do cache level 1 em processamentos batch e o tratamento de LazyInitializationException.

0 Comments
34 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
14,840
On Slideshare
0
From Embeds
0
Number of Embeds
10
Actions
Shares
0
Downloads
364
Comments
0
Likes
34
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Hibernate EFETIVO ERROS COMUNS E SOLUÇÕESTuesday, August 7, 2012
  • 2. Eu estava me perguntando quando de fato o Hibernate foi criado...Tuesday, August 7, 2012
  • 3. Eu estava me perguntando quando de fato o Hibernate foi criado... O “Boom” foi em 2003! Luca BastosTuesday, August 7, 2012
  • 4. Quase uma década! 2012 - 2003 = 9Tuesday, August 7, 2012
  • 5. mas ainda hoje...Tuesday, August 7, 2012
  • 6. mas ainda hoje... existem devs que subutilizam o frameworkTuesday, August 7, 2012
  • 7. mas ainda hoje... existem devs que subutilizam o framework problemas de perfomance e escalabilidadeTuesday, August 7, 2012
  • 8. e pra piorar...Tuesday, August 7, 2012
  • 9. culpam o HibernateTuesday, August 7, 2012
  • 10. culpam o Hibernate A culpa é do Banco de Dados! SérgioTuesday, August 7, 2012
  • 11. é fácil culpar o que não se conhece...Tuesday, August 7, 2012
  • 12. um SGDB mal configurado pode ser o problema...Tuesday, August 7, 2012
  • 13. um SGDB mal configurado pode ser o problema... MAS na maioria das vezes o problema está na SUA APLICAÇÃOTuesday, August 7, 2012
  • 14. tabelas sem índices <3Tuesday, August 7, 2012
  • 15. tabelas sem índices consultas mal-feitas <3 <3Tuesday, August 7, 2012
  • 16. tabelas sem índices consultas mal-feitas muitos hits ao bancoTuesday, August 7, 2012 <3 <3 <3
  • 17. tabelas sem índices consultas mal-feitas muitos hits ao banco connection leaksTuesday, August 7, 2012 <3 <3 <3
  • 18. tabelas sem índices consultas mal-feitas muitos hits ao banco connection leaks memory leaksTuesday, August 7, 2012 <3 <3 <3
  • 19. Não saber tirar proveito frameworkTuesday, August 7, 2012
  • 20. Hibernate Efetivo 6 dicas para não deixar sua app morrerTuesday, August 7, 2012
  • 21. @rponteTuesday, August 7, 2012
  • 22. Tuesday, August 7, 2012
  • 23. Fortaleza - Terra do SolTuesday, August 7, 2012
  • 24. #1 POOL DE CONEXÕESTuesday, August 7, 2012
  • 25. com certeza todos aqui já ouviram falar...Tuesday, August 7, 2012
  • 26. mas nem todos dão a devida atenção...Tuesday, August 7, 2012
  • 27. mas nem todos dão a devida atenção... até perceberem a app engasgandoTuesday, August 7, 2012
  • 28. mas nem todos dão a devida atenção... até perceberem a app engasgando ou até receberem umTuesday, August 7, 2012
  • 29. 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 connectionTuesday, August 7, 2012
  • 30. daí percebem que não configuraram o o pool do Hibernate hibernate.properties 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=1234Tuesday, August 7, 2012
  • 31. daí percebem que não configuraram o o pool do Hibernate hibernate.properties 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=30Tuesday, August 7, 2012
  • 32. daí percebem que não configuraram o o pool do Hibernate hibernate.properties 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=30Tuesday, August 7, 2012
  • 33. a app volta a funcionar bem por um tempoTuesday, August 7, 2012
  • 34. a app volta a funcionar bem por um tempoTuesday, August 7, 2012
  • 35. e vão alocando mais conexões com o tempo hibernate.properties hibernate.connection.pool_size=30                                                              40                                                              55                                                              70                                                            ...Tuesday, August 7, 2012
  • 36. o pool PADRÃO do HibernateTuesday, August 7, 2012
  • 37. que possui uma impl. RUDIMENTARTuesday, August 7, 2012
  • 38. INFO DriverManagerConnectionProvider:64 - Using Hibernate built-in connection pool (not for production use!) INFO DriverManagerConnectionProvider:65 - Hibernate connection pool size: 20Tuesday, August 7, 2012
  • 39. not for production use! INFO DriverManagerConnectionProvider:64 - Using Hibernate built-in connection pool (not for production use!) INFO DriverManagerConnectionProvider:65 - Hibernate connection pool size: 20Tuesday, August 7, 2012
  • 40. qual pool utilizar?Tuesday, August 7, 2012
  • 41. temos ótimas opções...Tuesday, August 7, 2012
  • 42. temos ótimas opções... pools como c3p0 ou commons-dbcpTuesday, August 7, 2012
  • 43. o Hibernate já vem com c3p0Tuesday, August 7, 2012
  • 44. configurando c3p0 hibernate.properties 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=50Tuesday, August 7, 2012
  • 45. ou melhor ainda...Tuesday, August 7, 2012
  • 46. podemos obter as conexões de um DataSource <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>Tuesday, August 7, 2012
  • 47. Pool traz melhoria de performanceTuesday, August 7, 2012
  • 48. Pool traz melhoria de performance mas não faz milagresTuesday, August 7, 2012
  • 49. #2 lidando com LazyInitialization ExceptionTuesday, August 7, 2012
  • 50. quando e por que acontece?Tuesday, August 7, 2012
  • 51. @Entity class  NotaFiscal  {    …    @OneToMany    List<Item>  itens; }Tuesday, August 7, 2012
  • 52. Percorrendo os itens de uma nota NotaFiscal  nf  =  (NotaFiscal)  session.load (NotaFiscal.class,  42); List<Item>  itens  =  nf.getItens();Tuesday, August 7, 2012
  • 53. Hibernate executa 2 selects NotaFiscal  nf  =  (NotaFiscal)  session.load(NotaFiscal.class,  42); select nf.* from NotaFiscal nf where nf.id=42 List<Item>  itens  =  nf.getItens(); select i.* from Item i where i.nota_fiscal_id=42Tuesday, August 7, 2012
  • 54. a session do Hibernate foi fechada 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());Tuesday, August 7, 2012
  • 55. mas ao ler os itens da nota Session  session  =   sessionFactory.openSession(); NotaFiscal  nf  =  (NotaFiscal)  session.load org.hibernate.LazyInitializationException: (NotaFiscal.class,  42); failed to lazily session.close(); initialize a collection - no session or session was closed. List<Item>  itens  =  nf.getItens(); System.out.println("numero  de  pedidos:"  +   itens.size());Tuesday, August 7, 2012
  • 56. resolver parece fácil, certo?Tuesday, August 7, 2012
  • 57. fechar a session ao término do trabalho 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();Tuesday, August 7, 2012
  • 58. Mas e quando estamos trabalhando na Web?Tuesday, August 7, 2012
  • 59. NotaFiscalController.java @Get("/notas/{id}") public  void  view(Long  id)  {    NotaFiscal  nf  =  notaFiscalDao.carrega(id);    result.include("nf",  nf);    result.forwardTo("/notas/view.jsp"); } view.jsp <c:forEach  var="item"  items="${nf.itens}">        ${item.produto.descricao}<br/> </c:forEach>Tuesday, August 7, 2012
  • 60. NotaFiscalController.java @Get("/notas/{id}") public  void  view(Long  id)  {    NotaFiscal  nf  =  notaFiscalDao.carrega(id);    result.include("nf",  nf);    result.forwardTo("/notas/view.jsp"); } LazyInitializationException view.jsp <c:forEach  var="item"  items="${nf.itens}">        ${item.produto.descricao}<br/> </c:forEach>Tuesday, August 7, 2012
  • 61. e agora? #comofasTuesday, August 7, 2012
  • 62. e agora? #comofas passa tudo pra EAGER! ;D SérgioTuesday, August 7, 2012
  • 63. @Entity class  NotaFiscal  {    …    @OneToMany(fetch=FetchType.EAGER)    List<Item>  itens; }Tuesday, August 7, 2012
  • 64. Hibernate executa 1 select NotaFiscal  nf  =  (NotaFiscal)  session.load(NotaFiscal.class,  42); select nf.*, i.* from NotaFiscal nf left outer join Item i on nf.id = i.nota_fiscal_id where nf.id=42Tuesday, August 7, 2012
  • 65. mas isso poderia gerar uma sobrecarga...Tuesday, August 7, 2012
  • 66. mas isso poderia gerar uma sobrecarga... pois os itens da nota não são necessários em muitos lugaresTuesday, August 7, 2012
  • 67. lembre-se que ter os relacionamentos como LAZY é uma boa práticaTuesday, August 7, 2012
  • 68. como evitar LIE sem modificar o relacionamento para EAGER?Tuesday, August 7, 2012
  • 69. Open Session In ViewTuesday, August 7, 2012
  • 70. Servlet Filter @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();       }     }   } }Tuesday, August 7, 2012
  • 71. o OSIV só evita LIE no mesmo request!Tuesday, August 7, 2012
  • 72. anti-pattern?Tuesday, August 7, 2012
  • 73. #3 Second Level CacheTuesday, August 7, 2012
  • 74. Carregando uma nota por ID NotaFiscal  nf  =  (NotaFiscal)  session.load (NotaFiscal.class,  42);Tuesday, August 7, 2012
  • 75. Session Banco de DadosTuesday, August 7, 2012
  • 76. First Level Cache Session Banco de DadosTuesday, August 7, 2012
  • 77. Session Session Session Session Banco de DadosTuesday, August 7, 2012
  • 78. Session Session Session Session Second Level Cache Banco de DadosTuesday, August 7, 2012
  • 79. First Level Cache Session Session Session Session Second Level Cache Banco de DadosTuesday, August 7, 2012
  • 80. Session Session Session Session SessionFactory Banco de DadosTuesday, August 7, 2012
  • 81. Configurar é simplesTuesday, August 7, 2012
  • 82. #1 configuramos o Hibernate hibernate.properties hibernate.cache.use_second_level_cache=true hibernate.cache.region.factory_class=net.sf.ehcac he.hibernate.EhCacheRegionFactoryTuesday, August 7, 2012
  • 83. #2 configuramos as entidades @Entity @Cache(usage=CacheConcurrencyStrategy.READ_WRITE) class  Issue  { @Id    private  Long  id; private  String  descricao; private  String  status; @ManyToOne private  Projeto  projeto;    @OneToMany    private  List<Comentario>  comentarios; }Tuesday, August 7, 2012
  • 84. Caching Strategy @Cache( usage=CacheConcurrencyStrategy.READ_WRITE) READ_ONLY NONSTRICT_READ_WRITE READ_WRITETuesday, August 7, 2012
  • 85. Caching Strategy @Cache( usage=CacheConcurrencyStrategy.READ_WRITE) READ_ONLY Melhor performance NONSTRICT_READ_WRITE READ_WRITETuesday, August 7, 2012
  • 86. Caching Strategy @Cache( usage=CacheConcurrencyStrategy.READ_WRITE) READ_ONLY NONSTRICT_READ_WRITE Dados não críticos READ_WRITETuesday, August 7, 2012
  • 87. Caching Strategy @Cache( usage=CacheConcurrencyStrategy.READ_WRITE) READ_ONLY NONSTRICT_READ_WRITE READ_WRITE Modificações frequentesTuesday, August 7, 2012
  • 88. ehcache.xml <cache        name="br.com.triadworks.model.Issue"        maxElementsInMemory="10000"        eternal="false"        timeToIdleSeconds="1800"        timeToLiveSeconds="10000"        overflowToDisk="true"        memoryStoreEvictionPolicy="LRU" />Tuesday, August 7, 2012
  • 89. Como 2nd Level Cache funciona?Tuesday, August 7, 2012
  • 90. 2nd Level Cache não faz cache das instancias das entidadesTuesday, August 7, 2012
  • 91. 2nd Level Cache não faz cache das instancias das entidades somente dos valores das propriedadesTuesday, August 7, 2012
  • 92. @Entity @Cache(usage=CacheConcurrencyStrategy.READ_WRITE) class  Issue  { @Id    private  Long  id; private  String  descricao; private  String  status; @ManyToOne private  Projeto  projeto;    @OneToMany    private  List<Comentario>  comentarios; }Tuesday, August 7, 2012
  • 93. modelo conceitual do cache Issue Data Cache 17 -> [ “Bug #1”, “ABERTA” , 1 ] 18 -> [ “Bug #2”, “FECHADA”, 2 ] 19 -> [ “Bug #3”, “ABERTA” , 1 ]Tuesday, August 7, 2012
  • 94. modelo conceitual do cache Issue 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"Tuesday, August 7, 2012
  • 95. 2nd Level Cache não faz cache das associaçõesTuesday, August 7, 2012
  • 96. @Entity @Cache(usage=CacheConcurrencyStrategy.READ_WRITE) class  Issue  { @Id    private  Long  id; private  String  descricao; private  String  status; @ManyToOne private  Projeto  projeto;    @OneToMany    @Cache(usage=CacheConcurrencyStrategy.READ_WRITE)    private  List<Comentario>  comentarios; }Tuesday, August 7, 2012
  • 97. modelo conceitual do cache Issue Data Cache 17 -> [ “Bug #1”, “ABERTA” , 1, [1,2] ] 18 -> [ “Bug #2”, “FECHADA”, 2, [] ] 19 -> [ “Bug #3”, “ABERTA” , 1, [3] ]Tuesday, August 7, 2012
  • 98. Devo cachear todas as minhas entidades?Tuesday, August 7, 2012
  • 99. Com 2nd Level Cache tudo funciona bem enquanto buscamos por ID... session.load(Issue.class,  17);Tuesday, August 7, 2012
  • 100. Com 2nd Level Cache tudo funciona bem enquanto buscamos por ID... session.load(Issue.class,  17); ...mas e quando precisamos de uma consulta um pouco diferente? session    .createQuery("from  Issue  where  status  =  ?")    .setString(0,"ABERTO")    .list();  Tuesday, August 7, 2012
  • 101. #4 Query CacheTuesday, August 7, 2012
  • 102. Query Cache faz cache do resultado de uma queryTuesday, August 7, 2012
  • 103. Configurando Hibernate para usar Query Cache hibernate.properties hibernate.cache.use_query_cache=trueTuesday, August 7, 2012
  • 104. Query Cache session    .createQuery("from  Issue  where  status  =  ?")    .setString(0,  status)    .setCacheable(true)    .list();  Tuesday, August 7, 2012
  • 105. modelo conceitual do query cache Query Cache [“from Issue where status = ?”, [“ABERTA”]] -> [17, 19]Tuesday, August 7, 2012
  • 106. modelo conceitual do query cache Query Cache [“from Issue where status = ?”, [“ABERTA”]] -> [17, 19] Query + Parâmetros IDsTuesday, August 7, 2012
  • 107. por isso Query Cache SEM 2nd Level Cache não é de muita ajudaTuesday, August 7, 2012
  • 108. Utilize somente em consultas que são executadas repetidas vezes com os mesmos parâmetrosTuesday, August 7, 2012
  • 109. Utilize somente em consultas que são executadas repetidas vezes com os mesmos parâmetrosTuesday, August 7, 2012
  • 110. #5 Select n+1Tuesday, August 7, 2012
  • 111. o campeão em prejudicar a performance da aplicaçãoTuesday, August 7, 2012
  • 112. Processando os itens de uma nota NotaFiscal  nf  =  (NotaFiscal)  session.load (NotaFiscal.class,  42); processaItensDaNota(nf);Tuesday, August 7, 2012
  • 113. Hibernate executa 2 selects NotaFiscal  nf  =  (NotaFiscal)  session.load(NotaFiscal.class,  42); select nf.* from NotaFiscal nf where nf.id=42 processaItensDaNota(nf); select i.* from Item i where i.nota_fiscal_id=42Tuesday, August 7, 2012
  • 114. Processando os itens de varias notas List<NotaFiscal>  notas  =  dao.listaTudo(); for  (NotaFiscal  nf  :  notas)  {        processaItensDaNota(nf); }Tuesday, August 7, 2012
  • 115. Hibernate executa n+1 selects List<NotaFiscal>  notas  =  dao.listaTudo(); select nf.* from NotaFiscal nf for  (NotaFiscal  nf  :  notas)  {        processaItensDaNota(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=? ...Tuesday, August 7, 2012
  • 116. são muitos hits no banco de dadosTuesday, August 7, 2012
  • 117. são muitos hits no banco de dados mas podemos resolver isso...Tuesday, August 7, 2012
  • 118. 3 soluçõesTuesday, August 7, 2012
  • 119. #1 EAGER ou join- fetchTuesday, August 7, 2012
  • 120. Utilizando FetchMode=EAGER @Entity class  NotaFiscal  {    …    @OneToMany(fetch=FetchType.EAGER)    List<Item>  itens; }Tuesday, August 7, 2012
  • 121. Hibernate executa 1 select List<NotaFiscal>  notas  =  dao.listaTudo(); select nf.*, i.* from NotaFiscal nf left outer join Item i on nf.id = i.nota_fiscal_idTuesday, August 7, 2012
  • 122. antes de definir um mapeamento global deste tipo você precisa se perguntar...Tuesday, August 7, 2012
  • 123. SEMPRE que uma nota é necessária, todos seus itens também são necessários?Tuesday, August 7, 2012
  • 124. não?Tuesday, August 7, 2012
  • 125. Utilizando Join Fetch session    .createQuery("from  NotaFiscal  n   left  join  fetch  n.itens")    .list();  Tuesday, August 7, 2012
  • 126. #2 batch-size nas associaçõesTuesday, August 7, 2012
  • 127. É o meio termo entre EAGER e LAZYTuesday, August 7, 2012
  • 128. @BatchSize @Entity class  NotaFiscal  {    …    @OneToMany    @BatchSize(size=10)    List<Item>  itens; }Tuesday, August 7, 2012
  • 129. Hibernate executa n/10+1 selects List<NotaFiscal>  notas  =  dao.listaTudo(); select nf.* from NotaFiscal nf for  (NotaFiscal  nf  :  notas)  {        processaItensDaNota(nf); } select i.* from Item i where i.nota_fiscal_id in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) select i.* from Item i where i.nota_fiscal_id in (?, ?, ?, ?, ?)Tuesday, August 7, 2012
  • 130. @BatchSize também é conhecido como:Tuesday, August 7, 2012
  • 131. @BatchSize também é conhecido como: otimização de adivinhação cega (blind-guess optimization)Tuesday, August 7, 2012
  • 132. @BatchSize também é conhecido como: otimização de adivinhação cega (blind-guess optimization) ou seja, é um palpiteTuesday, August 7, 2012
  • 133. #3 FetchMode SUBSELECTTuesday, August 7, 2012
  • 134. SUBSELECT @Entity class  NotaFiscal  {    …    @OneToMany    @Fetch(FetchMode.SUBSELECT)    List<Item>  itens; }Tuesday, August 7, 2012
  • 135. Hibernate executa 2 selects List<NotaFiscal>  notas  =  dao.listaTudo(); select nf.* from NotaFiscal nf for  (NotaFiscal  nf  :  notas)  {        processaItensDaNota(nf); } select i.* from Item i where i.nota_fiscal_id in (select nf.id from NotaFiscal nf)Tuesday, August 7, 2012
  • 136. Qual utilizar?Tuesday, August 7, 2012
  • 137. Qual utilizar? dependeTuesday, August 7, 2012
  • 138. #6 Processamento em loteTuesday, August 7, 2012
  • 139. Imagine que temos que importar 100k produtos para o banco de dadosTuesday, August 7, 2012
  • 140. 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();Tuesday, August 7, 2012
  • 141. em ~50k produtos nós receberíamos um OutOfMemoryExceptionTuesday, August 7, 2012
  • 142. por que?Tuesday, August 7, 2012
  • 143. Hibernate faz cache de todas as instâncias dos Produtos inseridos na SessionTuesday, August 7, 2012
  • 144. mas como melhorar?Tuesday, August 7, 2012
  • 145. 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();Tuesday, August 7, 2012
  • 146. evitamos o OutOfMemoryExceptionTuesday, August 7, 2012
  • 147. evitamos o OutOfMemoryException Mas o processamento ainda continua lento!Tuesday, August 7, 2012
  • 148. evitamos o OutOfMemoryException Mas o processamento ainda continua lento! Dá pra melhorar?Tuesday, August 7, 2012
  • 149. JDBC puro?Tuesday, August 7, 2012
  • 150. JDBC puro? código de maxu! Handerson FrotaTuesday, August 7, 2012
  • 151. StatelessSessionTuesday, August 7, 2012
  • 152. API mais baixo nível próxima ao jdbc sem 1st Level Cache mapeamento básico sem 2nd Level Cache StatelessSession sem cascade sem dirty-checking Collections são ignorados sem modelo de sem interceptors eventosTuesday, August 7, 2012
  • 153. 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();Tuesday, August 7, 2012
  • 154. menos consumo de memória e mais rápida!Tuesday, August 7, 2012
  • 155. dá pra melhorar? Yuri Adams menos consumo de memória e mais rápida!Tuesday, August 7, 2012
  • 156. hibernate.properties hibernate.jdbc.batch_size=50Tuesday, August 7, 2012
  • 157. CONCLUSÃOTuesday, August 7, 2012
  • 158. Foi apenas a ponta o iceberg!Tuesday, August 7, 2012
  • 159. cada uma destas dicas são simples, mas requerem mais estudoTuesday, August 7, 2012
  • 160. cada uma destas dicas são simples, mas requerem mais estudo pois depende do projetoTuesday, August 7, 2012
  • 161. um DBA certamente pode ter ajudar em muitos cenáriosTuesday, August 7, 2012
  • 162. Hibernate não é seu inimigo, deixem de #mimimiTuesday, August 7, 2012
  • 163. Rafael Ponte rponte@triadworks.com.brTuesday, August 7, 2012

×