Hibernate Efetivo (QCONSP-2012)

15,946
-1

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 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
15,946
On Slideshare
0
From Embeds
0
Number of Embeds
10
Actions
Shares
0
Downloads
369
Comments
0
Likes
34
Embeds 0
No embeds

No notes for slide

Hibernate Efetivo (QCONSP-2012)

  1. 1. Hibernate EFETIVO ERROS COMUNS E SOLUÇÕESTuesday, August 7, 2012
  2. 2. Eu estava me perguntando quando de fato o Hibernate foi criado...Tuesday, August 7, 2012
  3. 3. Eu estava me perguntando quando de fato o Hibernate foi criado... O “Boom” foi em 2003! Luca BastosTuesday, August 7, 2012
  4. 4. Quase uma década! 2012 - 2003 = 9Tuesday, August 7, 2012
  5. 5. mas ainda hoje...Tuesday, August 7, 2012
  6. 6. mas ainda hoje... existem devs que subutilizam o frameworkTuesday, August 7, 2012
  7. 7. mas ainda hoje... existem devs que subutilizam o framework problemas de perfomance e escalabilidadeTuesday, August 7, 2012
  8. 8. e pra piorar...Tuesday, August 7, 2012
  9. 9. culpam o HibernateTuesday, August 7, 2012
  10. 10. culpam o Hibernate A culpa é do Banco de Dados! SérgioTuesday, August 7, 2012
  11. 11. é fácil culpar o que não se conhece...Tuesday, August 7, 2012
  12. 12. um SGDB mal configurado pode ser o problema...Tuesday, August 7, 2012
  13. 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. 14. tabelas sem índices <3Tuesday, August 7, 2012
  15. 15. tabelas sem índices consultas mal-feitas <3 <3Tuesday, August 7, 2012
  16. 16. tabelas sem índices consultas mal-feitas muitos hits ao bancoTuesday, August 7, 2012 <3 <3 <3
  17. 17. tabelas sem índices consultas mal-feitas muitos hits ao banco connection leaksTuesday, August 7, 2012 <3 <3 <3
  18. 18. tabelas sem índices consultas mal-feitas muitos hits ao banco connection leaks memory leaksTuesday, August 7, 2012 <3 <3 <3
  19. 19. Não saber tirar proveito frameworkTuesday, August 7, 2012
  20. 20. Hibernate Efetivo 6 dicas para não deixar sua app morrerTuesday, August 7, 2012
  21. 21. @rponteTuesday, August 7, 2012
  22. 22. Tuesday, August 7, 2012
  23. 23. Fortaleza - Terra do SolTuesday, August 7, 2012
  24. 24. #1 POOL DE CONEXÕESTuesday, August 7, 2012
  25. 25. com certeza todos aqui já ouviram falar...Tuesday, August 7, 2012
  26. 26. mas nem todos dão a devida atenção...Tuesday, August 7, 2012
  27. 27. mas nem todos dão a devida atenção... até perceberem a app engasgandoTuesday, August 7, 2012
  28. 28. mas nem todos dão a devida atenção... até perceberem a app engasgando ou até receberem umTuesday, August 7, 2012
  29. 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. 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. 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. 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. 33. a app volta a funcionar bem por um tempoTuesday, August 7, 2012
  34. 34. a app volta a funcionar bem por um tempoTuesday, August 7, 2012
  35. 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. 36. o pool PADRÃO do HibernateTuesday, August 7, 2012
  37. 37. que possui uma impl. RUDIMENTARTuesday, August 7, 2012
  38. 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. 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. 40. qual pool utilizar?Tuesday, August 7, 2012
  41. 41. temos ótimas opções...Tuesday, August 7, 2012
  42. 42. temos ótimas opções... pools como c3p0 ou commons-dbcpTuesday, August 7, 2012
  43. 43. o Hibernate já vem com c3p0Tuesday, August 7, 2012
  44. 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. 45. ou melhor ainda...Tuesday, August 7, 2012
  46. 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. 47. Pool traz melhoria de performanceTuesday, August 7, 2012
  48. 48. Pool traz melhoria de performance mas não faz milagresTuesday, August 7, 2012
  49. 49. #2 lidando com LazyInitialization ExceptionTuesday, August 7, 2012
  50. 50. quando e por que acontece?Tuesday, August 7, 2012
  51. 51. @Entity class  NotaFiscal  {    …    @OneToMany    List<Item>  itens; }Tuesday, August 7, 2012
  52. 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. 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. 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. 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. 56. resolver parece fácil, certo?Tuesday, August 7, 2012
  57. 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. 58. Mas e quando estamos trabalhando na Web?Tuesday, August 7, 2012
  59. 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. 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. 61. e agora? #comofasTuesday, August 7, 2012
  62. 62. e agora? #comofas passa tudo pra EAGER! ;D SérgioTuesday, August 7, 2012
  63. 63. @Entity class  NotaFiscal  {    …    @OneToMany(fetch=FetchType.EAGER)    List<Item>  itens; }Tuesday, August 7, 2012
  64. 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. 65. mas isso poderia gerar uma sobrecarga...Tuesday, August 7, 2012
  66. 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. 67. lembre-se que ter os relacionamentos como LAZY é uma boa práticaTuesday, August 7, 2012
  68. 68. como evitar LIE sem modificar o relacionamento para EAGER?Tuesday, August 7, 2012
  69. 69. Open Session In ViewTuesday, August 7, 2012
  70. 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. 71. o OSIV só evita LIE no mesmo request!Tuesday, August 7, 2012
  72. 72. anti-pattern?Tuesday, August 7, 2012
  73. 73. #3 Second Level CacheTuesday, August 7, 2012
  74. 74. Carregando uma nota por ID NotaFiscal  nf  =  (NotaFiscal)  session.load (NotaFiscal.class,  42);Tuesday, August 7, 2012
  75. 75. Session Banco de DadosTuesday, August 7, 2012
  76. 76. First Level Cache Session Banco de DadosTuesday, August 7, 2012
  77. 77. Session Session Session Session Banco de DadosTuesday, August 7, 2012
  78. 78. Session Session Session Session Second Level Cache Banco de DadosTuesday, August 7, 2012
  79. 79. First Level Cache Session Session Session Session Second Level Cache Banco de DadosTuesday, August 7, 2012
  80. 80. Session Session Session Session SessionFactory Banco de DadosTuesday, August 7, 2012
  81. 81. Configurar é simplesTuesday, August 7, 2012
  82. 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. 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. 84. Caching Strategy @Cache( usage=CacheConcurrencyStrategy.READ_WRITE) READ_ONLY NONSTRICT_READ_WRITE READ_WRITETuesday, August 7, 2012
  85. 85. Caching Strategy @Cache( usage=CacheConcurrencyStrategy.READ_WRITE) READ_ONLY Melhor performance NONSTRICT_READ_WRITE READ_WRITETuesday, August 7, 2012
  86. 86. Caching Strategy @Cache( usage=CacheConcurrencyStrategy.READ_WRITE) READ_ONLY NONSTRICT_READ_WRITE Dados não críticos READ_WRITETuesday, August 7, 2012
  87. 87. Caching Strategy @Cache( usage=CacheConcurrencyStrategy.READ_WRITE) READ_ONLY NONSTRICT_READ_WRITE READ_WRITE Modificações frequentesTuesday, August 7, 2012
  88. 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. 89. Como 2nd Level Cache funciona?Tuesday, August 7, 2012
  90. 90. 2nd Level Cache não faz cache das instancias das entidadesTuesday, August 7, 2012
  91. 91. 2nd Level Cache não faz cache das instancias das entidades somente dos valores das propriedadesTuesday, August 7, 2012
  92. 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. 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. 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. 95. 2nd Level Cache não faz cache das associaçõesTuesday, August 7, 2012
  96. 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. 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. 98. Devo cachear todas as minhas entidades?Tuesday, August 7, 2012
  99. 99. Com 2nd Level Cache tudo funciona bem enquanto buscamos por ID... session.load(Issue.class,  17);Tuesday, August 7, 2012
  100. 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. 101. #4 Query CacheTuesday, August 7, 2012
  102. 102. Query Cache faz cache do resultado de uma queryTuesday, August 7, 2012
  103. 103. Configurando Hibernate para usar Query Cache hibernate.properties hibernate.cache.use_query_cache=trueTuesday, August 7, 2012
  104. 104. Query Cache session    .createQuery("from  Issue  where  status  =  ?")    .setString(0,  status)    .setCacheable(true)    .list();  Tuesday, August 7, 2012
  105. 105. modelo conceitual do query cache Query Cache [“from Issue where status = ?”, [“ABERTA”]] -> [17, 19]Tuesday, August 7, 2012
  106. 106. modelo conceitual do query cache Query Cache [“from Issue where status = ?”, [“ABERTA”]] -> [17, 19] Query + Parâmetros IDsTuesday, August 7, 2012
  107. 107. por isso Query Cache SEM 2nd Level Cache não é de muita ajudaTuesday, August 7, 2012
  108. 108. Utilize somente em consultas que são executadas repetidas vezes com os mesmos parâmetrosTuesday, August 7, 2012
  109. 109. Utilize somente em consultas que são executadas repetidas vezes com os mesmos parâmetrosTuesday, August 7, 2012
  110. 110. #5 Select n+1Tuesday, August 7, 2012
  111. 111. o campeão em prejudicar a performance da aplicaçãoTuesday, August 7, 2012
  112. 112. Processando os itens de uma nota NotaFiscal  nf  =  (NotaFiscal)  session.load (NotaFiscal.class,  42); processaItensDaNota(nf);Tuesday, August 7, 2012
  113. 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. 114. Processando os itens de varias notas List<NotaFiscal>  notas  =  dao.listaTudo(); for  (NotaFiscal  nf  :  notas)  {        processaItensDaNota(nf); }Tuesday, August 7, 2012
  115. 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. 116. são muitos hits no banco de dadosTuesday, August 7, 2012
  117. 117. são muitos hits no banco de dados mas podemos resolver isso...Tuesday, August 7, 2012
  118. 118. 3 soluçõesTuesday, August 7, 2012
  119. 119. #1 EAGER ou join- fetchTuesday, August 7, 2012
  120. 120. Utilizando FetchMode=EAGER @Entity class  NotaFiscal  {    …    @OneToMany(fetch=FetchType.EAGER)    List<Item>  itens; }Tuesday, August 7, 2012
  121. 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. 122. antes de definir um mapeamento global deste tipo você precisa se perguntar...Tuesday, August 7, 2012
  123. 123. SEMPRE que uma nota é necessária, todos seus itens também são necessários?Tuesday, August 7, 2012
  124. 124. não?Tuesday, August 7, 2012
  125. 125. Utilizando Join Fetch session    .createQuery("from  NotaFiscal  n   left  join  fetch  n.itens")    .list();  Tuesday, August 7, 2012
  126. 126. #2 batch-size nas associaçõesTuesday, August 7, 2012
  127. 127. É o meio termo entre EAGER e LAZYTuesday, August 7, 2012
  128. 128. @BatchSize @Entity class  NotaFiscal  {    …    @OneToMany    @BatchSize(size=10)    List<Item>  itens; }Tuesday, August 7, 2012
  129. 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. 130. @BatchSize também é conhecido como:Tuesday, August 7, 2012
  131. 131. @BatchSize também é conhecido como: otimização de adivinhação cega (blind-guess optimization)Tuesday, August 7, 2012
  132. 132. @BatchSize também é conhecido como: otimização de adivinhação cega (blind-guess optimization) ou seja, é um palpiteTuesday, August 7, 2012
  133. 133. #3 FetchMode SUBSELECTTuesday, August 7, 2012
  134. 134. SUBSELECT @Entity class  NotaFiscal  {    …    @OneToMany    @Fetch(FetchMode.SUBSELECT)    List<Item>  itens; }Tuesday, August 7, 2012
  135. 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. 136. Qual utilizar?Tuesday, August 7, 2012
  137. 137. Qual utilizar? dependeTuesday, August 7, 2012
  138. 138. #6 Processamento em loteTuesday, August 7, 2012
  139. 139. Imagine que temos que importar 100k produtos para o banco de dadosTuesday, August 7, 2012
  140. 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. 141. em ~50k produtos nós receberíamos um OutOfMemoryExceptionTuesday, August 7, 2012
  142. 142. por que?Tuesday, August 7, 2012
  143. 143. Hibernate faz cache de todas as instâncias dos Produtos inseridos na SessionTuesday, August 7, 2012
  144. 144. mas como melhorar?Tuesday, August 7, 2012
  145. 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. 146. evitamos o OutOfMemoryExceptionTuesday, August 7, 2012
  147. 147. evitamos o OutOfMemoryException Mas o processamento ainda continua lento!Tuesday, August 7, 2012
  148. 148. evitamos o OutOfMemoryException Mas o processamento ainda continua lento! Dá pra melhorar?Tuesday, August 7, 2012
  149. 149. JDBC puro?Tuesday, August 7, 2012
  150. 150. JDBC puro? código de maxu! Handerson FrotaTuesday, August 7, 2012
  151. 151. StatelessSessionTuesday, August 7, 2012
  152. 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. 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. 154. menos consumo de memória e mais rápida!Tuesday, August 7, 2012
  155. 155. dá pra melhorar? Yuri Adams menos consumo de memória e mais rápida!Tuesday, August 7, 2012
  156. 156. hibernate.properties hibernate.jdbc.batch_size=50Tuesday, August 7, 2012
  157. 157. CONCLUSÃOTuesday, August 7, 2012
  158. 158. Foi apenas a ponta o iceberg!Tuesday, August 7, 2012
  159. 159. cada uma destas dicas são simples, mas requerem mais estudoTuesday, August 7, 2012
  160. 160. cada uma destas dicas são simples, mas requerem mais estudo pois depende do projetoTuesday, August 7, 2012
  161. 161. um DBA certamente pode ter ajudar em muitos cenáriosTuesday, August 7, 2012
  162. 162. Hibernate não é seu inimigo, deixem de #mimimiTuesday, August 7, 2012
  163. 163. Rafael Ponte rponte@triadworks.com.brTuesday, August 7, 2012

×