如何把
Hibernate2.1
升级到
Hibernate3.0
?
选自
<<
精通
Hibernate
:
Java
对象持久化技术详解
>>
作者:孙卫琴
来源
:www.javathinker.org
如果转载,请标明出处,谢谢
1.1 Hibernate API
变化
1.1.1
包名
1.1.2 org.hibernate.classic
包
1.1.3 Hibernate
所依赖的第三方软件包
1.1.4
异常模型
1.1.5 Session
接口
1.1.6 createSQLQuery()
1.1.7 Lifecycle
和
Validatable
接口
1.1.8 Interceptor
接口
1.1.9 UserType
和
CompositeUserType
接口
1.1.10 FetchMode
类
1.1.11 PersistentEnum
类
1.1.12
对
Blob
和
Clob
的支持
1.1.13 Hibernate
中供扩展的
API
的变化
1.2
元数据的变化
1.2.1
检索策略
1.2.2
对象标识符的映射
1.2.3
集合映射
1.2.4 DTD
1.3
查询语句的变化
1.3.1 indices()
和
elements()
函数
尽管
Hibernate 3.0
与
Hibernate2.1
的源代码是不兼容的,但是当
Hibernate
开发小组在设计
Hibernate3.0
时,为简化升级
Hibernate
版本作了周到的考虑。对于现有的基于
Hibernate2.1
的
Java
项目,可以很方便的把它升级到
Hibernate3.0
。
本文描述了
Hibernate3.0
版本的新变化,
Hibernate3.0
版本的变化包括三个方面:
(
1
)
API
的变化,它将影响到
Java
程序代码。
(
2
)元数据,它将影响到对象
-
关系映射文件。
(
3
)
HQL
查询语句。
值得注意的是,
Hibernate3.0
并不会完全取代
Hibernate2.1
。在同一个应用程序中,允许
Hibernate3.0
和
Hibernate2.1
并存。
1.1 Hibernate API
变化
1.1.1
包名
Hibernate3.0
的包的根路径为
: “org.hibernate”
,而在
Hibernate2.1
中为
“net.sf.hibernate”
。这一命名变化使得
Hibernate2.1
和
Hibernate3.0
能够同时在同一个应用程序中运行。
如果希望把已有的应用升级到
Hibernate3.0
,那么升级的第一步是把
Java
源程序中的所有
“net.sf.hibernate”
替换为
“org.hibernate”
。
Hibernate2.1
中的
“net.sf.hibernate.expression”
包被改名为
“org.hibernate.criterion”
。假如应用程序使用了
Criteria API
,那么在升级的过程中,必须把
Java
源程序中的所有
“net.sf.hibernate.expression”
替换为
“org.hibernate.criterion”
。
如果应用使用了除
Hibernate
以外的其他外部软件,而这个外部软件又引用了
Hibernate
的接口,那么在升级时必须十分小心。例如
EHCache
拥有自己的
CacheProvider
:
net.sf.ehcache.hibernate.Provider
,在这个类中引用了
Hibernate2.1
中的接口,在升级应用时,可以采用以下办法之一来升级
EHCache:
(
1
)手工修改
net.sf.ehcache.hibernate.Provider
类,使它引用
Hibernate3.0
中的接口。
(
2
)等到
EHCache
软件本身升级为使用
Hibernate3.0
后,使用新的
EHCache
软件。
(
3
)使用
Hibernate3.0
中内置的
CacheProvider
:
org.hibernate.cache.EhCacheProvider
。
1.1.2 org.hibernate.classic
包
Hibernate3.0
把一些被废弃的接口都转移到
org.hibernate.classic
中。
1.1.3 Hibernate
所依赖的第三方软件包
在
Hibernate3.0
的软件包的
lib
目录下的
README.txt
文件中,描述了
Hibernate3.0
所依赖的第三方软件包的变化。
1.1.4
异常模型
在
Hibernate3.0
中,
HibernateException
异常以及它的所有子类都继承了
java.lang.RuntimeException
。因此在编译时,编译器不会再检查
HibernateException
。
1.1.5 Session
接口
在
Hibernate3.0
中,原来
Hibernate2.1
的
Session
接口中的有些基本方法也被废弃,但为了简化升级,这些方法依然是可用的,可以通过
org.hibernate.classic.Session
子接口来访问它们,例如:
org.hibernate.classic.Session session=sessionFactory.openSession();
session.delete("delete from Customer ");
在
Hibernate3.0
中,
org.hibernate.classic.Session
接口继承了
org.hibernate.Session
接口,在
org.hibernate.classic.Session
接口中包含了一系列被废弃的方法,如
find()
、
interate()
等。
SessionFactory
接口的
openSession()
方法返回
org.hibernate.classic.Session
类型的实例。如果希望在程序中完全使用
Hibernate3.0
,可以采用以下方式创建
Session
实例:
org.hibernate.Session session=sessionFactory.openSession();
如果是对已有的程序进行简单的升级,并且希望仍然调用
Hibernate2.1
中
Session
的一些接口,可以采用以下方式创建
Session
实例:
org.hibernate.classic.Session session=sessionFactory.openSession();
在
Hibernate3.0
中,
Session
接口中被废弃的方法包括:
*
执行查询的方法:
find()
、
iterate()
、
filter()
和
delete(String hqlSelectQuery)
* saveOrUpdateCopy()
Hibernate3.0
一律采用
createQuery()
方法来执行所有的查询语句,采用
DELETE
查询语句来执行批量删除,采用
merge()
方法来替代
saveOrUpdateCopy()
方法。
提示:在
Hibernate2.1
中,
Session
的
delete()
方法有几种重载形式,其中参数为
HQL
查询语句的
delete()
方法在
Hibernate3.0
中被废弃,而参数为
Ojbect
类型的的
delete()
方法依然被支持。
delete(Object o)
方法用于删除参数指定的对象,该方法支持级联删除。
Hibernate2.1
没有对批量更新和批量删除提供很好的支持,参见
<<
精通
Hibernate>>
一书的第
13
章的
13.1.1
节(批量更新和批量删除),而
Hibernate3.0
对批量更新和批量删除提供了支持,能够直接执行批量更新或批量删除语句,无需把被更新或删除的对象先加载到内存中。以下是通过
Hibernate3.0
执行批量更新的程序代码:
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
String hqlUpdate = "update Customer set name = :newName where name = :oldName";
int updatedEntities = s.createQuery( hqlUpdate )
.setString( "newName", newName )
.setString( "oldName", oldName )
.executeUpdate();
tx.commit();
session.close();
以下是通过
Hibernate3.0
执行批量删除的程序代码:
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
String hqlDelete = "delete Customer where name = :oldName";
int deletedEntities = s.createQuery( hqlDelete )
.setString( "oldName", oldName )
.executeUpdate();
tx.commit();
session.close();
1.1.6 createSQLQuery()
在
Hibernate3.0
中,
Session
接口的
createSQLQuery()
方法被废弃,被移到
org.hibernate.classic.Session
接口中。
Hibernate3.0
采用新的
SQLQuery
接口来完成相同的功能。
1.1.7 Lifecycle
和
Validatable
接口
Lifecycle
和
Validatable
接口被废弃,并且被移到
org.hibernate.classic
包中。
1.1.8 Interceptor
接口
在
Interceptor
接口中加入了两个新的方法。
用户创建的
Interceptor
实现类在升级的过程中,需要为这两个新方法提供方法体为空的实现。此外,
instantiate()
方法的参数作了修改,
isUnsaved()
方法被改名为
isTransient()
。
1.1.9 UserType
和
CompositeUserType
接口
在
UserType
和
CompositeUserType
接口中都加入了一些新的方法,这两个接口被移到
org.hibernate.usertype
包中,用户定义的
UserType
和
CompositeUserType
实现类必须实现这些新方法。
Hibernate3.0
提供了
ParameterizedType
接口,用于更好的重用用户自定义的类型。
1.1.10 FetchMode
类
FetchMode.LAZY
和
FetchMode.EAGER
被废弃。取而代之的分别为
FetchMode.SELECT
和
FetchMode.JOIN
。
1.1.11 PersistentEnum
类
PersistentEnum
被废弃并删除。已经存在的应用应该采用
UserType
来处理枚举类型。
1.1.12
对
Blob
和
Clob
的支持
Hibernate
对
Blob
和
Clob
实例进行了包装,使得那些拥有
Blob
或
Clob
类型的属性的类的实例可以被游离、序列化或反序列化,以及传递到
merge()
方法中。
1.1.13 Hibernate
中供扩展的
API
的变化
org.hibernate.criterion
、
org.hibernate.mapping
、
org.hibernate.persister
和
org.hibernate.collection
包的结构和实现发生了重大的变化。多数基于
Hibernate
2.1
的应用不依赖于这些包,因此不会被影响。如果你的应用扩展了这些包中的类,那么必须非常小心的对受影响的程序代码进行升级。
1.2
元数据的变化
1.2.1
检索策略
在
Hibernate2.1
中,
lazy
属性的默认值为
“false”
,而在
Hibernate3.0
中,
lazy
属性的默认值为
“true”
。在升级映射文件时,如果原来的映射文件中的有关元素,如
<set>
、
<class>
等没有显式设置
lazy
属性,那么必须把它们都显式的设置为
lazy=“true”
。如果觉得这种升级方式很麻烦,可以采取另一简单的升级方式:在
<hibernate-mapping>
元素中设置
: default-lazy=“false”
。
1.2.2
对象标识符的映射
unsaved-value
属性是可选的,在多数情况下,
Hibernate3.0
将把
unsaved-value="0"
作为默认值。
在
Hibernate3.0
中,当使用自然主键和游离对象时,不再强迫实现
Interceptor.isUnsaved()
方法。
如果没有设置这个方法,当
Hibernate3.0
无法区分对象的状态时,会查询数据库,来判断这个对象到底是临时对象,还是游离对象。不过,显式的使用
Interceptor.isUnsaved()
方法会获得更好的性能,因为这可以减少
Hibernate
直接访问数据库的次数。
1.2.3
集合映射
<index>
元素在某些情况下被
<list-index>
和
<map-key>
元素替代。此外,
Hibernate3.0
用
<map-key-many-to-many>
元素来替代原来的
<key-many-to-many>.
元素,用
<composite-map-key>
元素来替代原来的
<composite-index>
元素。
1.2.4 DTD
对象
-
关系映射文件中的
DTD
文档,由原来的:
http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd
改为:
http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd
1.3
查询语句的变化
Hibernate3.0
采用新的基于
ANTLR
的
HQL/SQL
查询翻译器,不过,
Hibernate2.1
的查询翻译器也依然存在。在
Hibernate
的配置文件中,
hibernate.query.factory_class
属性用来选择查询翻译器。例如:
(
1
)选择
Hibernate3.0
的查询翻译器:
hibernate.query.factory_class= org.hibernate.hql.ast.ASTQueryTranslatorFactory
(
2
)选择
Hibernate2.1
的查询翻译器
hibernate.query.factory_class= org.hibernate.hql.classic.ClassicQueryTranslatorFactory
提示:
ANTLR
是用纯
Java
语言编写出来的一个编译工具,它可生成
Java
语言或者是
C++
的词法和语法分析器,并可产生语法分析树并对该树进行遍历。
ANTLR
由于是纯
Java
的,因此可以安装在任意平台上,但是需要
JDK
的支持。
Hibernate
开发小组尽力保证
Hibernate3.0
的查询翻译器能够支持
Hibernate2.1
的所有查询语句。不过,对于许多已经存在的应用,在升级过程中,也不妨仍然使用
Hibernate2.1
的查询翻译器。
值得注意的是,
Hibernate3.0
的查询翻译器存在一个
Bug
:不支持某些
theta-style
连结查询方言:如
Oracle8i
的
OracleDialect
方言、
Sybase11Dialect
。解决这一问题的办法有两种:(
1
)改为使用支持
ANSI-style
连结查询的方言,如
Oracle9Dialect,
(
2
)如果升级的时候遇到这一问题,那么还是改为使用
Hibernate2.1
的查询翻译器。
1.3.1 indices()
和
elements()
函数
在
HQL
的
select
子句中废弃了
indices()
和
elements()
函数,因为这两个函数的语法很让用户费解,可以用显式的连接查询语句来替代
select elements(...)
。而在
HQL
的
where
子句中,仍然可以使用
elements()
函数。
posted on 2006-05-01 21:13
badboy 阅读(394)
评论(0) 编辑 收藏 所属分类:
Framework