使用Hibernate框架轻松连接数据库(蓝桥杯软件大赛培训教材-Java方向)
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.6 Hibernate核心接口

在本章1.4节中,用到了若干个Hibernate的接口,这些接口都是Hibernate的核心接口,下面是对它们的说明。

1.6.1 Configuration接口

Configuration对象用来配置和引导Hibernate,一个Hibernate应用使用一个Configuration实例来指定主配置文件的位置,然后创建会话工厂。

在代码中,配置文件是自动探测的,Configuration cfg = new Configuration().configure();中的configure()方法未带参数时,Hibernate在classpath根路径下搜索名为hibernate.cfg.xml的文件,如果没有找到将会抛出异常。这就是为什么要将Hibernate主配置文件命名为hibernate.cfg.xml,并且将其放在src目录下(src目录映射到编译后的classpath根路径)的原因。当然,也可以另行配置和指定Hibernate主配置文件的路径及名称,例如:

        Configuration cfg = new Configuration().configure("/cfg/h4.cfg.xml")

1.6.2 SessionFactory接口

一个Hibernate应用从SessionFactory(会话工厂)里获得会话实例。会话工厂是一个典型的工厂模型,它可以被多个线程共享,提供会话。一般情况下,整个应用只有唯一的一个SessionFactory,它在应用初始化时被创建。如果应用需要使用Hibernate访问多个数据库,则需要对每一个数据库使用一个SessionFactory。SessionFactory缓存了生成的SQL语句和Hibernate在运行时使用的元数据。

一个常见的问题是,SessionFactory在创建之后如何存储和访问,既可以保持其单例性质又不要太麻烦。具体有JNDI、JMX等方式,在这里要介绍一种最直观和快捷的解决方式,即编写一个工具类,将SessionFactory的实例设置为静态成员(只在内存中存在一份)并将其初始化的代码放在静态初始化块中(只执行一次)。这个工具类在Hibernate社区相当知名,其基本实现如下:

        package org.ijob.util;
        import org.Hibernate.SessionFactory;
        import org.Hibernate.cfg.Configuration;
        import org.Hibernate.service.ServiceRegistry;
        import org.Hibernate.service.ServiceRegistryBuilder;
        public class HibernateUtil {
            private static SessionFactory sessionFactory; //静态变量
            static{                           //静态初始化块
                try {
                    Configuration cfg = new Configuration().configure();
                    //Hibernate4提供的新方式
                    ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
                        .applySettings(cfg.getProperties()).buildServiceRegistry();
                    sessionFactory = cfg.buildSessionFactory(serviceRegistry);
                } catch (Throwable ex) {
                    throw new ExceptionInInitializerError(ex);
                }
            }
            public static SessionFactory getSessionFactory() {
                return sessionFactory;
            }
            public static void shutdown() {
                getSessionFactory().close();
            }
        }

在工具类中,构建SessionFactory的方式不是以前大家熟知的方式,例如:

        Configuration cfg = new Configuration().configure();
        sessionFactory = cfg.buildSessionFactory();

从Hibernate4开始,推荐的方式是:

org.hibernate.cfg.Configuration buildSessionFactory(ServiceRegistry serviceRegistry)

需要先构造一个ServiceRegistry对象。这个对象,目前无须深究,只要照做就行了。

现在,获取Session实例的代码就可以这样写:

        Session session = HibernateUtil.getSessionFactory().openSession();

1.6.3 Session接口

Session(会话)接口是Hibernate应用使用的主要接口,它拥有操作持久化对象的一系列API,可用于管理(例如加载和保存)对象,因此也称为“持久化管理器”。它的内部是一系列的SQL语句,在某个点会与数据库同步。

Session实例是轻量级的,创建与销毁的代价不昂贵,通常会为每个事务创建一个Session实例,并在使用后关闭它。Session实例并不是线程安全的,因此应该被设计为每次只能在一个线程中使用。

注意:Hibernate会话与Web层的HttpSession没有任何关系,在本书中使用的会话,指的是Hibernate会话。

1.6.4 Transaction接口

Transaction(事务)接口是对实际事务实现的一个抽象,这些实现包括JDBC事务或者JTA事务等。这样的设计允许开发人员在代码中使用统一的事务操作接口,为项目在不同事务环境间迁移提供了便利性。

Hibernate中的具体事务控制通过主配置文件中的配置来选择。下面的配置内容选择了JDBC原生事务控制,如果注释的行变换一下,选择的就是JTA事务控制。

        <property name="transaction.factory_class">
            org.hibernate.transaction.JDBCTransactionFactory<!-- 默认值 -->
            <!--使用JTA事务控制应改为:org.hibernate.transaction.JTATransactionFactory -->
        </property>

在Transaction接口中主要定义了commit()和rollback()两个方法,前者是提交事务的方法,后者是回滚事务的方法。

1.6.5 Query与Criteria接口

Query(查询)接口允许在数据库上执行查询,并控制查询如何具体执行。查询可以使用HQL(后面课程会详细介绍)或SQL。Query实例可用来绑定查询参数,限定查询返回的结果数,并且最终执行查询。Criteria与Query接口非常类似,它允许创建并执行面向对象方式的查询。