2

Introduction

I have a JavaEE Application which consists in a RESTFul Web Service. This WS is responsible to receive some requests and answer with XMLs. There are services to store and services to capture information of a MySQL DB.
The system was done using APIs like JAX-WS and JAX-B and the framework Hibernate for data persistence.

Problem

When I update, delete or insert anything in my DB, directly or through a service of the WS, and try to see the result through a service, the differences doesn't appears unless I restart my WS.

Possibility

I believe it's about Hibernate caching but I didn't find anything that help me to fix it.

Does anybody already had this problem? Any idea?

hibernate.cfg.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/context_server</property>
    <property name="hibernate.connection.username">user</property>
    <property name="hibernate.connection.password"></property>

    <mapping class="br.marcelo.bean.CsMediaAudio"/>
    <mapping class="br.marcelo.bean.CsMediaImage"/>
    <mapping class="br.marcelo.bean.CsMediaVideo"/>
    <mapping class="br.marcelo.bean.CsContext"/>
    <mapping class="br.marcelo.bean.CsMedia"/>
    <mapping class="br.marcelo.bean.CsResource"/>
    <mapping class="br.marcelo.bean.CsUser"/>
  </session-factory>
</hibernate-configuration>

An service to Get informations:

@GET
@Path("/getResourceByIdXML/{id}")
@Produces(MediaType.APPLICATION_XML)
public CsResource getResourceByIdXML(@PathParam("id")Long id) {     
    return new DAOResource().find(id);
}

Class: DAOResource with find method used above:

public class DAOResource extends DAOGenerics<CsResource, Long> {
    private final Session s;

    public DAOResource()
    {
        s = HibernateSessionFactory.getSession();
    }

    @Override
    public CsResource find(Long id) {
       try {
            s.flush();
            s.clear();
            String sql = "from CsResource where id = :id";
            Query qr = s.createQuery(sql);
            qr.setParameter("id", id);

            return (CsResource) qr.uniqueResult();

        }catch(HibernateException e){
            System.out.println(e);
            return null;
        } finally {
            s.close();
        }
    }
}

HibernateSessionFactory class with getSession method used above:

public class HibernateSessionFactory {

    private static SessionFactory sf;
    static
    {
        try
        {
            sf = new AnnotationConfiguration().configure("hibernate.cfg.xml").buildSessionFactory();
        }
        catch (Exception erro)
        {
            System.err.println(erro);
            sf = null;
        }
    }

    public static Session getSession()
    {
        return sf.openSession();
    }


    public static Connection getConnection(){

        try {
            SessionFactoryImplementor sessionFactoryImplementation = (SessionFactoryImplementor) sf;
            ConnectionProvider connectionProvider = (ConnectionProvider)sessionFactoryImplementation.getConnectionProvider();

            java.sql.Connection connection = connectionProvider.getConnection();            

            return connection;
        } catch (SQLException ex) {
            Logger.getLogger(HibernateSessionFactory.class.getName()).log(Level.SEVERE, null, ex);
        }

        return null;
    }

}

EDIT:

DAOGenerics class with call of flush() and clear() methods

public abstract class DAOGenerics<K, G> {

    private final Session s;

    public DAOGenerics()
    {
        s = HibernateSessionFactory.getSession();
    } 

    public abstract K buscar(G obj);

    public abstract List<K> buscarTodos();

    public boolean inserir(K obj){
        try {
            s.flush();
            s.clear();
            s.getTransaction().begin();
            s.saveOrUpdate(obj);                
            s.getTransaction().commit();
            s.close();
            return true;
        }
        catch (HibernateException erro){

            System.out.println(erro.getMessage());
            s.flush();
            s.clear();
            s.getTransaction().rollback();
            s.close();
            return false;
        }

    }

    public void apagar(K obj) {
        try {
            apagar(obj, s);
        } finally {
            s.flush();
            s.clear();
            s.close();
        }
    }

    public void apagar(K obj, Session s) {

        try {
            s.flush();
            s.clear();
            s.getTransaction().begin();
            s.delete(obj);                
            s.getTransaction().commit();
        }
        catch (HibernateException erro){
            System.out.println(erro);
            s.flush();
            s.clear();
            s.getTransaction().rollback();
        }finally{
            s.close();
        }
    }


}
Marcelo Machado
  • 1,179
  • 2
  • 13
  • 33

1 Answers1

0

Yes, if you change something outside the "view" of hibernate, the hibernate caching does not realize that. So 2 options:

  • Use hibernate for your deletes/updates etc: This will take care that hibernate stays in sync and performance is the same as it is right now;
  • use clear or use stateless sessions: See org.hibernate.Session.clear() considered Harmful? for more details on that.
Community
  • 1
  • 1
Norbert
  • 6,026
  • 3
  • 17
  • 40
  • I already use deletes/updates with hibernate, but this doesn't solve the problem first because the same problem happens and because is normal to change things on DB directly for tests. I already have on my DAO classes the flush method, but the problem persistes. I will edite my post showing the flush call. – Marcelo Machado Sep 19 '15 at 07:12
  • Flush is for writes, clear is: Bye bye cache. Can you test the clear? – Norbert Sep 19 '15 at 15:59
  • unfortunally I tested and didn't work, I edited my question with the test – Marcelo Machado Sep 20 '15 at 18:48
  • Flush & clear should not be within transactions: You are emptying your query cache before commit. Can you move it outside the transaction? – Norbert Sep 21 '15 at 01:17
  • Done, but still nothing. – Marcelo Machado Sep 21 '15 at 05:33