Spring @Transactional Declarative Transaction Management Getcurrentsession

Source: Internet
Author: User

Spring @Transactional Declarative Transaction Management Getcurrentsession

 

in spring @Transactional the configuration of declarative transaction management, Hibernate.current_session_context_class=thread ...

This sentence cannot be added ... If you add it, it will go wrong. Then why not add it?

that's because in spring transaction management, the current session is bound to Springsessioncontext in the Threadlocalsessioncontext, not in the

First, combine bernate4.0 to say:

From the beginning, the background implementation of sessionfactory.getcurrentsession () is pluggable. As a result, we have introduced new extension interfaces (Org.hibernate.context.spi.CurrentSessionContext) and

The new configuration parameter (Hibernate.current_session_context_class) to unplug the definition of what is the scope and context (scope and context) for the current session.

It defines a single method, Currentsession (), which is used by the specific implementation to track the current context session.

first, let's see Org.hibernate.context.spi.CurrentSessionContext .

There is only one method for this interface:

Sessioncurrentsession()

Throws Hibernateexception

Retrieve thecurrent Session According to the scoping defined by this implementation.

currentsession () indicates that the current session is returned based on the implementation and definition of the current Currentsessioncontext

 

This interface ... There are 3 classes in hibernate that implement this interface

All known implementing Classes:

Jtasessioncontext, Managedsessioncontext, Threadlocalsessioncontext

 

1:org.hibernate.context.internal.threadlocalsessioncontext -The current session is tracked and defined through the currently executing threads.

2:org.hibernate.context.internal.jtasessioncontext-current session According to JTA to track and define. This is exactly the same as the previous method of supporting JTA only.

3:org.hibernate.context.internal.managedsessioncontext.

Spring also implements this interface for transaction management:

1:org.springframework.orm.hibernate4.springsessioncontext– The current session is tracked and defined according to the spring and transaction manager.

These implementations provide a programming model for "one session per database transaction", also called a session per request. The start and end of Hibernate session is controlled by the existence of database transactions.

The Hibernate.current_session_context_class configuration parameter defines which Org.hibernate.context.spi.CurrentSessionContext implementation should be used.

Generally, the value of this parameter indicates the full name of the implementation class to be used, but the two built-in implementations can use shorthand, "JTA" and "thread".

Hibernate.current_session_context_class=thread

The essence is:

hibernate.current_session_context_class= Org.hibernate.context.internal.ThreadLocalSessionContext

 

similarly:

Hibernate.current_session_context_class=jta

The essence is:

hibernate.current_session_context_class= Org.hibernate.context.internal.JTASessionContext

 

 

In Spring @Transactional Declarative Transaction management, the definition of "currentsession" is: The session currently managed by the Spring transaction manager, which should be configured at this time:

hibernate.current_session_context_class=Org.springframework.orm.hibernate4.SpringSessionContext

After spring consolidates hibernate management transactions, the currentsession is bound to springsessioncontext instead of thread after the transaction is managed by spring's transactionmanager.

At this point the Hibernate.current_session_context_class should be springsessioncontext, and it will be set automatically when using Localsessionfactorybean.

So I don't need you to set Current_session_context_class.

-   -       - --         -

Let's analyze Sessionfactoryimpl, org.hibernate.context.spi.CurrentSessionContext .

Org.hibernate.context.internal.ThreadLocalSessionContext

Org.springframework.orm.hibernate4.SpringSessionContext

The source code for these classes

 

1: Analysis Sessionfactory.getcurrentsession () Let's go in .

come to Sessionfactoryimpl.getcurrentsession () method:

 

Public final class Sessionfactoryimpl
      implements Sessionfactoryimplementor {...
  Private final transient currentsessioncontext currentsessioncontext;
  . . .
  Public Session getcurrentsession () throws Hibernateexception {
      if (Currentsessioncontext = = null) {
         throw new Hi Bernateexception ("No currentsessioncontext configured!");
      }
      return currentsessioncontext.currentsession ();
  }
 
. . .
}


 

The actual type of the Currentsessioncontext property of Sessionfactoryimpl is

Decided by the Hibernate.current_session_context_class ...

 

2: First set: hibernate.current_session_context_class= Org.hibernate.context.internal.ThreadLocalSessionContext

To this sentence, currentsessioncontext.currentsession () follow in

public class Threadlocalsessioncontext implements Currentsessioncontext {... private static final threadlocal&lt ;
   map> context = newthreadlocal<map> ();
            ...//Open a session protected session buildorobtainsession () {return factory.withoptions () with "auto-close after transaction commit" . AutoClose (Isautocloseenabled ()). Connectionreleasemode (Getconnectionreleasemode ()).
    Flushbeforecompletion (isautoflushenabled ()). Opensession ();
      The public final session currentsession () throws Hibernateexception {//from the thread-local volume context tries to remove the Session that has been bound to the thread
     
      Session current = Existingsession (factory); If there is no session bound to the thread (current = = null) {//Opens a "auto-close after transaction commit" session current = Buildorobtainsessio
            N ();
         Current.gettransaction (). Registersynchronization (Buildcleanupsynch ());
       Wrap the session in Thetransaction-protection Proxy if (needswrapping (current)) {     Current = wrap (current);
      }//The resulting Session is bound to the thread: that is, set to the thread local amount in the <SessionFactory,Session> key value pair context Dobind (current, factory);
   } return current; }
. . .
}


the Getcurrentsession () for hibernate.current_session_context_class= thread is now clear:

1: Try to remove the session bound to the thread

2: If not, open a session "auto-close after transaction commit" and add this session to the Threadlocal map.

3: Back to session


 

3: Then re-analysis: hibernate.current_session_context_class= Org.springframework.orm.hibernate4.SpringSessionContext

 

Public UserService
{
   @Transactional public
   void AddUser (user user) throws Exception
   {
      Session session = Sessionfactory.getcurrentsession ();
     
      Session.save (user);
   }
}


 

since the @transactional was added and the AddUser () method was executed, spring's TransactionManager will automatically open sesion, automatically open transactions, and bind this sesion to Springsessioncontext ( In fact a map of Transactionsynchronizationmanager's threadlocal):

 

 

Then to the sessionfactoryimpl.getcurrentsesssion () of the currentsessioncontext.currentsession () This sentence, followed in

public class Springsessioncontext implements Currentsessioncontext {private final sessionfactoryimplementor sessionf
 
 
   Actory; ------Public Session currentsession () throws Hibernateexception {//The key is this sentence, spring will actually go Transactionsynchron Izationmanager find "currentsession" Object value = Transactionsynchronizationmanager.getresource (this.sessionfactory
      );
      if (value instanceof session) {return (session) value;
         } else if (value instanceof sessionholder) {Sessionholder Sessionholder = (sessionholder) value;
         Session session = Sessionholder.getsession (); if (transactionsynchronizationmanager.issynchronizationactive () &&!sessionholder.issynchronizedwit Htransaction ()) {transactionsynchronizationmanager.registersynchronization (new springsess
            Ionsynchronization (Sessionholder, this.sessionfactory)); Sessionholder.setsynchronizedwithtransaction (TRUE);
  
            Flushmode Flushmode = Session.getflushmode (); if (Flushmode.ismanualflushmode (flushmode) &&!
                Transactionsynchronizationmanager.iscurrenttransactionreadonly ()) {Session.setflushmode (FlushMode.AUTO);
            Sessionholder.setpreviousflushmode (Flushmode);
      }} return session;
         } else if (this.jtasessioncontext! = NULL) {Session session = This.jtaSessionContext.currentSession (); if (transactionsynchronizationmanager.issynchronizationactive ()) {Transactionsynchronizationmanager.reg
         Istersynchronization (Newspringflushsynchronization (session));
      } return session;
      } else {throw new Hibernateexception ("No Session found for current thread"); }
   }
 
}


Object value =transactionsynchronizationmanager.getresource (this. sessionfactory); The key is this sentence, follow in:

Public abstract class Transactionsynchronizationmanager {
 
 ...
 Private static final threadlocal<map<object, object>> resources;
 
 public static object GetResource (Object key) {
      Object actualkey = Transactionsynchronizationutils.unwrapresourceifnecessary (key);
      Find the session in the properties resources of Threadlocal, in the resources of <SessionFactory,SessionHolder> or <sessionfactory, Session> Key-value pairs are stored in the map of threadlocal
      Object value = Dogetresource (Actualkey);
      if (value! = null && logger.istraceenabled ()) {
         logger.trace ("retrievedvalue [" + Value + "] for key [" + ACTU Alkey + "] bound to thread [" +
                Thread.CurrentThread (). GetName () + "]");
      }
      return value;
   }
 
 . ..
}


Now for hibernate.current_session_context_class= The Org.springframework.orm.hibernate4.SpringSessionContext getcurrentsession () is clear:

 

 

1: When @Transactional declared method is executed, spring's TransactionManager will automatically open sesion, automatically open transactions, and bind this sesion to Springsessioncontext ( In fact a map of Transactionsynchronizationmanager's threadlocal):

 

when the 2:sessionfactory.getcurrentsession () method executes, the call Springsessioncontext.currentsession () finds the current session from the context of the Transactionsynchronizationmanager

3: Returned to the current session, not found, then return Hibernateexception ("No Sessionfound for Present thread")



PS: From this, we also know that when executing sessionfactoryimpl.opensession (), just simply new a sessionbuilder, then call Sessionbuilder.opensession (), The resulting session is not bound to any org.hibernate.context.spi.CurrentSessionContext in the context.


////////////////////////////////////////////////////////////////----------------------------------------------- ----------------------------------------------------------------------------------------



Summary: hibernate.current_session_context_class=thread ( Org.hibernate.context.internal.ThreadLocalSessionContext)

and Hibernate.current_session_context_class=org.springframework.orm.hibernate4.springsessioncontext The difference between the Sessionfactory.getcurrentsession () is:

The former finds the session in the thread-local map of the Threadlocalsessioncontext,

The latter is found in the context of the Springsessioncontext (thethread-local map in the Transactionsynchronizationmanager) .


In the end, you will find that both Threadlocalsessioncontext or springsessioncontext look for "currentsession", all with similar key-value pairs <sessionfactory, The session> form is stored in the threadlocal map, meaning the context of both is a threadlocal map ... Find the corresponding session with the Sessionfactory key, so in the same thread, a sessionfactory can only have one currentsession

 

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.