分类: Java
2008-08-01 14:59:21
在JAVA应用中建立Hibernate的步聚
建立Hibernate的配置文件
创建持久化类
创建对象-关系映射文件
通过Hibernate API访问数据库
Hibernate应用程序的结构
Hibernate的配置文件
Hibernate配置信息由一个XML文件来指定,常用的配置参数:
建立持久化类
持久化类必需符合JavaBean的规范,以及包含一些属性,以及与之对应的getXXX()及setXXX的方法。
持久化类必需要有一个id属性用于唯一标识该类的对象。在面向对象的术语中这个id属性 又被 称之为对象标识符(OID,Object Identifier),一般用整数表示。
Hibernate要求持久化类必需提供一个不带参数的默认构造 方法。
参见工程示例:Customer.java
建立数据库Schema
Create table Customer(
Id bigint not null primary key,
….
);
需要为对应实体类对应的表建立主键。
建立对象与关系映射文件
映射文件的名称及存放位置最好与持久化类的名称及位置保持一致。
Hbm文件:
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"">
…
Id元素映射OID
name属性:指定持久化类的属性名字。
column属性:指定持久化类的属性映射的表的字段名。
type属性:指定与类的属性映射类型。类型可以指定为hibernate类型或java类型 hibernate类型 是java类型 与SQL类型的桥梁。
Java类型、hibernate类型、及SQL类型之间的对应关系
采用XML文件配置对象-关系映射的优点
Hibernate即不会渗透到上层的域模型中,也不会渗透到下层的数据模型中。
软件开发人员可以独立的设计域模型,而必强迫遵守任何规范。
数据库设计人员也可以独立的设计数据 模型,而不必强迫遵守任何规范。
对象-关系的映射不依赖任何的程序代码,如果需要修改对象-关系的映射,只需要修改XML文件,而不需要修改任何的程序代码,提高了软件的灵活性,并且更加容易维护。
通过Hibernate API来操纵数据库
通过Hibernate API来操纵数据库
通过Hibernate API来操纵数据库
初始化Hibernate
通过Hibernate的Session接口来操作数据库:
保存持久化对象
更新持久化对象
加载持久化对象
删除持久化对象
检索持久化对象
Hibernate的初始化
private static SessionFactory sessionFactory = null;
static{
try{
//根据Hibernate的配置文件建立一个Configration的实例
//其中configfile为配置文件类路径
Configration config = new Configration(configfile);
//建立SessionFactory实例
sessionFactory = config.buildSessionFactory();
}catch(Exception e){
e.printStackTrance();
}
}
SessionFactory接口
一个SessionFactory的实例对应一个数据存储源,应用从SessionFactory中获取Session的实例。
SessionFactory具有以下几个特点:
它是线程序安全的,意味着它的同一个实例可以被 多个线程共享。
它是重量级的Java对象,这意味着它不能随意的创建或销毁。如果应用只有一个数据库,只需要建立一个SessionFactory的实例就可以了,应当在应用程序初始化时就建立,如果需要访问多个数据库,则需要建立多个SessionFactory实例。
Session接口
Session接口是Hibernate应用最为广泛的接口。
Session也被称为持久化管理器,它提供了持久化相关的操作,例如:添加,删除,更新,载入,查询对象等。
Session具有以下几个特点:
它不是线程安全的,因此在设计软件时,应当避免多个线程序共享同一个Session实例。
它是一个轻量级的对象,所谓轻量级是指对象的建立和销毁不需要消耗很多的系统资源,在应用程序中你可以经常建立和销毁Session对象。
Session接口常用的方法
Session接口有提供用于操作数据库的一些常用方法:
Save:把java对象保存到数据库中。
Update:更新数据库中的java对象。
Delete:删除数据库中的java对象。
Load:从数据库中加载java对象
Find:从数据库中查找java对象。
用session来执行事务的流程
Transaction tx = null
try{
//开始一个事务
tx = session.beginTransaction();
//执行事务
….
//提交事务
tx.commit();
}catch(Exception e){
//回滚事务
tx.rollback();
}
name:设定待映射的持久化类的属性名。例如:Oder类中的customer属性。
column:设定和持久化类的属性对应的表的外键,例如:Orders表中的Customer_ID
class:设定持久化类的该属性的类型,例如:Customer
class=“Customer”/>
注意:使用多对一时,应当在多的一方使用
name设定待映射的持久化的类的属性名,例如:Customer中的orders
cascade用于设定级联的级别,例如:save-update表示级联保存和更新。
inverse:当设为true时,表示在双向关联中,当前端为镜像端。
table:用于映射多对多时,表示对应的关联表。
cascade属性
映射category一对多双向自身关联
Category类图
Category的表的结构
映射一对多自身双向关联
column=“CATEGORY_ID”
class=“vo.Category”
/>
casecade=“all-delete-orphan”
inverse=“true”
>
映射一对一双向关联
一对一关可分为:共享主键一对一关联,及使用主键与外键实现一对一双向关联。
参见示例:StudClass StudGroup
映射多对多双向关联
产品类别:Category
casecade=“save-update” inverse=“true”>
产品:Product
>
nHibernate的缓存分为:
¨一级缓存,单个会话的对象缓存。
¨二级缓存,可插拔的缓存插件
n当Session加载或保存一个对PO时,PO将被Session缓存。
n当再次通过Session加载相同OID的PO时,Hibernate将直接从Session的缓存中获取。
n当Session关闭时,缓存将被清空。
//第一次加载时将产生SQL访问数据库
Customer cusa = (Customer)session.get(Customer.class,
//第二次加载同样的Customer时Hibernate将从Session中获取
Customer cusb = (Customer)session.get(Customer.class,
//cusa和cusb应当是同一对象
If(cusa == cusb)System.out.println(“同一个对象!”);
//缓存被清空
session.close();
n减少访问数据库的频率。
应用程序从内存中获取对象明显快于从数据库中查找。
n保证缓存中的对象与数据库相关的记录同步。
当处于缓存中的PO的属性发生改变时,Session不会立即更新数据库,它可以将多次更新合并处理后产生一条更新语句。
Customer customer = (Customer)session.load(Customer.class, 1);
customer.setName("jack");
customer.setName("mike");
//以上只会产生一条sql语句。
update Customer set name = 'mike' ...
nHibernate会在特定的时间自动同步缓存与数据库
¨当提交事务时
¨当执行session的查询方法时
¨当执行session.flush时
n注意:关闭Session时,Hibernate不会执行缓存同步。
n二级缓存是一个可以插拔的缓存插件,它由SessionFactory负责管理,由于SessionFactory对象的生命周期和应用程序的生命周期对应,因此二级缓存是进程范围或群集范围的缓存。
n缓存中存放的是对象的散装数据而不是对PO的引用。
n二级缓存是可选的,可以在每个类或每个集合的粒度上配置二级缓存。
nHibernate默认使用EhCacheProvider提供二缓存支持,可通过配置参数hibernate.cache.provider_class设置其它的缓存器。
n通过在
n配置属性:
¨usage用于指定缓存的策略
¨region指定缓存对象存放的区域名,默认为类名或集合名。
¨include表示缓存对象的种类all所有的,non-lazy不包含延迟加载的。
nread-only缓存的对象只可以读取。
nread-write缓存的对象可读写。
nnonstrict-read-write非严格的读写,适合于并发更新的情况非常小。
ntransaction适用于jta事务范围内的缓存
//Customer使用读写二级缓存
…
//执行下面一条时,Hibernate将产生一条SQL
Customer cus = (Customer)session.get(Customer.class,
//关闭Session的一级缓存清空,但二级缓存中仍保留有cus的数据
session.close();
…
//打开session再次获取Customer时,检查控制台并未产生一条SQL
//Hibernate此时并未从数据库中获取数据而是从二级缓存中获取。
Customer cus = (Customer)session.get(Customer.class,
PO状态
n临时状态(transient):刚刚用new语句建立,还没有被持久化,不处于session的缓存中。
n持久化对象(persistent):已经被持久化,加入到session的缓存中。
n游离状态(detached):已经被持久化,但不再处于session的缓存中
PO状态转换
Session session = sf.getCurrentSession();
Transaction tx = session.beginTransaction();
Customer cus = new Customer();//临时状态
cus.setName("Tony");
session.save(cus);//持久化状态
tx.commit();
session.close();
//修改游离态的Customer对象
cus.setName("ModTonyName");
Session session2 = sf.getCurrentSession();
Transaction txb = session2.beginTransaction();
session2.update(cus);//关联游离态的对象
txb.commit();//保存更新
session2.close();
。 nHibernate对于PO及集合属性的数据采用延迟加载的策略。
n对于PO初始化时并不加载属性,只有在访问时才加载数据。
n对于set集合,只有当访问集合元素时才执行加载。
n注意:只有持久化状态下的对象才可以执行延迟加载。
n优点
¨由应用程序决定需要加载那些对象,可以以避免执行多余的select语句,避免加载应用程序不需要的访问对象。因此能提高检索性能,并能节省内存空间。
n缺点
¨应用程序如果希望访问游离的代理类实例,必需保证它在持久化状态时已被初始化。