Hibernate学习(一)

一、使用单例初始化SessionFactory

SessionFactory接口负责HIbernate的初始化和建立Session对象。它在Hibernate中起到一个缓冲区的作用,HIbernate可以将自动生成的SQL语句、映射数据以及某些可重复利用的数据放在这个缓冲区中。同时它还保存了对数据库配置的所有映射关系,维护了当前的二级缓存。

SessionFactory具有以下特点:

  • 它是线程安全的,它的的同一个实例能够多个线程共享。
  • 它是重量级的,不能随意创建和销毁它的实例。

由于SessionFactory的这些特点,一般情况下,一个项目只需要一个SessionFactory,只有在应用中存在多个数据源时,才为每个数据源建立一个SessionFactory实例。可以建立一个HibernateUtils.java类初始化SessionFactory使项目使用的是同一个SessionFactory。代码如下:


package com.test.util;

import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.SessionFactory;

public class HibernateUtils {

    private static Configuration conf;
    private static SessionFactory factory;

    static{
        conf =  new Configuration().configure();
        factory = conf.buildSessionFactory();
    }
    
    public static SessionFactory getFactory(){
        return factory;
    }
      
 }

二、线程安全的Session

创建SessionFactory实例后,就可以通过它获取Session实例。获取Session实例有两种方式,一种是通过openSession()方法,另一种是通过getCurrentSession()方法。

这两种方法的区别是:采用openSession方法获取Session实例时,SessionFactory直接创建一个新的实例,并且在使用完成后需要调用close方法进行手动关闭。而getCurrentSession方法创建的Session实例会绑定到当前线程中,它会在提交或回滚操作时自动关闭。

Session是线程不安全的,多个线程同时操作一个Session实例时,就可能造成线程混乱。

我们可以改写HibernateUtils工具类实现线程安全的Session。代码如下:


package com.test.util;

import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.SessionFactory;

public class HibernateUtils {

    private static Configuration conf;
    private static SessionFactory factory;
    private static ThreadLocal<Session> session = new ThreadLocal();

    static{
        conf =  new Configuration().configure();
        factory = conf.buildSessionFactory();
    }

    public static Session getSession(){
        Session s = session.get();
        if(s ==  null){
            s = factory.getCurrentSession();
            session.set(s);
        }
        return s;
    }

    public static void closeSession(){
        Session s = session.get();
        if (s != null) {
            session.set(null);
        }
    }

}

ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是thread local variable(线程局部变量)。也许把它命名为ThreadLocalVar更加合适。线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。从线程的角度看,就好像每 一个线程都完全拥有一个该变量。具体关于ThreadLocal的详细知识可以自行去查一下。

三、遇到的问题

在使用getCurrentSession是遇到了以下错误

org.hibernate.HibernateException: No CurrentSessionContext configured!

是因为在hibernate.cfg.xml文件中忘记进行了如下设置:
如果是在web容器中运行hibernate,则在hibernate.cfg.xml中加入这句话:

<property name="hibernate.current_session_context_class">jta</property>

如果是在一个单独的需要进行JDBC连接的java application中运行hibernate,则这样设置:

<property name="hibernate.current_session_context_class">thread</property>
posted @ 2018-05-15 11:12  RicardoWX  阅读(137)  评论(0编辑  收藏  举报