Difference between getCurrentSession () and openSession () implemented by Hibernate session in java in service

Source: Internet
Author: User
Tags commit log log rollback sessions throwable

When we use Hibernate as a class library for database operations, we generally write business logic in the DAO layer for database-related operations. However, if our project is relatively small, it is also possible to write transactions directly in the dao layer. This is an individual, and there is no special rule. However, if the project is relatively large, DAO should only perform database operations and write transactions to the service, that is, the entire business logic.

For example, the business logic requires you to add a user to the user table in the database and add a log to the log table. You need to call the two methods of DAO (the saveUser of UserDao and the saveLog of LogDao ). This is obviously a transaction, that is, if an operation encounters a problem, it is necessary to roll back to the initial state. So how to control transactions at the Service layer? This article describes the code in this example.

Problems with Session transactions in DAO

Let's look at the transaction that writes the Hibernate session in the DAO layer first.

Package com. xxg;
 
Import org. hibernate. SessionFactory;
Import org. hibernate. cfg. Configuration;
 
Public class HibernateUtil {
 
Private static final SessionFactory sessionFactory = buildSessionFactory ();
Private static SessionFactory buildSessionFactory (){
Try {
// Create the SessionFactory from hibernate. cfg. xml
Return new Configuration (). configure (). buildSessionFactory ();
        }
Catch (Throwable ex ){
// Make sure you log the exception, as it might be swallowed
System. err. println ("Initial SessionFactory creation failed." + ex );
Throw new ExceptionInInitializerError (ex );
        }
    }
Public static SessionFactory getSessionFactory (){
Return sessionFactory;
    }
}

Create the User table T_user (id, username) and Log table T_log (id, content), and their corresponding object class User, Log, and ing files. The code is not pasted here.


Public class UserDao {
 
Public void saveUser (User user ){
SessionFactory sessionFactory = HibernateUtil. getSessionFactory (); // get SessionFactory
Session session = sessionFactory. openSession (); // openSession
Session. beginTransaction (); // start the transaction
 
Session. save (user );
 
Session. getTransaction (). commit (); // transaction commit
Session. close (); // close the session
    }
}


Public class LogDao {
 
Public void saveLog (Log log ){
SessionFactory sessionFactory = HibernateUtil. getSessionFactory (); // get SessionFactory
Session session = sessionFactory. openSession (); // openSession
Session. beginTransaction (); // start the transaction
 
Session. save (log );
 
Session. getTransaction (). commit (); // transaction commit
Session. close (); // close the session
    }
 
}

Next, let's look at writing a business logic in the service.

Public class TestService {
 
Public void save (User user ){
UserDao userDao = new UserDao ();
UserDao. saveUser (user );
 
LogDao logDao = new LogDao ();
Log log = new Log ();
Log. setContent ("insert a user ");
LogDao. saveLog (log );
    }
 
}
We can see that we have written database transactions in two DAO statements, highlighted in the code, and session. beginTransaction () shows the beginning of the declared transaction.

This is not correct because these two tasks are performed as one transaction, and one transaction is successfully committed, and the other may fail to be committed, resulting in inconsistency, in this way, these two operations are not considered a transaction, so such writing is a failed transaction.

Therefore, we need to declare the transaction in the service.

Database transactions that write sessions at the service layer

In order to put transactions in the service, we need to change the code of HibernateUtil to implement it. Otherwise, the above one cannot meet our needs. In this new HibernateUtil code, the local variables in the ThreadLocal thread are used to save the hibernate session object. In this way, you can use the same session object in different classes without passing parameters.

Public class HibernateUtil {
Public static final ThreadLocal session = new ThreadLocal ();
 
Public static final SessionFactory sessionFactory;
Static {
Try {
SessionFactory = new Configuration (). configure (). buildSessionFactory ();
} Catch (Throwable ex ){
Throw new ExceptionInInitializerError (ex );
        }
    }
 
Public static Session currentSession () throws HibernateException
    {
Session s = session. get ();
If (s = null)
        {
S = sessionFactory. openSession ();
Session. set (s );
        }
Return (s );
    }
 
Public static void closeSession () throws HibernateException
    {
Session s = session. get ();
If (s! = Null)
        {
S. close ();
        }
Session. set (null );
    }
}

Next, we will place the transaction in the service. Check the code:


Public class TestService {
 
Public void save (User user ){
 
SessionFactory sessionFactory = HibernateUtil. getSessionFactory (); // get SessionFactory
Session session = sessionFactory. getCurrentSession (); // getCurrentSession
Session. beginTransaction (); // start the transaction
 
UserDao userDao = new UserDao ();
UserDao. saveUser (user );
 
LogDao logDao = new LogDao ();
Log log = new Log ();
Log. setContent ("insert a user ");
LogDao. saveLog (log );
Session. getTransaction (). commit (); // transaction commit
    }
 
}


Public class LogDao {
 
Public void saveLog (Log log) throws RuntimeException {
SessionFactory sessionFactory = HibernateUtil. getSessionFactory (); // get SessionFactory
Session session = sessionFactory. getCurrentSession (); // getCurrentSession
 
Session. save (log );
 
Throw new RuntimeException ();
    }
}


Public class UserDao {
 
Public void saveUser (User user ){
SessionFactory sessionFactory = HibernateUtil. getSessionFactory (); // get SessionFactory
Session session = sessionFactory. getCurrentSession (); // getCurrentSession
 
Session. save (user );
 
    }
 
}

GetCurrentSession () is used to obtain the session object of the current thread and share the session. In this way, the transaction starts from the service and then ends with the service.

Difference between getCurrentSession () and openSession ()

The session created by getCurrentSession is bound to the current thread, but not openSession.

The thread created by getCurrentSession is automatically closed after transaction rollback or transaction commit, and openSession must be closed manually.

The session created using getCurrentSession () is bound to the current thread, and openSession () is used ()
The created session will not
* Sessions created using getCurrentSession () are automatically closed when commit or rollback is used, and openSession () is used ()
The created session must be disabled manually.

2. To use getCurrentSession (), add the following configuration to the hibernate. cfg. xml file:

* If you are using a local transaction (jdbc transaction)
<Property name = "hibernate. current_session_context_class"> thread </property>
* If you are using a global transaction (jta transaction)
<Property name = "hibernate. current_session_context_class"> jta </property>

GetCurrentSession () is associated with openSession ().

When SessionFactory is started, Hibernate will create the corresponding CurrentSessionContext according to the configuration. When getCurrentSession () is called, the actual method to be executed is CurrentSessionContext. currentSession (). When currentSession () is executed, if the current Session is empty, currentSession will call the openSession of SessionFactory. Therefore, getCurrentSession () is a better method for obtaining sessions for Java EE.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.