connection、HttpSession、hibernate中的session、transaction
阿新 • • 發佈:2019-02-09
connection和HttpSession的區別
session(會話)和connection(連線)的定義:
connection:是一個物理的概念,它指的是一個通過網路建立的客戶端和專有伺服器(Dedicated Server)或共享伺服器(Shared Server)的一個網路連線,既是一條物理路勁。
session:是一個邏輯的概念,它是存在於例項中,一個連線可以擁有多個會話也可以沒有會話,同一個連線上的不同會話之間不會相互影響。
有A/B兩個城市,需要從A運送白菜到B城
我們先建設一條公路
然後運送白菜過去,包括準備白菜和運送白菜以及返回等一系列的動作。
一條公路,可以運送0-n次的白菜
當然從A到B的公路也可能不只一條。
某一次運送白菜,可以在真正上路時才開通某一條道路
一次運送不會影響別的運送的狀態
對應資料庫
A代表客戶端程序
B代表伺服器端程序
公路代表連線,
運送一次白菜代表一個會話
一個連線可以進行多次的會話
一個會話可以不依賴於某個連線,甚至沒有連線(當我準備好了,真正開始運送時再建立連線)
一個會話不會影響別的會話
ThreadLocalSessionContext的名稱上看,它所做的就是把一個session繫結到當前執行緒上,讓當前執行緒作為session的上下文。這樣,在service裡不同的dao通過sessionFactory.getCurrentSession()得到的將是當前執行緒上的同一個session,這是非常必要的做法,通過使用同一個session確保了持久化物件的一致性。但是從ThreadLocalSessionContext的程式碼來看,它並只是做了這一件事,它還做了另外一件非常“醒目”的事情:即給session包裹了一層代理org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper,這個代理將攔截session的操作,對session的使用做出瞭如下的限制:
1.在沒有顯式地開始一個事務之前,不能使用session的任何資料訪問方法。
2.一旦事務提交,session將自動close。
Session是JAVA應用程式和Hibernate進行互動時使用的主要介面,它也是持久化操作核心API, Session物件是有生命週期的,它以Transaction物件的事務開始和結束邊界
。Session作為貫穿Hibernate的持久化管理器核心,提供了眾多的持久化的方法,如save(), update ,delete ,find(Hibernate 3中已經取消了此方法)等,通過這些方法我們可以透明的完成物件的增刪改查。
public class HibernateUtil {
public static final SessionFactory sessionFactory;
public static final ThreadLocal<Session> session = new ThreadLocal<Session>();
static {
try {
Configuration configuration = new Configuration().configure();
sessionFactory = configuration.buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static Session currentSession() throws HibernateException {
Session s = (Session) session.get();
if (s == null) {
s = sessionFactory.openSession();
session.set(s);
}
return s;
}
public static void closeSession() throws HibernateException {
Session s = (Session) session.get();
if (s != null)
s.close();
session.set(null);
}
}
通過以上程式碼(ThreadLocal<Session>),我們就可以實現執行緒範圍內的Session共享,從而避免了線上程中頻繁的建立和銷燬Session 例項。不過注意線上程結束時關閉Session。同時值得一提的是,新版本的Hibernate在處理Session的時候已經內建了延遲載入機制,只有在真正發生資料庫操作的時候,才會從資料庫連線池獲取資料庫連線,我們不必過於擔心Session的共享會導致整個執行緒生命週期內資料庫
Hibernate Transaction是從Session中獲得的,tx = session.beginTransaction(),最後要先提交tx,然後再session.close,這完全符合JDBC的Transaction的操作順序,但是這個順序是和JTA的Transactioin操作順序徹底矛盾的!!! JTA是先啟動Transaction,然後啟動Session,關閉Session,最後提交Transaction,因此當你使用JTA的Transaction的時候,那麼就千萬不要使用Hibernate的Transaction
總結: 1、在JDBC上使用Hibernate 必須寫上Hibernate Transaction程式碼,否則資料庫沒有反應。此時Hibernate的Transaction就是Connection.commit而已 2、在JTA上使用Hibernate 寫JTA的Transaction程式碼,不要寫Hibernate的Transaction程式碼,否則程式會報錯 3、在EJB上使用Hibernate 什麼Transactioin程式碼都不要寫,在EJB的部署描述符裡面配置 Java程式碼 |---CMT(Container Managed Transaction); | |---BMT(Bean Managed Transaction); | |----JDBC Transaction | |----JTA Transaction 你說“Hibernate的JDBCTransaction根本就是conn.commit而已,根本毫無神祕可言,只不過在Hibernate中,Session開啟的時候,就會自動conn.setAutoCommit(false),不像一般的JDBC,預設都是true,所以你最後不寫commit也沒有關係,由於Hibernate已經把AutoCommit給關掉了,所以用Hibernate的時候,你在程式中不寫Transaction的話,資料庫根本就沒有反應” 但sf.opengSession()時,並沒有setAutoCommit(false),我想問的是,如果不編寫任何事務程式碼,如: Java程式碼 Session s = sf.openSession();; ...... s.close();; 資料庫會不會有反應(此時應該是預設AutoCommit為true)。 另外,我想問一下: 1. s.flush()是不是必須的 2. s.close()是不是一定要關閉 比如你上面提到的: Java程式碼 javax.transaction.UserTransaction tx = new InitialContext();.lookup("javax.transaction.UserTransaction");; Session s1 = sf.openSession();; ... s1.flush();; s1.close();; .. Session s2 = sf.openSession();; ... s2.flush();; s2.close();; tx.commit();; s1不關閉,使用s2進行操作的程式碼中使用s1可不可以(我覺得這樣更加節約資源,不需要反覆的連線、關閉) 引用 但sf.opengSession()時,並沒有setAutoCommit(false),我想問的是,如果不編寫任何事務程式碼,如: Session s = sf.openSession(); ...... s.close(); 資料庫會不會有反應(此時應該是預設AutoCommit為true)。 不會有反應。在sf.openSession() 建立Session例項的時候,就已經呼叫了conn.setAutoCommit(false)了。