Search code examples
javatransactionshibernate-session

Should I commit hibernate transaction before calling session.evict(obj)


When should I commit a transaction in hibernate after saving it. Is it before or after I call session.evict(obj). Currently my code looks like this(only required parts).

Session session = connector.getSession();
Transaction tx = session.beginTransaction();
try {
        Criteria crit = session.createCriteria(ST_CODE_SETTINGS_STORE.class).add(Restrictions.eq("TYPE", "issueno"));
        List<ST_CODE_SETTINGS_STORE> ls = crit.list();
        if (ls.size() < 1) {
            session.save(st_code_settings_store);
            session.evict(st_code_settings_store);
            msg = "insert";
        } 
        else {
            Long Id = null;
            ST_CODE_SETTINGS_STORE st_code_settings_store1 = ls.get(0);
            Id = st_code_settings_store1.getCODE_ID();

            Object o = session.get(ST_CODE_SETTINGS_STORE.class, Id);
            ST_CODE_SETTINGS_STORE update = (ST_CODE_SETTINGS_STORE) o;
            session.update(update);
        }
        tx.commit();
    } catch (Exception e) {
        if (tx != null) {
            tx.rollback();
        }
        System.out.println("Error: " + e.getMessage());
        connector.printStack(e);
        throw e;
    } finally {
        session.close();
    }

Sometimes if I commit after evicting, the data does not get saved in the database. Is it the right way to code??


Solution

  • The method evict() removes a single object from Session cache. So before you call evict() the object should be there in the Session cache. Therefore if you save the object first time, you have to save the object via Session.save(object). Subsequent update calls should follow through session.saveOrUpdate(object) or session.update(object) before calling evict() to remove the loaded object from the cache.(reference )

    From Hibernate Docs

    Ending a Session usually involves four distinct phases:

    • flush the session
    • commit the transaction
    • close the session
    • handle exceptions

    Do not use the anti-patterns session-per-user-session or session-per-application (there are, however, rare exceptions to this rule). Some of the following issues might also arise within the recommended patterns, so ensure that you understand the implications before making a design decision:

    • A Session is not thread-safe. Things that work concurrently, like HTTP requests, session beans, or Swing workers, will cause race conditions if a Session instance is shared. If you keep your Hibernate Session in your HttpSession (this is discussed later in the chapter), you should consider synchronizing access to your Http session. Otherwise, a user that clicks reload fast enough can use the same Session in two concurrently running threads.

    • An exception thrown by Hibernate means you have to rollback your database transaction and close the Session immediately (this is discussed in more detail later in the chapter). If your Session is bound to the application, you have to stop the application. Rolling back the database transaction does not put your business objects back into the state they were at the start of the transaction. This means that the database state and the business objects will be out of sync. Usually this is not a problem, because exceptions are not recoverable and you will have to start over after rollback anyway.

    • The Session caches every object that is in a persistent state (watched and checked for dirty state by Hibernate). If you keep it open for a long time or simply load too much data, it will grow endlessly until you get an OutOfMemoryException. One solution is to call clear() and evict() to manage the Session cache, but you should consider a Stored Procedure if you need mass data operations.