Hibernate 系列 04 - Hibernate 配置相关的类


 

引导目录:

  Hibernate 系列教程 目录

 

 

前言:

  通过上一篇的增删改查小练习之后,咱们大概已经掌握了Hibernate的基本用法。

 

  我们发现,在调用Hibernate API的过程中,虽然Hibernate里面为咱们提供了很多的类,但是常用的类只有很少的那么几个。

  下面,一起着重地看一下其中配置相关的类 - Configuration & SessionFactory。

 

目录:

Configuration 类 (负责管理Hibernate的配置信息) SessionFactory 类 (负责创建Session的实例)

 

1. Configuration 类 (负责管理Hibernate的配置信息)

  Configuration类负责管理Hibernate的配置信息。

  当创建SessionFactory时,Configuration实例可以指定使用哪一个映射文档(xxx.cfg.xml)。

 

  应用程序通常只是创建一个Configuration实例,并通过它创建一个SessionFactory实例。

  例如下面的代码:

1     private static SessionFactory sessionFactory = null;
2     static{
3         try {
4             sessionFactory = new Configuration().configure().buildSessionFactory();
5         }catch (HibernateException ex){
6             throw new RuntimeException("Exception building SessionFacotry: "+ex.getMessage());
7         }
8     }

 

  当客户端发送一个请求线程时,SessionFactory初始化一个Session(大部分对数据库的操作都调用Session类的API来完成)。

  代码如下:

 1     public static final ThreadLocal sessionMap = new ThreadLocal();
 2     public static Session currentSession() throws HibernateException{
 3         Session s = (Session)sessionMap.get();
 4         // 如果此线程还没有打开一个Session,则新建一个
 5         if (s == null) {
 6             s = sessionFactory.openSession();
 7             sessionMap.set(s);
 8         }
 9         return s;
10     }

 

  对于第一次使用Hibernate的初学者来说,下面的这段代码可以说是最常见的使用Configuration的方式了:

1 Configuration cfg = new Configuration().configure();

 

  Configuration是Hibernate的入口,在新建一个Configuration的实例时(构造),Hibernate会在CLASSPATH环境变量中查找hibernate.properties文件。

  如果该文件存在,则将文件的内容加载到内容中,如果不存在,则抛出例外。

 

   .configure() 方法默认会在CLASSPATH环境变量下面寻找hibernate.cfg.xml文件,参见源码, configure() 的内部实现为:

1     public Configuration configure() throws HibernateException {
2         return this.configure("hibernate.cfg.xml");
3     }

 

  如果没有找到,系统会打印信息并抛出HibernateException;

  如果找到该文件, configure() 方法会首先访问 <session-factory> 配置节点,并获取该元素的name属性;如果非空,将用这个配置的值来覆盖hibernate.propertieshibernate.session_factory_name的配置值。

 

  从这里可以看出,hibernate.cfg.xml中的配置信息可以覆盖hibernate.properties的配置信息。

 

  Configuration的configure()方法还支持带参数的访问形式,可以指定xxx.cfg.xml文件的位置,而不是使用默认的CLASSPATH中设置的hibernate.cfg.xml。

  例如:

1 File file = new File("D:\\configs\\hibernate.cfg.xml");
2 Configuration cfg = new Configuration().configure(file);

 

  Configuration还提供了一系列方法用来定制Hibernate的加载配置文件的过程,可以让应用更灵活。

  常用的有以下几种:

addProperties(Element) addProperties(Properties) setProperties(Properties) setProperty(String, String)

 

  通过以上的几个方法,除了使用默认的hibernate.properties文件,还可以提供多个.properties配置文件。

  使用Hibernate时可以根据不同的情况使用不同的配置文件,例如:

1 Properties p = new Properties();
2 p.load(new FileInputStream("my.properties"));
3 Configuration cfg = new Configuration().setProperties(p).configure();

 

  除了指定.properties文件外,还可以指定xxx.hbm.xml文件。

  下面列出几个常用的方法:

 addClass(Class) addFile(File) addFile(String) addURL(URL)

 

  前面已经讲过,configure()方法默认是通过访问hibernate.cfg.xml的<mapping>元素来加载程序员所提供的xxx.hbm.xml文件。

  上面列出的方法可以直接指定xxx.hbm.xml文件,例如,addClass()方法可以直接通过指定Class类加载对应的映射文件,Hibernate会将提供的Class的全名(包括package)自动转化为文件路径。

  如com.geeksss.entity.Student.class对应了com/geeksss/entity/Student.hbm.xml。

 

  还可以使用addFile()方法直接指定映射文件,例如下面的例子:

1 Configuration cfg = new Configuration().addClass(Student.class);

  或:

1 Configuration cfg = new Configuration().addURL(Configuration.class.getResource("Student.hbm.xml"));

  或:

1 Configuration cfg = new Configuration().addFile("Student.hbm.xml");

 

  Configuration提供的这些方法的优点如下:

一个应用程序中往往有很多xxx.hbm.xml映射文件,开发的过程中如果只是为了测试某个或几个Java PO (Persistence Object),则没有必要把所有的xxx.hbm.xml都加在到内存中。
这样可以通过addClass()或者addFile()方法直接加载,显得非常灵活。 学习Hibernate的过程中,往往需要通过练习来体会Hibernate提供的各种特征,而很多特征是需要修改配置文件的。
如果要观察相同的代码在不同特征下的表现是怎样的,就需要手工修改配置文件,这样太麻烦了,而且容易出错,但是可以提供多个配置文件,每个配置文件针对需要的特征而配置。
在调用程序时,把不同的配置文件作为参数传递进去,而程序代码中使用setProperties()和addFile()指定传入的配置文件参数即可。

 

 

2. SessionFactory 类 (负责创建Session的实例)

  SessionFactory负责Session实例的创建。

 

  为了能创建一个Session对象,必须在Hibernate初始化时创建一个Configuration类的实例,并将已经写好的映射文件交由它处理。

  这样,Configuration对象就可以创建一个SessionFactory对象,当SessionFactory对象创建成功之后,Configuration对象就没有用了,可以简化的抛弃它。

  例如下面的示例代码:

1 Configuration cfg = new Configuration().configure();
2 SessionFactory sessionFactory = cfg.buildSessionFactory();

 

  SessionFactory是线程安全的,可以被多线程调用以取得Session,而且构造SessionFactory很消耗资源。

  所以多数情况下一个应用中之初始化一个SessionFactory,为不同的线程提供Session。