HIbernate deve refazer consulta no BD

9 respostas
joaoorso

Boa tarde.
Bem primeiramente quero pedir desculpas ao moderador caso esteja duplicando o assunto; mas pesquisei e não encontrei o que procurava.
tenho uma consulta em SQL nativo executada da sequinte forma :

@SuppressWarnings("unchecked")
	public static String getParametro(String sigla) throws EsferaException {
			
			Session session = null;
			StringBuilder sql = new StringBuilder();
			sql.append("select valor005 from t005parametro where sigla005 = '" +sigla+ "'; \n");
			
			try {			
				session = HibernateUtil.getSession();			
				Object o = session.createSQLQuery(sql.toString()).uniqueResult();
				
				if(o== null){
					return null;					
				}
				else{
					return o.toString();
				}
				
			} catch (Exception e) {
				throw new EsferaException
					(EsferaException.getMsg(e));
			} finally {
				session.close();
			}	
		
	}

O que acontece é que a tabela t005parametro é alterada por um outro sistema; o hibernate não refaz a consulta e pega as informções de seu cache. O que resulta em informações inconsistentes .

Algém sabe como resolver isso ?
Agradeço a todos que responderem.

9 Respostas

joaoorso

Pessoal … será que deu pra entender o que escrevi ?
Eu quero obrigar o hibernate a fazer a consulta no BD novamente.
Não quero que ele faça a busca dos dados no cache como está ocorrendo.

renanreismartins

deu sim amigo, achei interessante seu problema, até procurei rapidamente por uma solucao. sei q o hibernate tem cache de 1o e 2o nivel, bem como query cache… estou acompanhando o topico, vou estudar sobre o assunto caso encontre solucao eu posto aqui.

se vc encontrar, por favor compartilhe

abrassss

emanuelCruz

Tenta isto:

@SuppressWarnings("unchecked")
	public static String getParametro(String sigla) throws EsferaException {
			
			Session session = null;
			StringBuilder sql = new StringBuilder();
			sql.append("select valor005 from t005parametro where sigla005 = '" +sigla+ "'; \n");
			
			try {			
				session = HibernateUtil.getSession();			
				Query query = session.createSQLQuery(sql.toString());
                               //nao pesquisa no cache, vai direto ao banco
                               query.setCacheMode(CacheMode.IGNORE);
                                
                               Object o = query.uniqueResult();
				
				if(o== null){
					return null;					
				}
				else{
					return o.toString();
				}
				
			} catch (Exception e) {
				throw new EsferaException
					(EsferaException.getMsg(e));
			} finally {
				session.close();
			}	
		
	}
joaoorso

Não … não Rolou
Implementei esse método com conexão via JDBC (sem usar o Hibernate); só assim consegui fazer funcionar direito.
O ruim é que agora fiquei com duas formas de conexão com o banco no projeto
POG… mas deu certo.

acho que o

query.setCacheMode(CacheMode.IGNORE);

deve apenas desabilitar o cache de segundo nível

assim como essas linhas que vão no hibernate.cfg.xml

<property name="cache.provider_class">
org.hibernate.cache.NoCacheProvider</property>

eu acho … :roll:

joaoorso

Bem … Vamos Reviver o tópico que a situação é parecida.
Tem uma classe que por motivo de força maior eu faço um insert na mão assim :

try {
session = HibernateUtil.getSession();
transaction = session.beginTransaction();

session.createSQLQuery(getSQLInserirBem()
						.toString()).executeUpdate();
transaction.commit();

} finally {
			session.close();
		}

e também faço um select na mão assim

List<Object> list = session.createSQLQuery(sql.toString()).list();

O problema é que as vezes quando depois de alterar um bem , vou consulta-lo novamente e ele aparece desatualizado.
Provavelmente devido ao cache do hibernate .
Alguém já passou por isso ?
Se o hibernate não identifica um insert ou update feito na mão . Por qual motivo ele permite que eu o faça ?

renanreismartins

amigo acredito que se vc chamar o metodo clear() do obj session de certo

abrassss

B

O hibernate identifica o comando, porém fica esperando por outro para que os execute todos de uma vez.
A sessão do hibernate é o cache de primeiro nível, que faz o que eu disse acima.

transaction.commit();   
session.close();

Este código não está funcionando como deveria. Ao fechar a sessão, o hibernate executaria todos os comandos pendentes na sessão na base de dados. Provavelmente é alguma falha no seu HibernateUtil.

agodinho

Estou com um problema semelhante, contudo em uma view. Tenho definido duas entidades, a tabela principal e uma view em cima dessa tabela.
tentei session.evict( MinhaClasse.class) e até o clear e nada, volta sempre o resultado do cache.

achei uma property para o hibernate cfg mas ela desabilita TODO o cache do sistema e isso pode impactar na performance da app.

achei no google isso, http://docs.jboss.org/hibernate/stable/core/reference/en/html/batch.html#batch-statelesssession, que nada mais é que fazer o acesso direto ao banco com o hibernate.

Ainda tentando fazer essa coisa funcionar …
Que saudades do iBates.

Woody

agodinho
Funcionou de primeira.
public List&lt; Serializable &gt; getPayments( //
      final Integer year, //
      final Integer month, //
      final List&lt; Integer &gt; idSites ) throws DAOException
   {
      try {
         /*
          * 11.1.4 Common issues 
          * @see http://docs.jboss.org/hibernate/stable/core/reference/en/html/transactions.html#transactions-basics-issues
          * @see http://docs.jboss.org/hibernate/stable/core/reference/en/html/batch.html#batch-statelesssession
          */
         final StatelessSession ss = HibernateUtils.getSessionFactory().openStatelessSession();

         final Criteria criteria = ss.createCriteria( ViewPayment.class );
         criteria.scroll( ScrollMode.FORWARD_ONLY );
         criteria.setLockMode( LockMode.NONE );
         criteria.setFetchSize( 1000 );

         criteria.add( Restrictions.eq( &quot;year&quot;, year ) );
         criteria.add( Restrictions.eq( &quot;month&quot;, month ) );
         if( idSites.size() &gt; 0 ) {
            criteria.add( Restrictions.in( &quot;idSite&quot;, idSites ) );
         }

         criteria.addOrder( Order.asc( &quot;year&quot; ) );
         criteria.addOrder( Order.asc( &quot;month&quot; ) );
         criteria.addOrder( Order.asc( &quot;idSite&quot; ) );

         log.info( criteria.toString() );

         return criteria.list();

      } catch( HibernateException e ) {
         throw new InternalBusinessException( &quot;Could not execute getPayments.'.&quot;, e );
      }
   }
Em vez do tradicional HibernateUtils.getCurrentSession() estou usando o perigoso HibernateUtils.getSessionFactory().openStatelessSession() - eu digo perigoso porquê se algum desavisado fizer copy and paste de um método desses e executar alguma mudança na base ele pode melar todo meu cache ne?

Só acho que o hibernate DEVERIA ter alguma configuração pra dizer que eu não quero cache para uma determinada entidade. (ele não tem mesmo?)

Woody

Criado 24 de junho de 2009
Ultima resposta 24 de ago. de 2009
Respostas 9
Participantes 5