??xml version="1.0" encoding="utf-8" standalone="yes"?>
用于配置Hibernate的接口:Configuration接口
Hibernate核心接口
Configuration接口Q配|Hibernate,Hibernate应用通过Configuration实例来指定对?关系映射文g的位|或动态配|Hibernate的属性,然后创徏SessionFactory对象实例?/p>
SessionFactory接口Q初始化Hibernate,充当数据存储源的代理、创建Session对象?/p>
一个SessionFactory实例对应一个数据存储源QHibernate应用从SessionFactory中获得Session对象实例?/p>
特定Q它是线E安全的Q意味着同一个实例可以被应用的多个线E共享,它是重量U的Q意味着不能随意创徏或销毁实例,一个数据库讉K只需创徏一个实例?/p>
Session接口Q负责保存、更新、删除、加载、查询对?/p>
Session接口被称做持久化理器,每个Session实例都有自已的缓存,用来存放被当前工作单元加载的对象且只能被当前工作单元讉K?/p>
Ҏ,它不是线E安全的Q应该避免多个线E共享同一个Session实例Q它是轻量的,意味着创徏或销毁实例不需要消耗太多的资源Q可以ؓ每个h分配单独的Session实例Q或者ؓ每个工作单元分配单独的Session实例?/p>
Transation接口QHibernate的数据库事务接口Q对底层的事务接口做了封装?/p>
装的底层事务接口:
JDBC API、JTAQJava TransationQAPI、CORBAQCommon Object Request Broker ArchitectureQAPI
通过一致的Transation接口来声明事务边界,有利于应用在不同环境或容器中UL?/p>
Query接口和Criteria接口Q执行数据库查询Q控制执行查询的q程?/p>
Query接口装了一个面向对象的查询语句QHibernate Query Language, HQLQ?/p>
Criteria接口装了基于字W串形式的查询语句,擅长于执行动态查询?/p>
回调接口QInterceptor接口、Lifecycle接口、Validatable接口
当一个对象发生了特定的事Ӟ如加载、保存、更新、删除)QHibernate应用可以通过回调来响应事件?/p>
回调接口按实现方式可分ؓQ?/p>
Lifecycle接口和Validatable接口Q由持久化类来实现接口?/p>
Lifecycle接口Q持久化类的实例能响应被加载、保存、删除的事g?/p>
Validatable接口Q持久化类的实例在被保存前q行数据验证?/p>
Interceptor接口Q不必由持久化类来实现接口。Interceptor实现c负责响应持久化cȝ实例被加载、保存、更新、删除的事g?/p>
映射cd接口QType接口、UserType接口、CompositeUserType接口
Type接口Q表CHibernate映射cdQ用于把域对象映ؓ数据库的关系数据?/p>
Type接口的实现类QPrimitiveTypec,映射Java基本cd。DateTypec,映射Java日期cd?/p>
扩展接口Q?/p>
定制主键的生成策略:IndentifierGenerator接口
定制本地SQL方言QDialect抽象c?/p>
定制~存机制QCache接口、CacheProvider接口
定制JDBCq接理QConnectionProvider接口
定制事务理QTransationFactory接口、Transation接口、TransationManagerLookup接口
定制ORM{略QClassPersister接口及其子接?/p>
定制属性访问策略:PropertyAccesser接口
创徏代理QProxyFactory接口
定制客户化映类型:UserType接口、CompositeUserType接口?/p>
在Hibernate中处理批量更新和扚w删除
扚w更新是指在一个事务中更新大批量数据,扚w删除是指在一个事务中删除大批量数据,以下E序直接通过Hibernate API扚w更新
tx = session.beginTransaction();
Iterator customers=session.find("from Customer c where c.age>0").iterator();
while(customers.hasNext()){
Customer customer=(Customer)customers.next();
customer.setAge(customer.getAge()+1);
}
tx.commit();
session.close();
如果CUSTOMERS表中?万条q龄大于零的记录Q那么Session的find()Ҏ会一下子加蝲1万个Customer对象到内存。当执行tx.commit()ҎӞ会清理缓存,Hibernate执行1万条更新CUSTOMERS表的update语句Q?/p>
update CUSTOMERS set AGE=? ? where ID=i;
update CUSTOMERS set AGE=? ? where ID=j;
…?br />update CUSTOMERS set AGE=? ? where ID=k;
以上扚w更新方式有两个缺点:
(1) 占用大量内存Q必L1万个Customer对象先加载到内存Q然后一一更新它们?/p>
(2) 执行的update语句的数目太多,每个update语句只能更新一个Customer对象Q必通过1万条update语句才能更新一万个Customer对象Q频J的讉K数据库,会大大降低应用的性能?/p>
Zq速释?万个Customer对象占用的内存,可以在更新每个Customer对象后,p用Session的evict()Ҏ立即释放它的内存Q?/p>
tx = session.beginTransaction();
Iterator customers=session.find("from Customer c where c.age>0").iterator();
while(customers.hasNext()){
Customer customer=(Customer)customers.next();
customer.setAge(customer.getAge()+1);
session.flush();
session.evict(customer);
}
tx.commit();
session.close();
在以上程序中Q修改了一个Customer对象的age属性后Q就立即调用Session的flush()Ҏ和evict()ҎQflush()Ҏ使Hibernate立刻Ҏq个Customer对象的状态变化同步更新数据库Q从而立x行相关的update语句Qevict()Ҏ用于把这个Customer对象从缓存中清除出去Q从而及旉攑֮占用的内存?/p>
但evict()Ҏ只能E微提高扚w操作的性能Q因Z有没有使用evict()ҎQHibernate都必L?万条update语句Q才能更?万个Customer对象Q这是媄响批量操作性能的重要因素。假如Hibernate能直接执行如下SQL语句Q?/p>
update CUSTOMERS set AGE=AGE+1 where AGE>0;
那么以上一条update语句p更新CUSTOMERS表中?万条记录。但是Hibernateq没有直接提供执行这Uupdate语句的接口。应用程序必ȝqHibernate APIQ直接通过JDBC API来执行该SQL语句Q?/p>
tx = session.beginTransaction();
Connection con=session.connection();
PreparedStatement stmt=con.prepareStatement("update CUSTOMERS set AGE=AGE+1 "
+"where AGE>0 ");
stmt.executeUpdate();
tx.commit();
以上E序演示了绕qHibernate APIQ直接通过JDBC API讉K数据库的q程。应用程序通过Session的connection()Ҏ获得该Session使用的数据库q接Q然后通过它创建PreparedStatement对象q执行SQL语句。值得注意的是Q应用程序仍焉过Hibernate的Transaction接口来声明事务边界?/p>
如果底层数据库(如OracleQ支持存储过E,也可以通过存储q程来执行批量更新。存储过E直接在数据库中q行Q速度更加快。在Oracle数据库中可以定义一个名为batchUpdateCustomer()的存储过E,代码如下Q?/p>
create or replace procedure batchUpdateCustomer(p_age in number) as
begin
update CUSTOMERS set AGE=AGE+1 where AGE>p_age;
end;
以上存储q程有一个参数p_ageQ代表客Lq龄Q应用程序可按照以下方式调用存储q程Q?/p>
tx = session.beginTransaction();
Connection con=session.connection();
String procedure = "{call batchUpdateCustomer(?) }";
CallableStatement cstmt = con.prepareCall(procedure);
cstmt.setInt(1,0); //把年龄参数设?
cstmt.executeUpdate();
tx.commit();
从上面程序看出,应用E序也必ȝqHibernate APIQ直接通过JDBC API来调用存储过E?/p>
Session的各U重载Ş式的update()Ҏ都一ơ只能更C个对象,而delete()Ҏ的有些重载Ş式允总HQL语句作ؓ参数Q例如:
session.delete("from Customer c where c.age>0");
如果CUSTOMERS表中?万条q龄大于零的记录Q那么以上代码能删除一万条记录。但是Session的delete()Ҏq没有执行以下delete语句Q?/p>
delete from CUSTOMERS where AGE>0;
Session的delete()Ҏ先通过以下select语句?万个Customer对象加蝲到内存中Q?/p>
select * from CUSTOMERS where AGE>0;
接下来执行一万条delete语句Q逐个删除Customer对象Q?/p>
delete from CUSTOMERS where ID=i;
delete from CUSTOMERS where ID=j;
…?br />delete from CUSTOMERS where ID=k;
由此可见Q直接通过Hibernate APIq行扚w更新和批量删除都不值得推荐。而直接通过JDBC API执行相关的SQL语句或调用相关的存储q程Q是扚w更新和批量删除的最x式,q两U方式都有以下优点:
(1) 无需把数据库中的大批量数据先加蝲到内存中Q然后逐个更新或修改它们,因此不会消耗大量内存?/p>
(2) 能在一条SQL语句中更新或删除大批量的数据?/p>
在hibernate中,最核心的概念就是对PO的状态管理,一个PO有三U状态:
未被持久化的VO
此时是一个内存对象VOQ由JVM理生命周期
已被持久化的POQƈ且在Session使命周期?/p>
此时映射数据库数据,由数据库理生命周期
曾被持久化过Q但现在和Session已经detached了,以VO的n份在q行?/p>
q种和Session已经detached的POq能够进入别一个SessionQl进行PO状态状,此时它就成ؓPO的第二种状态了?/p>
q种PO实际上是跨了Sessionq行了状态维护的?/span>
在传l的JDO1.x中,PO只有前面两种状态,一个PO一旦脱PMQ就丧失了状态了Q不再和数据库数据关联,成ؓ一个纯_的内存VOQ它即ɘq入一个新的PMQ也不能恢复它的状态了?
Hibernate强的地方在于,一个POqSession之后Q还能保持状态,再进入一个新的Session之后Q就恢复状态管理的能力Q但此时状态管理需要用session.update或者session.saveOrUpdateQ这是Hibernate Reference中提到的“requires a slightly different programming model ?/p>
]]>
վ֩ģ壺
|
֥|
|
Դ|
|
ͬ|
ڳ|
Ʊ|
ֲ|
Ϸ|
|
Դ|
µ|
|
Ȫ|
|
ν|
Ļ|
ٰ|
|
ͺ|
|
¤|
|
մ|
ˮ|
|
|
μ|
|
ƽ|
Ԫ|
ʯ¥|
|
|
ˮ|
|
»|
ʯ|
̩|
|