CRM1.0工单割接到2.0全过程经验总结,此文章献给所有为2.0努力奋斗的人。

12 篇文章 0 订阅
8 篇文章 0 订阅

        经历过一个半月的征战,项目完工。只有身在其中才知道有什么感觉,验证了一句话,没有解决不了的问题。开始总结之前,首先要感谢帮助过我的人,一起决战到天亮的人。(土豆烧牛肉、王磊、鲸等)

 

        1、读原CRM1.0原程序,了解程序结构和过程。   简单说明了程序结构。

 

 

       

说明: 每个子系统都有完整的一套Web前段程序,它调用后端同名的EJB项目,前段访问不一定只调用一个EJB。可以调用不同命的EJB项目。

使用到的技术:Spring 2 、hibernate2、struts1等,其他都是无关紧要的。

 

        2、割接项目程序结构设计

        割接项目程序结构设计,由于业务逻辑异常复杂,打算用以前现有的代码。当初考虑到有可能更改原有的程序,hibernate维护起来异常费劲,打算用Mybatis提到一些Dao操作。

       所用到的技术:Spring3、Hibernate3、struts1、Mybatis。

       程序结构如下图所示:


 


 说明:比原有结构多了一个持久化库Mybatis,用于以后扩展开发。在EJB项目中,getBean模拟成为静态Service直接调用。

         配置过程很简单,用3大框架配置起来就行了。没有遇到问题。

 

        3、程序摘取 (连接到CRM1.0库)

        1、hibernate与之对应的javabean:由于hibernate配置的一对一关联,一对多关联非常多,要进行摘取不动业务逻辑,不知如何再去。决定一步到位,所有的hibernate配置文件和javabean全部移动到新项目当中,并进行hibernate与spring结合配置。

        2、Action,DAO,Service(原来CRM1.0的getServiceBean)填充代码。具体思路就是用到的就copy进来,此过程需要心细,把所有的代码全部移植过来,排除预编译错误。

        过程经验:不仅仅是copy代码、其中的web.xml的配置文件需要的servlet和filter都要copy过来,以便以后出现莫名其妙的问题。

       

        4、程序调试 (连接到CRM1.0库)

 1、hibernate2升级到hibernate3.

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

 

2、修改DAO中的方法

2.1、 find(String queryString, Object[] values, Type[] types)不在需要Type[]也就是hibernate的字段数据类型不在需要,去掉数据类型。

2.2、 getSession().createFilter()  在程序中报错(不知道为什么?如何修改? )目前filter只是内存排序。

 

3、 执行期间hibernate session关闭情况

两种解决办法:

第一种方法:配置文件 lazy=false, (这个方法虽然是移植的最好的办法,不过试过了不管用)废弃。不过目前我为了移植,全都把lazy=false了。这样能在crm1.0中很快的调通,因为数据库中的表很全。

第二种方法:spring 提供的 openSessionInViewFilter 这个靠谱。 在一个action请求中就能完整的保持sessionopen情况。彻底解决问题。

 

4、根据报错信息进行修改,基本上都是DAO。hibernate 的错误,3.0不支持,推荐使用2.0的hibernate查询器。这样会避免了不要的错误,有些hql使用的2.0查询器。在Spring配置文件中配置一下就ok了。

 

        5、 程序调试 (CRM2.0数据库)

由于这里不能确定所需要的表结构,不能全部都移植到我的用户下,只能拉我需要表结构,数据量很大。不得不进行表赛选。

1、当初因为在CRM1.0当中所有的配置文件都为lazy=false,这样的话没有表的话加载就会报错,后台人员推荐建立同义词。。。。(这个是很不靠谱的依赖别人动不动就会出现问题)。想了想,本来只需要一块弄能,不能把所有的表都加载进来。因为2.0默认就是false,到了3.0默认是true。这正好让我有了思路,把所有的hibernate配置文件改成默认情况,并且输出sql状态进行拉表操作。最后发现很难很难。原因有以下:

        1、大表数据量非常大(拉时间长)。

        2、大表查询时间过多(没有索引)。

        3、一次只能确定一个表没有。不能整体确定,照成时间超级浪费。这样猴年马月也干不完。

如何解决问题:修改程序连接到CRM1.0库当中,输出sql。sql过多怎么把? 百度一下调节console内容大小,通过日志取到所有sql,并且整理出来所有的表和索引。3台机器拉了4天的数据,问题解决。

2、lazy问题:原来的程序结构默认直接操作内存照成说找不到对象,或者为null情况,那就直接把这个hibernate配置文件弄成lazy=false就行了,因为2.0默认的就是lazy为false。这样我整理出来 207张表。虽然这个方法不是很高,但是我想到最有效率的方法了。

 

         6、正式部署(tomcat-weblogic,crm2.0库)tomcat没有问题,weblogic有问题。

1、Web.xml配置顺序、Weblogic编码要求比较Tomcat要严格,如问号表达式,需要分开字符;尽量少用自定义标签,在tomcat下使用正常,但在Weblogic报错。

2、<include-coda/>不能使用这种形式< ..../> 只能使用 <></>布置为什么。

3、filter 双参数<init-param>
            <param-name>singleSession</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <param-name>sessionFactoryBeanName</param-name>
            <param-value>hibSessionFactory</param-value>
        </init-param>

4、<jsp-config>包围<taglib>

5、必须注意顺序。

6、Spring连接池就这样配置,其他配置方法都错。

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="jdbc/oracle/his">
        </property>
    </bean>

        7、weblogic配置启动(这里不用多说)         8、Weblogic连接池问题

1、死链接:在crm1.0当中,有的程序有getSession().rollback 情况,这样会照成jndi连接池的死链接,必须注意。

2、无限获取连接问题:在openSessionInViewFilter当中,他是一个多利的类,可以设置为单利模式,也可以设置多利模式, 区别在于:tomcat下 不管是单利还是多利,可以行,连接数稳定。但是在weblogic下,多利会照成连接数暴增,使系统崩溃,所以必须设置单例。

 

以上是总结,其中有很多错别字,望见谅。时间比较紧。最后感谢所有帮助我的人。其中还有许多问题,很多很多,记不住了,等发现时候再来补充。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值