前言:本文用一个简单的Hibernate应用程序例子来引领初学者入门,让初学者对Hibernate的使用有一个大致的认识。本文例子使用了MySQL数据库、Maven管理工具、Eclipse开发工具,创建的项目是Maven项目但是本质上只是用了Java SE的东西。1.在Maven项目中引入Hibernate库
1.在Maven项目中引入Hibernate库
我们可以在Maven官网上搜索Hibernate库,选择Hibernate版本,复制Maven依赖代码到pom.xml文件引用Hibernate。由于当前Hibernate的最新版是4.3.8.Final所以我的引用如下:
<!-- 依赖项定义 -->
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.8.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
</dependencies>
如果你没有使用Maven,你也可以到Hibernate官网下载Hibernate引用到项目里,不过我在这里强烈推荐大家使用Maven管理项目,因为Maven管理很方便,它不需要你去网上找项目依赖的Jar文件,一个依赖配置就搞定。并且Maven的官网很强大几乎所有的Java开源项目都可以在这里找到!下面提供Maven的官网和Hibernate的官网:Maven:http://mvnrepository.com/ Hibernate:http://hibernate.org/
2.搭建数据库环境(MySQL)
为了测试我在本地计算机安装了Linux虚拟机,并在虚拟机中安装了MySQL数据库。下面是我新建的测试表(tb_teacher):
CREATE TABLE tb_teacher
(
id bigint NOT NULL auto_increment COMMENT 'ID',
no varchar(10) NOT NULL COMMENT '教师编号',
name varchar(50) NOT NULL COMMENT '教师姓名',
sex char(1) NOT NULL COMMENT '教师性别',
job_title varchar(50) NOT NULL COMMENT '职称',
PRIMARY KEY (id)
) COMMENT = '教师信息表';
3.设置Hibernate配置文件(hibernate.cfg.xml)
hibernate.cfg.xml配置文件需要放到项目ClassPath根路径,hibernate.cfg.xml配置文件是Hibernate的核心配置文件,其作用是:设置数据源、配置Hibernate属性、设置映射文件(*.hbm.xml)等。下面是一个简单的配置:
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 设置MySQL的数据库路径、用户名、密码 -->
<property name="hibernate.connection.url">jdbc:mysql://192.168.10.201:3306/Study</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">lizhiwei</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Hibernate配置 -->
<property name="connection.pool_size">1</property>
<property name="show_sql">true</property>
<property name="current_session_context_class">thread</property>
<property name="hibernate.cache.use_second_level_cache">false</property>
<property name="hibernate.format_sql">true</property>
<!-- 设置实体类到数据库的映射文件 -->
<mapping resource="model/Teacher.hbm.xml"/>
</session-factory>
</hibernate-configuration>
对于上面的配置的说明:
- hibernate.dialect:设置数据库方言,我使用的MySQL数据库就用MySQL数据库的方言。
- connection.pool_size:设置数据库连接池大小。
- current_session_context_class:与SessionFactory.getCurrentSession()相关,如果得到一个Session是调用这个方法(并非openSession())那么会使用这个属性。
- show_sql:配置是否显示Hibernate操作数据库的SQL,调试时非常有用。
- hibernate.format_sql:与show_sql配合使用,用于格式化打印的SQL。
- hibernate.cache.use_second_level_cache:是否使用Hibernate的二级缓存,关于二级缓存的使用后面的章节会讲到。
- <mapping resource="model/Teacher.hbm.xml"/>:设置实体类与数据库表的映射文件,关于这个映射文件的作用和内容会在下面讲到。
4.创建实体类与其映射文件(Teacher.hbm.xml)
实体类的创建要与前面新建的表(tb_teacher)对应,下面是我的实体类(Teacher.java):
package model;
/**
* 教师信息表
* */
public class Teacher
{
/** ID */
private Long id;
/** 教师编号 */
private String no;
/** 教师姓名 */
private String name;
/** 教师性别 */
private String sex;
/** 职称 */
private String job_title;
//省略setter、getter、toString...
}
创建好实体类后,Hibernate并不知道这个实体类会与数据库中的tb_teacher表对应,所以还要创建一个配置文件告诉Hibernate实体类与数据库表的映射细节,配置文件如下(Teacher.hbm.xml):
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="model">
<class name="Teacher" table="tb_teacher">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="no" column="no"/>
<property name="name" column="name"/>
<property name="sex" column="sex"/>
<property name="job_title" column="job_title"/>
</class>
</hibernate-mapping>
注意:这个配置文件的位置要与Teacher.java类在同一个文件夹下,并且并命必须是:[实体类名].hbm.xml。但这不是不必需的,这是Hibernate默认的规则,若要改变就要在hibernate.cfg.xml中加上额外的配置。
对于Teacher.hbm.xml配置的说明:
- package="model":用于设置实体类的命名空间。
- name="Teacher" table="tb_teacher":设置实体类名与数据库表名的映射。
- <id name="id" column="id">:设置实体类的属性与数据库的主键的映射。
- <generator class="native"></generator>:设置主键的生成方式,如:自定义、序列、自增长等。native表示根据底层数据库对自动生成标识的能力自动选择。
- <property name="no" column="no"/>:设置实体类属性与数据库字段的映射关系。
5.编写测试代码(Holle World)
编写测试代码必然会用到Hibernate API,这里我先看看测试代码和其运行的效果,再简单的分析一下Hibernate API的接口与其使用,代码如下(Test01.java):
package test;
import model.Teacher;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
@SuppressWarnings("deprecation")
public class Test01
{
public static void main(String[] args)
{
Configuration cfg = new Configuration();
cfg.configure();
ServiceRegistry sr = new ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry();
SessionFactory sf = cfg.buildSessionFactory(sr);
System.out.println("连接数据库");
Session session = sf.openSession();
Teacher teacher =(Teacher) session.get(Teacher.class, new Long(1));
System.out.println(teacher);
session.close();
System.out.println("关闭数据库");
System.exit(0);
}
}
这段代码的作用是从数据库中找到ID==1的Teacher记录并打印在控制台,运行效果如下(省略了部分Hibernate日志):
连接数据库
Hibernate:
select
teacher0_.id as id1_0_0_,
teacher0_.no as no2_0_0_,
teacher0_.name as name3_0_0_,
teacher0_.sex as sex4_0_0_,
teacher0_.job_title as job_titl5_0_0_
from
tb_teacher teacher0_
where
teacher0_.id=?
tb_teacher [id=1, no=000001, name=教师1, sex=女, job_title=初级教师]
关闭数据库
从打印结果中可以看出数据库中的记录“tb_teacher [id=1, no=000001, name=教师1, sex=女, job_title=初级教师]”,还可以看到Hibernate查询所用的SQL语句。
6.Hibernate API接口简介
(1)Hibernate核心接口介绍
- Configuration接口:配置Hibernate,启动Hibernate,创建SessionFactory对象。
- SessionFactory接口:初始化Hibernate,充当数据源的代理,创建Session对象。
- Session接口:负责保存、更新、删除、加载和查询对象。
- Transaction接口:事务管理接口。
- Query和Criteria接口:用于执行数据库查询。
- Callback接口:Hibernate事件回调接口。
(2)Configuration接口
Configuration接口的作用是对Hibernate进行配置,以及对它进行启动。在Hibernate的启动过程中,Configuration类实例首先定位映射文档的位置,读取这些配置,然后创建一个SessionFactory对象。
Configuration对象的作用是除了有读取配置文件的功能,还能创建SessionFactory对象。通常,一个应用程序会创建一个Configuration对象,然后利用Configuration实例建立唯一的SessionFactory实例,这就意味着Configuration对象只存在于系统的 初始化阶段,然后所有的持久化操作都能通过这个唯一的SessionFactory实例来进行。
Configuration对象只有在Hibernate 进行初始化的时候才需要创建,当使用Configuration对象的实例创建了SessionFactory对象的实例后,其配置信息已经绑定在他返回的SessionFactory对象实例中。因此,一般情况下,得到SessionFactory对象后,Configuration对象的使命就结束了。
重要方法:
public Configuration configure (*)
在参数中指定要加载的配置文件
public SessionFactory buildSessionFactory()
根据配置文件实例化一个新的SessionFactory对象,这个SessionFactory将是不可变的,所以在创建了SessionFactory对象后,对Configuration对象作出的所有修改不会影响以前创建出的SessionFactory对象。
(3)SessionFactory接口
这里用到了一个设计模式—工厂模式,用户程序从工厂类SessionFactory中取得Session的实例。SessionFactory不是轻量级的!它的设计者的意图是让它能在整个应用共享。典型地来说,一个项目通常只需要一个SessionFactory就够了,但是当你的项目要操作多个数据库时,那你必须为每个数据库指定一个SessionFactory。一个SessionFactory实例对应一个数据存储源,应用从SessionFactory中获得Session实例。它具有如下特点:
- 它是线程安全的,这意味着它的同一个实例可以被应用的各个线程共享。
- 它是重量级的,这意味着不能随意创建或销毁它的实例。
- 之所以说SessionFactory是重量级的,是因为它需要一个很大的缓存,用来存放预定义的SQL语句以及映射元数据等。用户还可以为SessionFactory配置一个缓存插件,这个缓存插件被称为Hibernate的第二级缓存,该缓存用来存放被工作单元读过的数据,将来其它工作单元可能会重用这些数据,因此这个缓存中的数据能够被所有工作单元共享,一个工作单元通常对应一个数据库事务。SessionFactory接口负责初始化Hibernate。
重要方法:
public Sessioin openSession()
创建一个数据库连接,并把他放在Session对象中,并返回
public Session openSession(Connection connection)
创建一个Session对象,并把参数给出的 connection对象放在其中
public boolean isClosed()
判断当前SessionFactory对象是否关闭了
public void close()
关闭SessionFactory以及释放所有的SessionFactory涉及到的资源(缓存,数据库连接池等)但在调用此方法之前,应该确定没有当前对象创建的 Session没有关闭
(4)Session接口
Session接口对于Hibernate 开发人员来说是一个最重要的接口。然而在Hibernate中,实例化的Session是一个轻量级的类,创建和销毁它都不会占用很多资源。这在实际项目中 确实很重要,因为在客户程序中,可能会不断地创建以及销毁Session对象,如果Session的开销太大,会给系统带来不良影响。Session具有一下特点:
- 不是线程安全的,因此在设计软件架构时,应该避免多个线程共享同一个Session实例。
- Session实例是轻量级的,所谓轻量级,是指它的创建和销毁不需要消耗太多的资源。这意味着在程序中可以经常创建和销毁Session对象,例如为每个客户请求分配单独的 Session实例,或者为每个工作单元分配单独的Session实例。
- Session有一个缓存,被称为Hibernate的第一级缓存,它存放被当前工作单元加载的对象。每个Session实例都有自己的缓存,这个Session实例的缓存只能被当前工作单元访问。Session接口负责执行被持久化对象的CRUD操作 (CRUD的任务是完成与数据库的交流,添加、更新、删除、加载和查询对象,包含了很多常见的SQL语句)。
在Hibernate的设计者的头脑中,他们将session看作介于数据连接与事务管理一种中间接口。我们可以将session想象成一个持久对象的缓冲区,Hibernate能检测到这些持久对象的改变,并及时刷新数据库。我们有时也称Session是一个持久层管理器,因为它包含这一些持久层相关的操作,诸如存储持久对象至数据库,以及从数据库中获得它们。请注意,Hibernate 的session不同于JSP应用中的HttpSession。以后会将HttpSesion对象称为用户session。
重要方法:
public Transaction beginTransaction()
在数据库中重新开始一个事务
public Transaction getTransaction()
返回和当前session联系的Transaction对象
public Connection connection close()
结束当前的Session对象
public void clear()
清空Session,清除所有保存在当前Session缓存中的实体对象,终止所有正在执行的方法(eg: save() , update() ,delete() .....)
public Serializable save(Object object)
对当前参数指定的对象进行持久化(系统会首先赋予参数对象一个标识符OID),他相当于insert语句 后面在详细介绍
public Connection connection()
得到当前Session 中包含的Connection对象。
public boolean contains(Object object)
判断参数给出的对象(持久化类)是否在当前Session的缓存中
public void evict(Object object)
将参数给出的Object从当前Session对象类中删除,使这个对象从持久态变成游离态,这种状态的改变不会引起对数据库的同步
public Object load(Class theclass ,Serializable id)
返回第一个参数指定类对应的表中,第二个参数指定的行(第二个参数就是要取得对象的OID,他对应表中主键列的值)
public void update(Object object)
更新一个对象到数据库中
public void delete (Object object)
从数据库中删除和参数指定的对象对应的记录
public Object get(Class class,Serializable id)
和load()方法一样区别在于,如果数据库表中没有对应的记录,get()方法返回null,load()方法将报异常
(5)Transaction接口
Transaction接口是一个可选的API,你可以选择不使用这个接口,取而代之的是Hibernate的设计者自己写的底层事务处理代码。它将应用代码从底层的事务实现中抽象出来——这可能是一个JDBC事务(Connection事务,基于数据库的事务),一个JTA事务(基于分布式的事务,同时管理多个数据库之间的事务)或者甚至是一个公共对象请求代理结构(CORBA)——允许应用通过一组一致的API控制事务边界。这有助于保持Hibernate应用在不同类型的执行环境或容器中的可移植性。
Transaction tx = session.beginTransaction();
注意:使用Hibernate进行操作时(增、删、改)必须显示的调用Transaction(默认:autoCommit=false)。
重要方法:
public void commit()
刷新当前的Session以及结束事务的工作,提交事务
public void rollback()
强迫回滚当前事务
public boolean isActive()
这个事务是否存活
(6)Query和Criteria接口
它们是Hibernate的查询接口,用于向数据库查询对象,以及控制执行查询的过程。query实例封装了一个HQL(Hibernate Query Language)查询语句,HQL是面向对象的,它引用类名及类的属性名,而不是表名及表的字段名。Criteria接口完全封装了基于字符串形式的查询语句,比Query接口更加面向对象,Criteria接口更擅长于执行动态查询。 Query接口让你方便地对数据库及持久对象进行查询,它可以有两种表达方式:HQL语言或本地数据库的SQL语句。Query经常被用来绑定查询参数、限制查询记录数量,并最终执行查询操作。
Criteria接口与Query接口非常类似,它允许你创建并执行面向对象的标准化查询。
值得注意的是Query接口也是轻量级的,它不能在Session之外使用。Session接口的find()方法也具有数据查询功能,但它只是执行一些简单的HQL查询语句的快捷方法,它的功能远没有Query接口强大。
(7)Callback接口
当一些有用的事件发生时—例如持久对象的载入、存储、删除时,Callback接口会通知Hibernate去接收一个通知消息。一般而言,Callback接口在用户程序中并不是必须的,但要在项目中创建审计日志时,可能会用到它。
-------------------------------------------------------------------------------------------------------------------------------