一、 Hibernate实现Web开发的基本步骤-简
(1) 创建数据库
(2) 将Hibernate所需要的JAR包导入项目(WEB-INF/lib下)
(3) 创建Hibernate的配置文件
(4) 利用Hibernate的第三方工具或者eclipse的有关插件从数据库中创建出相应的实体对象、ORM映射文件(Hibernate支持注解之后无此配置文件)
(5) 创建Hibernate的SessionFactory类
(6) 通过SessionFactory创建Session实例
(7) 通过创建的Session实例践行持久化对象的管理(CRUD)
(8) 通过创建的Transaction实例进行事务管理
(9) 通过创建的Query或者Criteria实例实现数据库的查询
二、 Hibernate的核心接口和类
Hibernate的核心类和接口一共有6个,分别为:Session、SessionFactory、Transaction、Query、Criteria和Configuration。这6个核心类和接口在任何开发中都会用到。通过这些接口,不仅可以对持久化对象进行存取,还能够进行事务控制,这一节先对这6个核心接口简要说一下,再接下来的几节会做详细介绍。
1. Configuration
Configuration 类的作用是对Hibernate 进行配置,以及对它进行启动。在Hibernate 的启动过程中,Configuration 类的实例首先定位映射文件的位置,读取这些配置,然后创建一个SessionFactory对象。虽然Configuration 类在整个Hibernate 项目中只扮演着一个很小的角色,但它是启动hibernate 时所遇到的第一个对象。
2. SessionFactory
SessionFactory接口负责初始化Hibernate。它充当数据存储源的代理,并负责创建Session对象。这里用到了工厂模式。需要注意的是SessionFactory并不是轻量级的,因为一般情况下,一个项目通常只需要一个SessionFactory就够,当需要操作多个数据库时,可以为每个数据库指定一个SessionFactory。
3. Session
Session接口负责执行被持久化对象的CRUD操作(CRUD的任务是完成与数据库的交流,包含了很多常见的SQL语句)。但需要注意的是Session对象是非线程安全的。同时,Hibernate的session不同于JSP应用中的HttpSession。这里当使用session这个术语时,其实指的是Hibernate中的session,而以后会将HttpSession对象称为用户session。
4. Transaction
Transaction 接口是一个可选的API,可以选择不使用这个接口,取而代之的是Hibernate 的设计者自己写的底层事务处理代码。 Transaction 接口是对实际事务实现的一个抽象,这些实现包括JDBC的事务、JTA 中的UserTransaction、甚至可以是CORBA 事务。之所以这样设计是能让开发者能够使用一个统一事务的操作界面,使得自己的项目可以在不同的环境和容器之间方便地移植。
5. Query
Query接口让你方便地对数据库及持久对象进行查询,它可以有两种表达方式:HQL语言或本地数据库的SQL语句。Query经常被用来绑定查询参数、限制查询记录数量,并最终执行查询操作。
6. Criteria
Criteria接口与Query接口非常类似,允许创建并执行面向对象的标准化查询。值得注意的是Criteria接口也是轻量级的,它不能在Session之外使用。
三、 Hibernate的体系结构
在Hibernate的体系结构中,Hibernate Session这个概念非常重要,只有处于Session管理下的POJO才有持久化操作的能力。当应用程序对处于Session管理下的POJO实例执行操作时,Hibernate将这种面向对象的操作转换为持久化操作。在使用Hibernate时,需要用到一个名为hibernate。properties的文件,此文件用于配置Hibernate与数据库的连接信息。还有映射文件(现在基本使用注解形式,持久化类和数据表之间的映射文件就不需要了)。
Hibernate的持久化解决方案将用户从原始的JDBC访问中释放出来,用户无需关心底层的JDBC操作,而是以面型对象的方式进行持久化操作。底层数据连接的获得、数据访问的实现、事务控制都无需用户关心。这是一种“全面解决”的体系结构方案,将应用层从底层的JDBC/JTA API中抽象出来。
一个简要的 Hibernate 整体体系结构大致如下图所示:
Application:应用
persistent objects:持续化对象
properties:属性,性能
XML Mapping:XML映射
从上图可以看出,Hibernate 使用数据库(Database)和配置信息(hibernate.properties 等)来为应用程序提供持久化服务(以及持久的对象 Persistent Objects)。
我们再来看看 Hibernate 运行时的体系结构。由于Hibernate非常灵活,且支持多种应用方案,所以这里我们只描述一下两种极端的情况。
1、 “轻型”的体系结构方案
要求应用程序提供自己的 JDBC 连接并管理自己的事务。这种方案使用了 Hibernate API 的最小子集:
2、 “全面解决”的体系结构方案
将应用层从底层的 JDBC/JTA API 中抽象出来,而让 Hibernate 来处理这些细节:
四、 使用Hibernate操作数据(最基本)
从上往下依次进行:
(1) 创建一个Configuration实例conf并且调用.configure()方法加载配置文件
(2) conf.buildSessionFactory()创建一个SessionFactory类sf
(3) sf.openSession()创建一个Session类sess
(4) sess.beginTransaction()创建一个Transaction事务类tx,开启事务
(5) 操作实体
(6) sess.save(entity);保存消息
(7) tx.commit()提交事务
(8) sess.close();关闭Session
(9) sf.close();关闭SessionFactory
也就是说,Hibernate的工作流程是:首先通过configuration对象读取配置文件;解析映射信息,创建StandardSessionFactory;调用openSession打开session;创建事务transaction,之后进行持久化操作;完成后提交事务,关闭session,关闭sessionFactory。
五、 核心接口之Configuration
1) 接口介绍
Configuration接口的作用是对Hibernate进行配置,以及对他进行启动,在Hibernate的启动过程中,Configuration类的实例首先定位映射文档的位置,读取这些配置,然后创建一个SessionFactory对象
一个org.hibernate.cfg.Configuration实例代表了一个应用程序中Java类型到SQL数据库映射的完整集合。Configuration被用来构建一个不可变的SessionFactory,映射定义则由不同的XML映射定义文件编译而来。
2) Configuration有以下几个方面的操作函数
(1)为Configuration指定映射文件
你可以直接实例化Configuration来获取一个实例并为他指定XML映射定义文件 如果映射定义文件在类路径中 请使用addResource()
Configuration cfg = new Configuration().addResource("com/demo/hibernate/beans/User.hbm.xml");
(2)为Configuration指定持久化类
一个替代的方法是指定被映射的类 让Hibernate帮你寻找映射定义文件
Configuration cfg = new Configuration().addClass(com.demo.hibernate.beans.User.class);
Hibernate将会在类路径中需找名字为/com/demo/hibernate/beans/User.hbm.xml 映射定义文件 消除了任何对文件名的硬编译
(3)为Configuration指定配置属性
Configuration也允许指定配置属性
Configuration cfg =new Configuration().addClass(com.demo.hibernate.beans.User.class)
setProperty("hibernate.dialect","org.hibernate.dialect.MySQLInnoDBDialect")
setProperty("hibernate.connection.datasource","java:comp/env/jdbc/test")
setProperty("hibernate.order_update","true");
六、 核心接口之SessionFactory
接口SessionFactory使用工厂设计模式。通过SessionFactory对象可以获取Session对象,Hibernate4已经将configuration的buildSessionFactory方法已经划线了,说明已经过时了,不过这不影响我们web开发人员使用(如果不追求极致深层次的话)。
参看hibernate源码。以及API帮助文档,发现Hibernate4新增了一个接口ServiceRegistry,所有基于Hibernate的配置或者服务都必须统一向这个ServiceRegistry注册后才能生效。所以不难看出 Hibernate4的配置入口不再是Configuration对象,而是ServiceRegistry对象,Configuration对象将通过ServiceRegistry对象获取配置信息。使用了Builder模式创建一个ServiceRegistry对象,可以看到源码org.hibernate.service.ServiceRegistryBuilder这个类。
具体获取如下:
import org.hibernate.HibernateException;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
public class Test {
private static Configuration configuration = null;
private static SessionFactory sessionFactory = null;
private static ServiceRegistry serviceRegistry = null;
public static void main(String[] args) {
try {
configuration = new Configuration().configure();
serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
} catch (HibernateException e) {
e.printStackTrace();
}
}
}
七、 核心接口之Session
1) Session介绍
Session:是应用程序与数据库之间的一个会话,是hibernate运作的中心,持久层操作的基础。持久化对象的生命周期、事务的管理、数据库的查询、存取都与Session息息相关。Hibernate在操作数据库之前必须先取得Session对象,相当于JDBC在操作数据库之前必须先取得Connection对象一样。
Session对象不是线程安全的(ThreadSafe),一个Session对象最好只由一个单一线程来使用。
2) Session创建
Session对象是通过SessionFactory构建的,有两种方式分别是:getCurrentSession()或者openSession(),在Spring的管理中我们可以这样获取Session:
@Autowired
private SessionFactory sessionFactory;
public Session getSession() {
return sessionFactory.getCurrentSession();
}
@Override
public T save(T entity){
Session session = getSession();
session.save(entity);
return entity;
}
3) 需要注意点
(1)openSession和getCurrentSession的区别?
*openSession必须关闭,currentSession在事务结束后自动关闭
*openSession没有和当前线程绑定,currentSession和当前线程绑定
如果使用currentSession需要在hibernate.cfg.xml文件中进行配置:
*如果是本地事务(jdbc事务)
<propertyname="hibernate.current_session_context_class">thread</property>
*如果是全局事务(jta事务)
<propertyname="hibernate.current_session_context_class">jta</property>
全局事务:资源管理器管理和协调的事务,可以跨越多个数据库和进程。资源管理器一般使用XA 二阶段提交协议与“企业信息系统”(EIS) 或数据库进行交互。
本地事务:在单个 EIS或数据库的本地并且限制在单个进程内的事务。本地事务不涉及多个数据来源。
(2)和jdbc的联系
获取Session对象后,Hibernate内部并不会获取操作数据库的java.sql.Connection对象,而是等到Session对象真正需要对数据库进行CRUD等操作时,才会从数据库连接池中获取java.sql.Connection对象。
而关闭Session对象时,则是将java.sql.Connection对象返回连接池,而不是直接关闭java.sql.Connection对象。
八、 核心接口之Transaction
摘自-《开源中国》黄勇的文章《Transaction 那点事儿》,
九、 核心接口之Query
Session session = getSession();
String hql = null;
hql = "from Authorization where serviceId ='"+serviceId+"'";
Query query = session.createQuery(hql);
Authorization authorization = (Authorization) query.uniqueResult();
return null;
上面代码只是为了说明Query这个接口的用法,具体的详细内容还要在实践中去获得,这里就不详细介绍了。
十、 核心接口之Criteria
Hibernate进行软件开发进行数据查询时,主要基于HQL(Hibernate 面向对象的查询语言,语法类似SQL)、Criteria(面向对象的条件查询对象)、SQL(原生态SQL语句)几种方式。
Criteria 是一个完全面向对象,可扩展的条件查询API,通过它完全不需要考虑数据库底层如何实现、SQL语句如何编写,是Hibernate框架的核心查询对象。Hibernate 定义了CriteriaSpecification接口规范用来完成面向对象的条件查询,Criteria就是CriteriaSpecification的子接口。
Criteria与Session绑定,其生命周期跟随着Session结束而结束,使用Criteria时进行查询时,每次都要于执行时期动态建立物件,并加入各种查询条件,随着Session的回收,Criteria也跟着回收。
Session session = getSession();
Criteria criteria = session.createCriteria(clazz);
Criteria 和 DetachedCriteria (Criteria 和 DetachedCriteria 的主要区别在于创建的形式不一样, Criteria 是在线的,是由Hibernate Session 进行创建的;而 DetachedCriteria 是离线的,创建时无需Session)均可使用Criterion 和Projection 设置查询条件。可以设置 FetchMode( 联合查询抓取的模式 ) ,设置排序方式。对于 Criteria 还可以设置 FlushModel(冲刷 Session 的方式)和 LockMode (数据库锁模式)。
Criterion 是 Criteria 的查询条件。Criteria提供了 add(Criterion criterion) 方法来添加查询条件。
Criterion 的实例可以通过 Restrictions 工具类来创建,Restrictions 提供了大量的静态方法,如 eq (等于)、 ge (大于等于)、 between 等来方法的创建 Criterion 查询条件(SimpleExpression 实例)
Criterion criterion1 = Restrictions.like(“name”,”李%”);
Criterion criterion2 = Restrictions.like(“id”,new Integer(1),new Integer(10));
criteria.add(criterion1);
criteria.add(criterion2);
十一、 Hibernate中对象的三种状态
1. 瞬时态
hibernate中什么时候的对象为瞬时态呢,当我们new 一个对象时,还没有save时,它就是瞬时态的,当我们delete一个对象时,它也是瞬时态了,因为此时,他们在数据库中没有对应的记录存在。两点特征:
1)不在Session的缓存中,不与任何的Session实例相关联
2)在数据库中没有与之相对应的记录
2. 持久态
当我们save一个对象时,这个对象会保存到数据库,同时也会缓存在session中,同时,当我们get(),load(),updateOrSave()一个对象时,也会将这个对象缓存在session中,这时缓存中的对象与数据库是同步的,也就是持久态的,任何一方的改变都会同步更新。两点特征:
1)在Session的缓存中,与Session实例相关联。
2)在数据库中存在与之相对应的记录
3. 游离态
当对象从持久态转变为另一状态时,这个状态就是游离态了。比如:session.close(),session.evict()对象时,对象从session缓存中清除,数据库中有数据,缓存中没有数据,因为数据库中有数据,所以它是可以再被持久化的.两点特征:
1)不在Session的缓存中,不与任何Session实例相关联。
2)在数据库中存在与之相对应的记录(前提是没有其他Session实例删除该条记录)。