Hibernate Efetivo (QCONSP-2012)
Upcoming SlideShare
Loading in...5
×
 

Hibernate Efetivo (QCONSP-2012)

on

  • 13,884 views

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.

Statistics

Views

Total Views
13,884
Views on SlideShare
8,074
Embed Views
5,810

Actions

Likes
32
Downloads
348
Comments
0

14 Embeds 5,810

http://www.rponte.com.br 5767
https://twitter.com 14
https://si0.twimg.com 10
http://digg.com 5
http://www.newsblur.com 2
http://www.freesafeip.com 2
https://twimg0-a.akamaihd.net 2
http://www.verious.com 2
https://www.google.com.br 1
http://cloud.feedly.com 1
http://webcache.googleusercontent.com 1
http://gogs.com.br 1
http://translate.googleusercontent.com 1
http://www.feedspot.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Hibernate Efetivo (QCONSP-2012) Hibernate Efetivo (QCONSP-2012) Presentation Transcript

  • Hibernate EFETIVO ERROS COMUNS E SOLUÇÕESTuesday, August 7, 2012
  • Eu estava me perguntando quando de fato o Hibernate foi criado...Tuesday, August 7, 2012
  • Eu estava me perguntando quando de fato o Hibernate foi criado... O “Boom” foi em 2003! Luca BastosTuesday, August 7, 2012
  • Quase uma década! 2012 - 2003 = 9Tuesday, August 7, 2012
  • mas ainda hoje...Tuesday, August 7, 2012
  • mas ainda hoje... existem devs que subutilizam o frameworkTuesday, August 7, 2012
  • mas ainda hoje... existem devs que subutilizam o framework problemas de perfomance e escalabilidadeTuesday, August 7, 2012
  • e pra piorar...Tuesday, August 7, 2012
  • culpam o HibernateTuesday, August 7, 2012
  • culpam o Hibernate A culpa é do Banco de Dados! SérgioTuesday, August 7, 2012
  • é fácil culpar o que não se conhece...Tuesday, August 7, 2012
  • um SGDB mal configurado pode ser o problema...Tuesday, August 7, 2012
  • um SGDB mal configurado pode ser o problema... MAS na maioria das vezes o problema está na SUA APLICAÇÃOTuesday, August 7, 2012
  • tabelas sem índices <3Tuesday, August 7, 2012
  • tabelas sem índices consultas mal-feitas <3 <3Tuesday, August 7, 2012
  • tabelas sem índices consultas mal-feitas muitos hits ao bancoTuesday, August 7, 2012 <3 <3 <3
  • tabelas sem índices consultas mal-feitas muitos hits ao banco connection leaksTuesday, August 7, 2012 <3 <3 <3
  • tabelas sem índices consultas mal-feitas muitos hits ao banco connection leaks memory leaksTuesday, August 7, 2012 <3 <3 <3
  • Não saber tirar proveito frameworkTuesday, August 7, 2012
  • Hibernate Efetivo 6 dicas para não deixar sua app morrerTuesday, August 7, 2012
  • @rponteTuesday, August 7, 2012
  • Tuesday, August 7, 2012
  • Fortaleza - Terra do SolTuesday, August 7, 2012
  • #1 POOL DE CONEXÕESTuesday, August 7, 2012
  • com certeza todos aqui já ouviram falar...Tuesday, August 7, 2012
  • mas nem todos dão a devida atenção...Tuesday, August 7, 2012
  • mas nem todos dão a devida atenção... até perceberem a app engasgandoTuesday, August 7, 2012
  • mas nem todos dão a devida atenção... até perceberem a app engasgando ou até receberem umTuesday, August 7, 2012
  • 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
  • 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
  • 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
  • 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
  • a app volta a funcionar bem por um tempoTuesday, August 7, 2012
  • a app volta a funcionar bem por um tempoTuesday, August 7, 2012
  • e vão alocando mais conexões com o tempo hibernate.properties hibernate.connection.pool_size=30                                                              40                                                              55                                                              70                                                            ...Tuesday, August 7, 2012
  • o pool PADRÃO do HibernateTuesday, August 7, 2012
  • que possui uma impl. RUDIMENTARTuesday, August 7, 2012
  • INFO DriverManagerConnectionProvider:64 - Using Hibernate built-in connection pool (not for production use!) INFO DriverManagerConnectionProvider:65 - Hibernate connection pool size: 20Tuesday, August 7, 2012
  • 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
  • qual pool utilizar?Tuesday, August 7, 2012
  • temos ótimas opções...Tuesday, August 7, 2012
  • temos ótimas opções... pools como c3p0 ou commons-dbcpTuesday, August 7, 2012
  • o Hibernate já vem com c3p0Tuesday, August 7, 2012
  • 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
  • ou melhor ainda...Tuesday, August 7, 2012
  • 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
  • Pool traz melhoria de performanceTuesday, August 7, 2012
  • Pool traz melhoria de performance mas não faz milagresTuesday, August 7, 2012
  • #2 lidando com LazyInitialization ExceptionTuesday, August 7, 2012
  • quando e por que acontece?Tuesday, August 7, 2012
  • @Entity class  NotaFiscal  {    …    @OneToMany    List<Item>  itens; }Tuesday, August 7, 2012
  • Percorrendo os itens de uma nota NotaFiscal  nf  =  (NotaFiscal)  session.load (NotaFiscal.class,  42); List<Item>  itens  =  nf.getItens();Tuesday, August 7, 2012
  • 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
  • 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
  • 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
  • resolver parece fácil, certo?Tuesday, August 7, 2012
  • 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
  • Mas e quando estamos trabalhando na Web?Tuesday, August 7, 2012
  • 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
  • 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
  • e agora? #comofasTuesday, August 7, 2012
  • e agora? #comofas passa tudo pra EAGER! ;D SérgioTuesday, August 7, 2012
  • @Entity class  NotaFiscal  {    …    @OneToMany(fetch=FetchType.EAGER)    List<Item>  itens; }Tuesday, August 7, 2012
  • 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
  • mas isso poderia gerar uma sobrecarga...Tuesday, August 7, 2012
  • mas isso poderia gerar uma sobrecarga... pois os itens da nota não são necessários em muitos lugaresTuesday, August 7, 2012
  • lembre-se que ter os relacionamentos como LAZY é uma boa práticaTuesday, August 7, 2012
  • como evitar LIE sem modificar o relacionamento para EAGER?Tuesday, August 7, 2012
  • Open Session In ViewTuesday, August 7, 2012
  • 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
  • o OSIV só evita LIE no mesmo request!Tuesday, August 7, 2012
  • anti-pattern?Tuesday, August 7, 2012
  • #3 Second Level CacheTuesday, August 7, 2012
  • Carregando uma nota por ID NotaFiscal  nf  =  (NotaFiscal)  session.load (NotaFiscal.class,  42);Tuesday, August 7, 2012
  • Session Banco de DadosTuesday, August 7, 2012
  • First Level Cache Session Banco de DadosTuesday, August 7, 2012
  • Session Session Session Session Banco de DadosTuesday, August 7, 2012
  • Session Session Session Session Second Level Cache Banco de DadosTuesday, August 7, 2012
  • First Level Cache Session Session Session Session Second Level Cache Banco de DadosTuesday, August 7, 2012
  • Session Session Session Session SessionFactory Banco de DadosTuesday, August 7, 2012
  • Configurar é simplesTuesday, August 7, 2012
  • #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
  • #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
  • Caching Strategy @Cache( usage=CacheConcurrencyStrategy.READ_WRITE) READ_ONLY NONSTRICT_READ_WRITE READ_WRITETuesday, August 7, 2012
  • Caching Strategy @Cache( usage=CacheConcurrencyStrategy.READ_WRITE) READ_ONLY Melhor performance NONSTRICT_READ_WRITE READ_WRITETuesday, August 7, 2012
  • Caching Strategy @Cache( usage=CacheConcurrencyStrategy.READ_WRITE) READ_ONLY NONSTRICT_READ_WRITE Dados não críticos READ_WRITETuesday, August 7, 2012
  • Caching Strategy @Cache( usage=CacheConcurrencyStrategy.READ_WRITE) READ_ONLY NONSTRICT_READ_WRITE READ_WRITE Modificações frequentesTuesday, August 7, 2012
  • 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
  • Como 2nd Level Cache funciona?Tuesday, August 7, 2012
  • 2nd Level Cache não faz cache das instancias das entidadesTuesday, August 7, 2012
  • 2nd Level Cache não faz cache das instancias das entidades somente dos valores das propriedadesTuesday, August 7, 2012
  • @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
  • 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
  • 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
  • 2nd Level Cache não faz cache das associaçõesTuesday, August 7, 2012
  • @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
  • 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
  • Devo cachear todas as minhas entidades?Tuesday, August 7, 2012
  • Com 2nd Level Cache tudo funciona bem enquanto buscamos por ID... session.load(Issue.class,  17);Tuesday, August 7, 2012
  • 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
  • #4 Query CacheTuesday, August 7, 2012
  • Query Cache faz cache do resultado de uma queryTuesday, August 7, 2012
  • Configurando Hibernate para usar Query Cache hibernate.properties hibernate.cache.use_query_cache=trueTuesday, August 7, 2012
  • Query Cache session    .createQuery("from  Issue  where  status  =  ?")    .setString(0,  status)    .setCacheable(true)    .list();  Tuesday, August 7, 2012
  • modelo conceitual do query cache Query Cache [“from Issue where status = ?”, [“ABERTA”]] -> [17, 19]Tuesday, August 7, 2012
  • modelo conceitual do query cache Query Cache [“from Issue where status = ?”, [“ABERTA”]] -> [17, 19] Query + Parâmetros IDsTuesday, August 7, 2012
  • por isso Query Cache SEM 2nd Level Cache não é de muita ajudaTuesday, August 7, 2012
  • Utilize somente em consultas que são executadas repetidas vezes com os mesmos parâmetrosTuesday, August 7, 2012
  • Utilize somente em consultas que são executadas repetidas vezes com os mesmos parâmetrosTuesday, August 7, 2012
  • #5 Select n+1Tuesday, August 7, 2012
  • o campeão em prejudicar a performance da aplicaçãoTuesday, August 7, 2012
  • Processando os itens de uma nota NotaFiscal  nf  =  (NotaFiscal)  session.load (NotaFiscal.class,  42); processaItensDaNota(nf);Tuesday, August 7, 2012
  • 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
  • Processando os itens de varias notas List<NotaFiscal>  notas  =  dao.listaTudo(); for  (NotaFiscal  nf  :  notas)  {        processaItensDaNota(nf); }Tuesday, August 7, 2012
  • 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
  • são muitos hits no banco de dadosTuesday, August 7, 2012
  • são muitos hits no banco de dados mas podemos resolver isso...Tuesday, August 7, 2012
  • 3 soluçõesTuesday, August 7, 2012
  • #1 EAGER ou join- fetchTuesday, August 7, 2012
  • Utilizando FetchMode=EAGER @Entity class  NotaFiscal  {    …    @OneToMany(fetch=FetchType.EAGER)    List<Item>  itens; }Tuesday, August 7, 2012
  • 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
  • antes de definir um mapeamento global deste tipo você precisa se perguntar...Tuesday, August 7, 2012
  • SEMPRE que uma nota é necessária, todos seus itens também são necessários?Tuesday, August 7, 2012
  • não?Tuesday, August 7, 2012
  • Utilizando Join Fetch session    .createQuery("from  NotaFiscal  n   left  join  fetch  n.itens")    .list();  Tuesday, August 7, 2012
  • #2 batch-size nas associaçõesTuesday, August 7, 2012
  • É o meio termo entre EAGER e LAZYTuesday, August 7, 2012
  • @BatchSize @Entity class  NotaFiscal  {    …    @OneToMany    @BatchSize(size=10)    List<Item>  itens; }Tuesday, August 7, 2012
  • 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
  • @BatchSize também é conhecido como:Tuesday, August 7, 2012
  • @BatchSize também é conhecido como: otimização de adivinhação cega (blind-guess optimization)Tuesday, August 7, 2012
  • @BatchSize também é conhecido como: otimização de adivinhação cega (blind-guess optimization) ou seja, é um palpiteTuesday, August 7, 2012
  • #3 FetchMode SUBSELECTTuesday, August 7, 2012
  • SUBSELECT @Entity class  NotaFiscal  {    …    @OneToMany    @Fetch(FetchMode.SUBSELECT)    List<Item>  itens; }Tuesday, August 7, 2012
  • 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
  • Qual utilizar?Tuesday, August 7, 2012
  • Qual utilizar? dependeTuesday, August 7, 2012
  • #6 Processamento em loteTuesday, August 7, 2012
  • Imagine que temos que importar 100k produtos para o banco de dadosTuesday, August 7, 2012
  • 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
  • em ~50k produtos nós receberíamos um OutOfMemoryExceptionTuesday, August 7, 2012
  • por que?Tuesday, August 7, 2012
  • Hibernate faz cache de todas as instâncias dos Produtos inseridos na SessionTuesday, August 7, 2012
  • mas como melhorar?Tuesday, August 7, 2012
  • 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
  • evitamos o OutOfMemoryExceptionTuesday, August 7, 2012
  • evitamos o OutOfMemoryException Mas o processamento ainda continua lento!Tuesday, August 7, 2012
  • evitamos o OutOfMemoryException Mas o processamento ainda continua lento! Dá pra melhorar?Tuesday, August 7, 2012
  • JDBC puro?Tuesday, August 7, 2012
  • JDBC puro? código de maxu! Handerson FrotaTuesday, August 7, 2012
  • StatelessSessionTuesday, August 7, 2012
  • 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
  • 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
  • menos consumo de memória e mais rápida!Tuesday, August 7, 2012
  • dá pra melhorar? Yuri Adams menos consumo de memória e mais rápida!Tuesday, August 7, 2012
  • hibernate.properties hibernate.jdbc.batch_size=50Tuesday, August 7, 2012
  • CONCLUSÃOTuesday, August 7, 2012
  • Foi apenas a ponta o iceberg!Tuesday, August 7, 2012
  • cada uma destas dicas são simples, mas requerem mais estudoTuesday, August 7, 2012
  • cada uma destas dicas são simples, mas requerem mais estudo pois depende do projetoTuesday, August 7, 2012
  • um DBA certamente pode ter ajudar em muitos cenáriosTuesday, August 7, 2012
  • Hibernate não é seu inimigo, deixem de #mimimiTuesday, August 7, 2012
  • Rafael Ponte rponte@triadworks.com.brTuesday, August 7, 2012