2015年10月18日 星期日

HibernateUtil (Hibernate3.x 三)

尤於每次使用Hibernate,都要使用以下三行開頭
Configuration cfg = new Configuration().configure();
SessionFactory factory = cfg.buildSessionFactory();
Session session = factory.openSession();
實在太麻煩,而且效能也太差,所以有人寫了一支公用的方法

※自己寫HibernateUtil

public class HibernateUtil {
    // 保存此thread之中所有打開的Session
    private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
    private static SessionFactory sessionFactory;
    private static Configuration config = new Configuration();
    
    static {
        try {
            config.configure();
            sessionFactory = config.buildSessionFactory();
        } catch (Exception e) {
            System.err.println("取得sessionFactory錯誤!");
            e.printStackTrace();
        }
    }
    
    public static Session getSession() throws HibernateException {
        // 從thread池之中取得一個Session,第一次一定沒有
        Session session = (Session) threadLocal.get();
    
        if (session == null || !session.isOpen()) {
            if (sessionFactory == null) {
                rebuildSessionFactory();
            }
            session = (sessionFactory != null) ? sessionFactory.openSession()
                    : null;
            // 將取得的Session保存在thread池之中
            threadLocal.set(session);
        }
        return session;
    }
    
    public static void rebuildSessionFactory() {
        try {
            config.configure();
            sessionFactory = config.buildSessionFactory();
        } catch (Exception e) {
            System.err.println("取得sessionFactory錯誤!");
            e.printStackTrace();
        }
    }
    
    public static void closeSession() throws HibernateException {
        Session session = (Session) threadLocal.get();
        threadLocal.set(null);
        if (session != null) {
            session.close();
        }
    }
    
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
    
    public static Configuration getConfiguration() {
        return config;
    }
}

現在只要這要子用就可以了
Session session = HibernateUtil2.getSession();
Emp emp = (Emp) session.get(Emp.class, 8888);
System.out.println(emp);
session.close();

※官方的HibernateUtil

官方提供的HibernateUtil在這裡,使用時,如下的方式
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
//session.beginTransaction();
Emp emp = (Emp) session.get(Emp.class, 8888);
System.out.println(emp);
session.close();

此時會報「No CurrentSessionContext configured!」,沒有設定CurrentSession
Hibernate本身沒有交易管理功能,它依賴於JDBC(DB只有一個)或JTA(DB有多個)的交易管理功能,所以在hibernate.cfg.xml增加以下兩行
<property name="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
<property name="hibernate.current_session_context_class">thread</property>

這時又報「get is not valid without active transaction」,沒有啟動transaction,所以把上面程式碼的註解打開就可以了,雖然是查詢,而且我還有設自動commit,但還是要加這行才不會報錯

hibernate.current_session_context_class在這裡有說明,有四個選項

完整的應用程式伺服器,必需包括:連線池、交易管理、安全管理
Tomcat不完整,它只有連線池的功能、交易和安全管理都沒有
它只能設thread而已
而hibernate.transaction.factory_class預設就是JDBC,所以可以不設定

如果是JTA可以將上面的兩行改成這樣
<property name="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>
<property name="hibernate.current_session_context_class">jta</property>


沒有留言:

張貼留言