1 Hibernate概述
Hibernate是Java世界中使用最广泛的数据持久化框架,使用ORM(对象关系映射)模式简化关系型数据库的的数据增删改查功能。
1.1 数据持久化
数据持久化就是将内存中的数据模型转换为存储模型,以及将存储模型转换为内存中的数据模型的统称。数据模型可以是任何数据结构或对象模型,存储模型主要是关系型数据库,还可以是XML、二进制流等。在Java中提供了JDBC组件来实现对象和数据库之间的持久化。
1.2 ORM框架
(1)JDBC的不足
直接使用JDBC开发具有以下问题:开发效率低、代码冗余高和重复性工作多。为了减少数据库开发中的管道代码,把开发精力集中在解决业务问题上,Java世界出现了很多的持久化框架,比较著名的有:Hibernate、MyBatis、TopLink(Oracle商业产品)等。
(2)ORM框架
对象关系映射(ORM,Object Relation Mapping)是持久化框架经常采用的技术模式。Object是指编写程序的时候,以面向对象的方式处理数据;Relation是指保存数据的时候,以关系型数据库的方式存储;而ORM框架则通过映射信息自动完成Java对象与数据库表之间的存取。
1.3 Hibernate
Hibernate是Java世界最经典的对象关系映射框架,堪称ORM技术的典范,简化了JDBC繁琐的编码,大大增加程序可靠性。
Hibernate的创始人Gavin King是EJB3.0专家委员会成员,EJB 3.0 JPA规范的主要制定者,是JBoss核心开发者之一著有《Hibernate in Action》一书。
2 Hibernate起步
下面通过简单的示例,介绍Hibernate的基本用法。
(1)导入hibernate依赖
代码语言:javascript复制 <!-- mysql jdbc驱动,或替换为Oracle的jar包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.8</version>
</dependency>
<!-- Hibernate 3.6.10, Core Annotation -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.6.10.Final</version>
</dependency>
<!-- 为Hibernate 提供支持 -->
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.9.0.GA</version>
</dependency>
(2)构建Hibernate主配置文件
在项目“类路径”下,添加hibernate.cfg.xml配置文件.
该文件主要配置JDBC连接、SQL方言和实体映射文件的位置。
代码语言:javascript复制<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 数据库连接配置 -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/MyCinema</property>
<property name="connection.username">root</property>
<property name="connection.password">1234</property>
<!-- SQL方言(Dialect)配置 -->
<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<!-- 是否显示执行的SQL语句 -->
<property name="show_sql">true</property>
<!-- 是否格式化SQL语句 -->
<property name="format_sql">true</property>
<!-- 配置实体映射文件路径 -->
<mapping resource="mapping/Category.hbm.xml"/>
</session-factory>
</hibernate-configuration>
(3)编写实体映射文件
在项目类路径下创建mapping文件夹,在其下创建“实体映射文件”,描述Java对象和数据库表的对应关系。
实体映射文件中元素功能如下:
- class元素用于声明Java类和数据库表的映射关系
2)id 元素用于声明主键属性映射,name属性用于指定对象属性名,column用于指定对应的表字段名
3)id中的generator子元素用于指定主键的生成策略,常见的策略有identity(自增长字段)、sequence(Oracle序列)、native(自适应)、uuid(全局唯一编号)等。
4)property元素用于声明普通属性映射
代码语言:javascript复制<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="demo.entity">
<class name="Category" table="CATEGORY">
<id name="id" column="ID">
<generator class="identity" />
</id>
<property name="name" column="NAME"/>
</class>
</hibernate-mapping>
(4)编写查询功能
要实现查询Hibernate需要使用以下几个重要对象
- Configuration:用于加载配置信息(hibernate.cfg.xml),是SessionFactory的工厂。
- SessionFactory:Session的工厂,用于维护数据库连接池和二级缓存。在一个应用程序中,一般只需要一个SessionFactory对象,应用单例模式维护其唯一性。
- Session:代表Hibernate与数据库之间的一次回话,维护数据连接和一级缓存,该对象不是线程安全的,应该每次使用前创建用完关闭,建议保存在方法或请求级别。
- Query:用于执行HQL查询语句的工具对象,由Session对象创建。
public static void main(String[] args) {
Configuration cfg = new Configuration(); //创建Configuration对象
cfg.configure(); //读取配置文件
SessionFactory factory = cfg.buildSessionFactory(); //创建SessionFactory对象
Session session = factory.openSession(); //获取Session
Query query = session.createQuery("from Category"); //创建查询对象
List<Category> list = query.list(); //执行查询
for(Category c : list){
System.out.println(c.getName());
}
session.close(); //关闭Session
}
3 Hibernate中持久化对象的三种状态
在Hibernate框架中的持久化对象有三种状态:瞬时状态(临时状态)、持久状态、游离状态。
(1)瞬时状态(Transient)
通过new创建对象后,对象并没有立刻持久化,它并未与数据库中的数据有任何关联,此时Java对象的状态为瞬时状态。
Session对于瞬时状态的Java对象是一无所知的,当对象不再被其他对象引用时,它的所有数据也就丢失了,对象将会被Java虚拟机按照垃圾回收机制处理。
(2)持久状态(Persistent)
当对象与Session关联,被Session管理时,它就处于持久状态。处于持久状态的对象拥有数据库标识(数据库中的主键值)。
那么,对象是什么时候与Session发生关联的呢?有两种方法:
第一种,通过Sesison的查询接口,或者get()方法,或者load()方法从数据库中加载对象的时候,加载的对象是与数据库表中的一条记录关联的,此时对象与加载它的Session发生关联;
第二种,瞬时状态的对象,通过Session的save()方法或SaveOrUpdate()方法时,Java对象也与Session发生关联。
对于处于持久状态的对象,Session会持续跟踪和管理它们,如果对象的内部状态发生了任何变更,Hibernate会选择合适的时机(如事务提交时)将变更固化到数据库中。
(3)游离状态(Detached)
处于持久状态的对象,脱离与其关联的Session的管理后,对象就处于游离状态。
处于游离状态的对象,Session无法保证对象所包含的数据与数据库中的记录一直,因为Hibernate已经无法感知对该对象的任何操作。
Session提供了两个方法(update()、merge()),将处于游离状态的对象,与一个新的Session发生关联。
Hibernate中对象的三种状态的相互转换机制如下图所示。
4 实现DAO模式
(1)封装一个用于构建Session对象的工具类
为维护SessionFactory的全局单例,建议创建一个HibernateUtil工具类对其进行封装。
代码语言:javascript复制public class HibernateUtil {
private static SessionFactory factory; //确保单例
static{
Configuration cfg = new Configuration();
cfg.configure();
factory = cfg.buildSessionFactory();
}
public static Session openSession(){
return factory.openSession();
}
}
(2)添加DAO组件并实现增删改查功能
代码语言:javascript复制public class CategoryDaoImpl implements CategoryDao {
public List<Category> getAll() {
Session sess = HibernateUtil.openSession();
try{
return sess.createQuery("from Category").list();
}finally{
sess.close();
}
}
public Category fetchById(int id) {
Session sess = HibernateUtil.openSession();
try{
return (Category)sess.get(Category.class, id);
}finally{
sess.close();
}
}
public void add(Category entity) {
Session sess = HibernateUtil.openSession();
Transaction tx = null;
try{
tx = sess.beginTransaction();
sess.save(entity);
tx.commit();
}catch(RuntimeException ex){
if(tx!=null)
tx.rollback();
throw ex;
}finally{
sess.close();
}
}
public void update(Category entity) {
Session sess = HibernateUtil.openSession();
Transaction tx = null;
try{
tx = sess.beginTransaction();
sess.update(entity);
tx.commit();
}catch(RuntimeException ex){
if(tx!=null)
tx.rollback();
throw ex;
}finally{
sess.close();
}
}
public void delete(int id) {
Session sess = HibernateUtil.openSession();
Transaction tx = null;
try{
tx = sess.beginTransaction();
sess.delete(sess.get(Category.class, id));
tx.commit();
}catch(RuntimeException ex){
if(tx!=null)
tx.rollback();
throw ex;
}finally{
sess.close();
}
}
}