服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

如何把hibernate2.1升级到hibernate3.0

尽管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 hibernate api 变化

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.exdivssion”包被改名为“org.hibernate.criterion”。假如应用程序使用了criteria api,那么在升级的过程中,必须把java源程序中的所有“net.sf.hibernate.exdivssion”替换为“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.2 org.hibernate.classic包

hibernate3.0把一些被废弃的接口都转移到org.hibernate.classic中。

1.3 hibernate所依赖的第三方软件包

在hibernate3.0的软件包的lib目录下的readme.txt文件中,描述了hibernate3.0所依赖的第三方软件包的变化。

1.4 异常模型

在hibernate3.0中,hibernateexception异常以及它的所有子类都继承了java.lang.runtimeexception。因此在编译时,编译器不会再检查hibernateexception。

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没有对批量更新和批量删除提供很好的支持,而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.6 createsqlquery()

在hibernate3.0中,session接口的createsqlquery()方法被废弃,被移到org.hibernate.classic.session接口中。hibernate3.0采用新的sqlquery接口来完成相同的功能。

1.7 lifecycle 和 validatable 接口

lifecycle和validatable 接口被废弃,并且被移到org.hibernate.classic包中。

1.8 interceptor接口

在interceptor 接口中加入了两个新的方法。 用户创建的interceptor实现类在升级的过程中,需要为这两个新方法提供方法体为空的实现。此外,instantiate()方法的参数作了修改,isunsaved()方法被改名为istransient()。

1.9 usertype和compositeusertype接口

在usertype和compositeusertype接口中都加入了一些新的方法,这两个接口被移到org.hibernate.usertype包中,用户定义的usertype和compositeusertype实现类必须实现这些新方法。

hibernate3.0提供了parameterizedtype接口,用于更好的重用用户自定义的类型。

1.10 fetchmode类

fetchmode.lazy 和 fetchmode.eager被废弃。取而代之的分别为fetchmode.select 和fetchmode.join。

1.11 persistentenum类

persistentenum被废弃并删除。已经存在的应用应该采用usertype来处理枚举类型。

1.12 对blob 和clob的支持

hibernate对blob和clob实例进行了包装,使得那些拥有blob或clob类型的属性的类的实例可以被游离、序列化或反序列化,以及传递到merge()方法中。

1.13 hibernate中供扩展的api的变化

org.hibernate.criterion、 org.hibernate.mapping、 org.hibernate.persister和org.hibernate.collection 包的结构和实现发生了重大的变化。多数基于hibernate 2.1 的应用不依赖于这些包,因此不会被影响。如果你的应用扩展了这些包中的类,那么必须非常小心的对受影响的程序代码进行升级。

2 元数据的变化

2.1 检索策略

在hibernate2.1中,lazy属性的默认值为“false”,而在hibernate3.0中,lazy属性的默认值为“true”。在升级映射文件时,如果原来的映射文件中的有关元素,如< set >、< class >等没有显式设置lazy属性,那么必须把它们都显式的设置为lazy=“true”。如果觉得这种升级方式很麻烦,可以采取另一简单的升级方式:在< hibernate-mapping >元素中设置: default-lazy=“false”。

2.2 对象标识符的映射

unsaved-value属性是可选的,在多数情况下,hibernate3.0将把unsaved-value="0" 作为默认值。

在hibernate3.0中,当使用自然主键和游离对象时,不再强迫实现interceptor.isunsaved()方法。 如果没有设置这个方法,当hibernate3.0无法区分对象的状态时,会查询数据库,来判断这个对象到底是临时对象,还是游离对象。不过,显式的使用interceptor.isunsaved()方法会获得更好的性能,因为这可以减少hibernate直接访问数据库的次数。

2.3 集合映射

< index >元素在某些情况下被元素替代。此外,hibernate3.0用< map-key-many-to-many > 元素来替代原来的< key-many-to-many >.元素,用< composite-map-key >元素来替代原来的< composite-index >元素。

2.4 dtd

对象-关系映射文件中的dtd文档,由原来的:

http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd

改为:

http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd

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()函数。

扫描关注微信公众号