深蓝色心情

过来聊聊~~~~

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  31 Posts :: 0 Stories :: 46 Comments :: 0 Trackbacks

#

如何不用写java代码来完成开发? 

对于大部分的产品和项目来说,页面变化是非常头痛的事情。每次小功能上线,新客户到来,都需要进行定制改造,不断的开发维护。每次开发一方面要改动页面,一方面要改动服务器代码,然后部署。而借助动态数据源,可以不用开发后端应用,直接完成功能开发。 

新功能开发时,只需要定义需要的数据格式和获取方法,如通过xml上传1个sql语句,系统根据sql语句自动提取数据并转成通用的格式。开发过程中,后台java开发部分只是写好sql并且上传,这样前台通过某一个servlet可以动态的读取执行sql,并将结果按照json返给前端,以后所有的开发只需要前端做ajax实现页面即可。 

完整业务流程如下: 

1. 用户在前端操作,如需要读取经济类图书。 

2. 前端js判断是什么操作,然后发送ajax请求到:http://services.guzz.org/commonServlet?id=f2354239sfASASFASfasf6&catId=47&keyword=jingji..... 

3. 服务器端有一个类似dispatcher-servlet的东西(我们这儿的commonServlet),拦截请求,根据id知道加载数据需要执行名称为f2354239sfASASFASfasf6的sql文件,执行时需要参数:catId=47和keyword=jingji 

4. commonServlet从文件系统中读取f2354239sfASASFASfasf6.xml文件(这个文件在一个隐藏的目录下,从浏览器是不能直接获取到的;集群环境会存放在集中存储上),解析sql以及对象映射ORM。 

5. commonServlet打开数据库连接,根据sql构造查询语句,将第一步传入的参数全部作为命名参数传给查询语句,执行查询。 

6. commonServlet把查询的ResultSet根据ORM转成java类,再转成json,返回前台。 

7. 前台根据json构造出页面并展示。结束流程。 

在整个过程中,有2个关键步骤,一是动态加载SQL并进行ORM映射,一是自动进行sql所需要参数的类型转换和匹配,进行命名查询。如果系统规模较大,还需要解决查询时分库分表的问题。对于这种sql使用方式,由于在系统上线时,并不知道以后会用哪些sql语句,我们称作动态SQL。 

实现方式: 

步骤1. 实现servlet。定义一个普通的servlet,或者jsp,或者webwork/spring action,接收参数,获取到sql的id,以及所有传入的参数,然后转入处理类处理。处理完成后,将返回结果转成json返回前端。 

步骤2. 实现动态SQL加载与查询。处理类根据id加载sql并执行,返回数据库查询结果。guzz 1.2.8 beta2提供了动态SQL服务,根据此服务可以直接实现此功能。详细说明:http://code.google.com/p/guzz/wiki/TutorialDynamicSQLService 

好处: 

实现以后,基本上后台开发就会很稳定很稳定了,大部分的工作只是前端做页面。可以大幅度的降低开发成本,提高开发进度。 

上面的实现是以上传文件来定义和管理sql,也可以通过数据库来管理。这样管理起来更加简单。 

如果使用guzz作为动态SQL提供者,可以自动获得命名查询,类型自动匹配(转成枚举类型都可以),分库,自动分切表,自定义属性表等附加支持。

啧啧~~ 

posted @ 2010-05-27 14:52 深蓝色心情 阅读(2956) | 评论 (5)编辑 收藏


guzz是一套用来解决ORM、多数据源管理、以及通用数据计算的数据层框架,为系统在数据层的设计提供一站式解决方案。guzz可以看作是 ibatis/hibernate的一大的延伸,并可以取代这2个东西。 

guzz主要功能与特点: 
  • 现代大规模系统设计,技术上吸收了ibatis/hibernate的优点
  • 支持像hibernate一样的对象化持久、映射和方便的增删改查
  • 支持像ibatis一样,让dba参与sql设计的复杂数据库操作和优化
  • 支持在线加载与调试SQL。按照应用策略,从文件/数据库/Web Service等途径,动态提取与使用SQL语句(Dynamic SQL)
  • 支持应用程序使用大量的数据库和主从读写分离
  • 支持超越范式的特殊关联、非结构化数据等异构资源的统一管理
  • 支持数据表在多组机器间水平分布(Shard),并自动维护多组机器之间的分布式事务
  • 支持1张表按照业务规则分切成多张小表(Shadow),并支持每张小表拥有自己特殊的属性字段(Custom)
  • 支持组件化服务(SOA),构建企业/项目实施基础平台
  • 提供面向对象的数据库读取标签(JSP Taglib),加快页面展示层的快速变更、开发与部署
  • 支持配置管理服务器,可以使用一套软件系统对所有应用程序的配置进行统一管理
项目地址:http://code.google.com/p/guzz/ 
文档:http://code.google.com/p/guzz/wiki/WikiHomePage?tm=6 

1.2.8 beta2更新介绍: 

支持动态管理SQL: 

动态SQL(Dynamic SQL)不是指应用程序动态的拼接SQL语句,动态SQL是指应用程序可以动态的获取配置好的SQL语句。在获取的过程中,SQL语句如何管理,由应用系统自身决定。 

换句话说,在ibatis中,SQL语句配置到ibatis.xml文件中,在guzz中,配置到guzz.xml中。但当配置完成后,在系统运行期间这些SQL都是不能变动的,如果需要添加1个或者修改优化1个SQL语句,必须重启应用才能生效。而动态SQL允许应用系统动态的管理(添加/修改/优化/删除)sql语句以及查询结果到对象的映射关系(ORM),对于SQL的变更不再需要重启应用系统,以简化维护与应对需求变化。 

动态SQL主要有两种应用场景:SQL优化和动态数据源。具体介绍请参看:http://code.google.com/p/guzz/wiki/TutorialDynamicSQLService 

改进远程服务设计: 

增加对hessian, burlap协议的支持。目前guzz内置支持phprpc, hessian, burlap三种协议进行RPC远程调用。使用时,三种协议可以透明替换,类似spring对RMI类协议的封装。具体介绍请参看:http://code.google.com/p/guzz/wiki/TutorialFutureService 

增加枚举类型与类型参数化支持: 

按照TopLink的模式,支持JDK5 enum。Enum在使用时和普通类型一样,不需要实现特殊的接口(hibernate要求实现接口)。Enum支持通过JPA的Enumeration注释声明,也支持在hbm.xml中通过xml定义。通过xml的定义方式参看:http://code.google.com/p/guzz/wiki/TutorialHbmXml 

类型参数化为guzz的特殊功能,用于处理动态SQL参数和Jsp Taglib条件参数时,将String类型自动转换成需要的数据类型。参数化类型主要为日期和枚举。详细介绍:http://code.google.com/p/guzz/wiki/TutorialHbmXml 

增加对数据库保留字的支持: 

在定义数据库列名时,可以用`(ESC下面的键)将列名引起来,避免字段名称与数据库保留字冲突。此功能与hibernate提供的处理保留字方法相同,但guzz只支持字段,不支持`表名`。 

增加对Microsoft SQL Server的支持(未测试): 

参考hibernate实现了一个SQL Server 2000 & 2005的dialect,不支持分页。没有测试过。Dialect实现类:org.guzz.dialect.MSSQLDialect 

Guzz已经能够支持的数据库和数据类型请参看: 
http://code.google.com/p/guzz/wiki/TutorialGuzzXml 

应用示例说明: 

http://code.google.com/p/guzz/wiki/TutorialDynamicSQLService 

下一版本计划: 

  • 修复发现的bug。
  • 设计一些常见的服务,推广guzz基础服务理念。
posted @ 2010-05-26 10:13 深蓝色心情 阅读(1713) | 评论 (2)编辑 收藏

     摘要: guzz是一套用来解决ORM、多数据源管理、以及通用数据计算的数据层框架,为系统在数据层的设计提供一站式解决方案。guzz可以看作是 ibatis/hibernate的一大的延伸,并可以取代这2个东西。  guzz主要功能与特点:  现代大规模系统设计,技术上吸收了ibatis/hibernate的优点 支持像hibernate一样的对象化持久...  阅读全文
posted @ 2010-05-05 10:36 深蓝色心情 阅读(1420) | 评论 (0)编辑 收藏

guzz是一套用来解决ORM、多数据源管理、以及通用数据计算的数据层框架,为系统在数据层的设计提供一站式解决方案。guzz可以看作是 ibatis/hibernate的一大的延伸,并可以取代这2个东西。 

guzz主要功能与特点: 
  • 现代大规模系统设计,技术上吸收了ibatis/hibernate的优点
  • 支持像hibernate一样的对象化持久、映射和方便的增删改查
  • 支持像ibatis一样,让dba参与sql设计的复杂数据库操作和优化
  • 支持应用程序使用大量的数据库和主从读写分离
  • 支持超越范式的特殊关联、非结构化数据等异构资源的统一管理
  • 支持数据表在多组机器间水平分布(Shard),并自动维护多组机器之间的分布式事务
  • 支持1张表按照业务规则分切成多张小表(Shadow),并支持每张小表拥有自己特殊的属性字段(Custom)
  • 支持组件化服务(SOA),构建企业/项目实施基础平台
  • 提供面向对象的数据库读取标签(JSP Taglib),加快页面展示层的快速变更、开发与部署
  • 支持配置管理服务器,可以使用一套软件系统对所有应用程序的配置进行统一管理
项目地址:http://code.google.com/p/guzz/ 
文档:http://www.guzz.org/wiki/GuzzGuide 

1.2.7正式版 更新介绍: 

  • 支持表分切。允许同一对象按照业务规则,分别存储在不同的表中。如新闻评论:新闻频道的评论存放在 tb_c1,娱乐:tb_c2,体育tb_c3,其他:tb_c4,满足同类在线数据的数据表平行扩展需要。表分切命名为:Shadow Table。

  • 支持自定义属性表。允许分切后的每张小表拥有自己的动态对象属性和字段。如购物网站中:商品对象拥有统一的名称、价格、编号、评分等,但不同的商品可能有自己特殊的属性,如图书拥有ISBN和出版社作者,服装拥有尺码、颜色、款式等等。自定义属性允许程序只定义1个商品域对象,然后通过自定义属性和切表,将每1种特定的商品分切到1张自己特殊的表中,这张表同时拥有商品通用的字段以及这种商品自己的字段,查询时可以按照特殊字段直接在数据库中进行关系查询。在guzz中,自定义属性的定义允许存储到数据库中,像普通对象一样动态生成和管理,不用配置复杂的xml。自定义属性命名为:Custom Table。

  • 增加并行任务支持。用于多个远程服务同步的调用,降低等待时间。

  • 增加hilo和seqhilo主健生成策略。至此,hibernate支持的常见主健生成策略,guzz都支持了。

  • 增加外挂环境接口。如果在spring中启动,允许在guzz中获取spring定义的bean。
应用示例说明: 

本次更新有很多新概念需要介绍,因此篇幅较长。详细的示例和说明请参看: 

表分切:http://www.guzz.org/wiki/GuzzShadow 

自定义属性表(基于表分切):[url]http://www.guzz.org/wiki/GuzzCustomTable [/url] 

并行任务执行(基于服务):http://www.guzz.org/wiki/GuzzFutureService 

主健生成策略:http://www.guzz.org/wiki/GuzzHbm 

下一版本计划: 

  • 数据库自动分库支持。允许同一张表,分散在多台数据库中。
  • 提供更多对服务的支持。
  • 探索SASS(软件就是服务)的数据层模型。
  • 其他
posted @ 2010-04-09 14:55 深蓝色心情 阅读(1525) | 评论 (1)编辑 收藏

我们主要是web应用,web规模也不能确定,有可能一天几千万甚至上亿的PV,也有可能根本没人用。最初设计guzz的目的就是让大型网站和小型网站一样设计编写,因为谁也不知道这个应用上去以后有多少人用,同时解决系统被要求页面天天改来该去的问题。 

使用guzz以来的效果: 

1. 框架性能上没有看得出的快慢区别。我觉得不会比hibernate和biatis慢,我看过他们的一些代码,流程挺复杂的。guzz很简单,整个持久化过程需要转手的类至少要比这两个少很多。 

2. 以前我们用hibernate较多,一般数据库设计就是一个库,读写全部做。现在在设计时大家脑子里面直接就是分出3个数据库(可能部署在1台mysql上)--业务主库,临时信息库,日志库,然后把表分到不同的库中。然后数据库安装时直接主从安装,主从使用。虽然看起来库复杂了,但程序上没有任何成本代价,基本上已经形成一种设计流程。这种模式感觉可以作为最佳实践。 

3. 编程上,一开始开发人员还是建个spring action类 + 在dao和manager中增加需要的方法 + 修改dispatcher-servlet.xml配置映射 + jsp实现view。但现在很多功能都是直接jsp,用taglib直接读库,基本上后台的读数据库操作页面已经看不到action的影子了。java代码比先前的工程,同样的功能少了大概60%-70%。 

4. 我们的系统一般后台功能比较复杂,以往编辑要改点东西大家都很郁闷。不过现在抵制少了很多,基本上就是改改jsp或者在复制1个新的jsp改改,然后传到服务器上,一大堆集群机器的重启工作都免了,无论是开发还是部署都很省事。和php差不多。 

guzz1.2.7分表和自定义表的应用实例: 

我们有1套调查系统,使用了这项技术,也是第一个线上测试。每个调查都不太一样,需要网友填一些东西,需要填什么,填的个数类型都不定。一个调查进行过程中,或者结束后要求对数据进行统计报表。统计的内容可能也包括那些自定义的填空题。 

在1.2.7之前,我们解决方案是:将所有自定义的调查项,按照key-value生成一个xml字符串,存储到数据库大字段中(Mysql text字段)。需要统计时,根据mysql5.1对xml支持的新特性使用ExtraValue函数解析这个xml生成一个新表(create table xxxx select ExtraValue(xx) as a, .....from 主调查记录表),然后在根据新的xxxx表统计。每次都要手工来弄,非常繁琐。 

1.2.7,使用切表和自定义属性后,现在的解决方案:每次创建投票并建立好自定义调查项(自定义调查项存储在数据库中),根据这些自动生成一个mysql create table的语句,创建好需要的表。在配置CustomTableView动态的映射用户提交的数据存储到对应的表中。完全自动,后续处理简化了很多。 

而且由于整个过程是实时的,以前的过程是手工的,所以很多线上的报表功能也可以开发了。开发也非常简单,我们用guzz jsp tablib直接读库,像操作普通java属性一样操作自定义属性,一个类型的表报1个jsp。特殊调查的特殊报表也就是往服务器上放1个特殊处理的jsp,应用都不用重启,非常方便。 

guzz1.2.7分表和自定义表的下一个应用计划: 

这是一个计划,还没有做,不过我们准备很快就开始做。 

我们的所有系统对日志都有要求,日志必须记录!但日志的开发很烦人,全是没有技术含量的重复工作。我们准备开发一个日志服务,所有系统以后就不用开发日志了,直接使用这个服务。日志服务分为服务器端和客户端。 

服务器端: 

一个标准的java web系统,有日志数据库,用来存储所有系统的日志信息,并提供查询和统计等界面。如果有人需要查日志,就到这个系统来查。 

服务器端有1个应用数据库,用来创建和管理授权的应用系统。1个新的应用上线的时候,在这里创建一个应用和他的授权码,然后录入他的个性日志字段和数据类型(类似上面提到调查的个性选项),服务器自动在数据库中给他创建1个日志表,用来存储这个应用的日志数据。我们准备按季度分表,让每个日志表1个季度分成1张子表。 

客户端: 

实现一个标准的guzz service,提供日志插入接口 
Java代码 
  1. public void log(UserLog log) ;  

每个系统开发时,将日志服务的jar包放到工程中,并在guzz.xml中声明此服务,代码直接调用就OK了。 

这样以后就不用为每个系统开发日志管理模块了。并且还能获取到统计某一个用户在所有系统中活动记录的额外增强(例如我们可以在服务器端将日志记录两份,一份按应用系统,一份按操做者记录)~~ 

posted @ 2010-04-09 14:52 深蓝色心情 阅读(3398) | 评论 (0)编辑 收藏

提高 Linux 上 socket 性能

加速网络应用程序的 4 种方法

developerWorks
 

未显示需要 JavaScript 的文档选项


 


级别: 中级

M. Tim Jones ,资深软件工程师,Emulex

2006 年 2 月 13 日

使用 Sockets API,我们可以开发客户机和服务器应用程序,它们可以在本地网络上进行通信,也可以通过 Internet 在全球范围内进行通信。与其他 API 一样,您可以通过一些方法使用 Sockets API,从而提高 Socket 的性能,或者限制 Socket 的性能。本文探索了 4 种使用 Sockets API 来榨取应用程序的最大性能并对 GNU/Linux® 环境进行优化从而达到最好结果的方法。

在开发 socket 应用程序时,首要任务通常是确保可靠性并满足一些特定的需求。利用本文中给出的 4 个提示,您就可以从头开始为实现最佳性能来设计并开发 socket 程序。本文内容包括对于 Sockets API 的使用、两个可以提高性能的 socket 选项以及 GNU/Linux 优化。

为了能够开发性能卓越的应用程序,请遵循以下技巧:

  • 最小化报文传输的延时。
  • 最小化系统调用的负载。
  • 为 Bandwidth Delay Product 调节 TCP 窗口。
  • 动态优化 GNU/Linux TCP/IP 栈。

技巧 1. 最小化报文传输的延时

在通过 TCP socket 进行通信时,数据都拆分成了数据块,这样它们就可以封装到给定连接的 TCP payload(指 TCP 数据包中的有效负荷)中了。TCP payload 的大小取决于几个因素(例如最大报文长度和路径),但是这些因素在连接发起时都是已知的。为了达到最好的性能,我们的目标是使用尽可能多的可用数据来填充每个报文。当没有足够的数据来填充 payload 时(也称为最大报文段长度(maximum segment size) 或 MSS),TCP 就会采用 Nagle 算法自动将一些小的缓冲区连接到一个报文段中。这样可以通过最小化所发送的报文的数量来提高应用程序的效率,并减轻整体的网络拥塞问题。

尽管 John Nagle 的算法可以通过将这些数据连接成更大的报文来最小化所发送的报文的数量,但是有时您可能希望只发送一些较小的报文。一个简单的例子是 telnet 程序,它让用户可以与远程系统进行交互,这通常都是通过一个 shell 来进行的。如果用户被要求用发送报文之前输入的字符来填充某个报文段,那么这种方法就绝对不能满足我们的需要。

另外一个例子是 HTTP 协议。通常,客户机浏览器会产生一个小请求(一条 HTTP 请求消息),然后 Web 服务器就会返回一个更大的响应(Web 页面)。

解决方案

您应该考虑的第一件事情是 Nagle 算法满足一种需求。由于这种算法对数据进行合并,试图构成一个完整的 TCP 报文段,因此它会引入一些延时。但是这种算法可以最小化在线路上发送的报文的数量,因此可以最小化网络拥塞的问题。

但是在需要最小化传输延时的情况中,Sockets API 可以提供一种解决方案。要禁用 Nagle 算法,您可以设置 TCP_NODELAY socket 选项,如清单 1 所示。


清单 1. 为 TCP socket 禁用 Nagle 算法

int sock, flag, ret;

/* Create new stream socket */
sock = socket( AF_INET, SOCK_STREAM, 0 );

/* Disable the Nagle (TCP No Delay) algorithm */
flag = 1;
ret = setsockopt( sock, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag) );

if (ret == -1) {
  printf("Couldn't setsockopt(TCP_NODELAY)\n");
  exit(-1);
}

提示:使用 Samba 的实验表明,在从 Microsoft® Windows® 服务器上的 Samba 驱动器上读取数据时,禁用 Nagle 算法几乎可以加倍提高读性能。



回页首


技巧 2. 最小化系统调用的负载

任何时候通过一个 socket 来读写数据时,您都是在使用一个系统调用(system call)。这个调用(例如 readwrite)跨越了用户空间应用程序与内核的边界。另外,在进入内核之前,您的调用会通过 C 库来进入内核中的一个通用函数(system_call())。从 system_call() 中,这个调用会进入文件系统层,内核会在这儿确定正在处理的是哪种类型的设备。最后,调用会进入 socket 层,数据就是在这里进行读取或进行排队从而通过 socket 进行传输的(这涉及数据的副本)。

这个过程说明系统调用不仅仅是在应用程序和内核中进行操作的,而且还要经过应用程序和内核中的很多层次。这个过程耗费的资源很高,因此调用次数越多,通过这个调用链进行的工作所需要的时间就越长,应用程序的性能也就越低。

由于我们无法避免这些系统调用,因此惟一的选择是最小化使用这些调用的次数。幸运的是,我们可以对这个过程进行控制。

解决方案

在将数据写入一个 socket 时,尽量一次写入所有的数据,而不是执行多次写数据的操作。对于读操作来说,最好传入可以支持的最大缓冲区,因为如果没有足够多的数据,内核也会试图填充整个缓冲区(另外还需要保持 TCP 的通告窗口为打开状态)。这样,您就可以最小化调用的次数,并可以实现更好的整体性能。



回页首


技巧 3. 为 Bandwidth Delay Product 调节 TCP 窗口

TCP 的性能取决于几个方面的因素。两个最重要的因素是链接带宽(link bandwidth)(报文在网络上传输的速率)和 往返时间(round-trip time) 或 RTT(发送报文与接收到另一端的响应之间的延时)。这两个值确定了称为 Bandwidth Delay Product(BDP)的内容。

给定链接带宽和 RTT 之后,您就可以计算出 BDP 的值了,不过这代表什么意义呢?BDP 给出了一种简单的方法来计算理论上最优的 TCP socket 缓冲区大小(其中保存了排队等待传输和等待应用程序接收的数据)。如果缓冲区太小,那么 TCP 窗口就不能完全打开,这会对性能造成限制。如果缓冲区太大,那么宝贵的内存资源就会造成浪费。如果您设置的缓冲区大小正好合适,那么就可以完全利用可用的带宽。下面我们来看一个例子:

BDP = link_bandwidth * RTT

如果应用程序是通过一个 100Mbps 的局域网进行通信,其 RRT 为 50 ms,那么 BDP 就是:

100MBps * 0.050 sec / 8 = 0.625MB = 625KB

注意:此处除以 8 是将位转换成通信使用的字节。

因此,我们可以将 TCP 窗口设置为 BDP 或 1.25MB。但是在 Linux 2.6 上默认的 TCP 窗口大小是 110KB,这会将连接的带宽限制为 2.2MBps,计算方法如下:

throughput = window_size / RTT

110KB / 0.050 = 2.2MBps

如果使用上面计算的窗口大小,我们得到的带宽就是 12.5MBps,计算方法如下:

625KB / 0.050 = 12.5MBps

差别的确很大,并且可以为 socket 提供更大的吞吐量。因此现在您就知道如何为您的 socket 计算最优的缓冲区大小了。但是又该如何来改变呢?

解决方案

Sockets API 提供了几个 socket 选项,其中两个可以用于修改 socket 的发送和接收缓冲区的大小。清单 2 展示了如何使用 SO_SNDBUFSO_RCVBUF 选项来调整发送和接收缓冲区的大小。

注意:尽管 socket 缓冲区的大小确定了通告 TCP 窗口的大小,但是 TCP 还在通告窗口内维护了一个拥塞窗口。因此,由于这个拥塞窗口的存在,给定的 socket 可能永远都不会利用最大的通告窗口。


清单 2. 手动设置发送和接收 socket 缓冲区大小

int ret, sock, sock_buf_size;

sock = socket( AF_INET, SOCK_STREAM, 0 );

sock_buf_size = BDP;

ret = setsockopt( sock, SOL_SOCKET, SO_SNDBUF,
                   (char *)&sock_buf_size, sizeof(sock_buf_size) );

ret = setsockopt( sock, SOL_SOCKET, SO_RCVBUF,
                   (char *)&sock_buf_size, sizeof(sock_buf_size) );

在 Linux 2.6 内核中,发送缓冲区的大小是由调用用户来定义的,但是接收缓冲区会自动加倍。您可以进行 getsockopt 调用来验证每个缓冲区的大小。

巨帧(jumbo frame)

我们还可以考虑将包的大小从 1,500 字节修改为 9,000 字节(称为巨帧)。在本地网络中可以通过设置最大传输单元(Maximum Transmit Unit,MTU)来设置巨帧,这可以极大地提高性能。

就 window scaling 来说,TCP 最初可以支持最大为 64KB 的窗口(使用 16 位的值来定义窗口的大小)。采用 window scaling(RFC 1323)扩展之后,您就可以使用 32 位的值来表示窗口的大小了。GNU/Linux 中提供的 TCP/IP 栈可以支持这个选项(以及其他一些选项)。

提示:Linux 内核还包括了自动对这些 socket 缓冲区进行优化的能力(请参阅下面 表 1 中的 tcp_rmemtcp_wmem),不过这些选项会对整个栈造成影响。如果您只需要为一个连接或一类连接调节窗口的大小,那么这种机制也许不能满足您的需要了。



回页首


技巧 4. 动态优化 GNU/Linux TCP/IP 栈

标准的 GNU/Linux 发行版试图对各种部署情况都进行优化。这意味着标准的发行版可能并没有对您的环境进行特殊的优化。

解决方案

GNU/Linux 提供了很多可调节的内核参数,您可以使用这些参数为您自己的用途对操作系统进行动态配置。下面我们来了解一下影响 socket 性能的一些更重要的选项。

/proc 虚拟文件系统中存在一些可调节的内核参数。这个文件系统中的每个文件都表示一个或多个参数,它们可以通过 cat 工具进行读取,或使用 echo 命令进行修改。清单 3 展示了如何查询或启用一个可调节的参数(在这种情况中,可以在 TCP/IP 栈中启用 IP 转发)。


清单 3. 调优:在 TCP/IP 栈中启用 IP 转发

[root@camus]# cat /proc/sys/net/ipv4/ip_forward
0
[root@camus]# echo "1" > /poc/sys/net/ipv4/ip_forward
[root@camus]# cat /proc/sys/net/ipv4/ip_forward
1
[root@camus]#

表 1 给出了几个可调节的参数,它们可以帮助您提高 Linux TCP/IP 栈的性能。

表 1. TCP/IP 栈性能使用的可调节内核参数
可调节的参数 默认值 选项说明
/proc/sys/net/core/rmem_default "110592" 定义默认的接收窗口大小;对于更大的 BDP 来说,这个大小也应该更大。
/proc/sys/net/core/rmem_max "110592" 定义接收窗口的最大大小;对于更大的 BDP 来说,这个大小也应该更大。
/proc/sys/net/core/wmem_default "110592" 定义默认的发送窗口大小;对于更大的 BDP 来说,这个大小也应该更大。
/proc/sys/net/core/wmem_max "110592" 定义发送窗口的最大大小;对于更大的 BDP 来说,这个大小也应该更大。
/proc/sys/net/ipv4/tcp_window_scaling "1" 启用 RFC 1323 定义的 window scaling;要支持超过 64KB 的窗口,必须启用该值。
/proc/sys/net/ipv4/tcp_sack "1" 启用有选择的应答(Selective Acknowledgment),这可以通过有选择地应答乱序接收到的报文来提高性能(这样可以让发送者只发送丢失的报文段);(对于广域网通信来说)这个选项应该启用,但是这会增加对 CPU 的占用。
/proc/sys/net/ipv4/tcp_fack "1" 启用转发应答(Forward Acknowledgment),这可以进行有选择应答(SACK)从而减少拥塞情况的发生;这个选项也应该启用。
/proc/sys/net/ipv4/tcp_timestamps "1" 以一种比重发超时更精确的方法(请参阅 RFC 1323)来启用对 RTT 的计算;为了实现更好的性能应该启用这个选项。
/proc/sys/net/ipv4/tcp_mem "24576 32768 49152" 确定 TCP 栈应该如何反映内存使用;每个值的单位都是内存页(通常是 4KB)。第一个值是内存使用的下限。第二个值是内存压力模式开始对缓冲区使用应用压力的上限。第三个值是内存上限。在这个层次上可以将报文丢弃,从而减少对内存的使用。对于较大的 BDP 可以增大这些值(但是要记住,其单位是内存页,而不是字节)。
/proc/sys/net/ipv4/tcp_wmem "4096 16384 131072" 为自动调优定义每个 socket 使用的内存。第一个值是为 socket 的发送缓冲区分配的最少字节数。第二个值是默认值(该值会被 wmem_default 覆盖),缓冲区在系统负载不重的情况下可以增长到这个值。第三个值是发送缓冲区空间的最大字节数(该值会被 wmem_max 覆盖)。
/proc/sys/net/ipv4/tcp_rmem "4096 87380 174760" tcp_wmem 类似,不过它表示的是为自动调优所使用的接收缓冲区的值。
/proc/sys/net/ipv4/tcp_low_latency "0" 允许 TCP/IP 栈适应在高吞吐量情况下低延时的情况;这个选项应该禁用。
/proc/sys/net/ipv4/tcp_westwood "0" 启用发送者端的拥塞控制算法,它可以维护对吞吐量的评估,并试图对带宽的整体利用情况进行优化;对于 WAN 通信来说应该启用这个选项。
/proc/sys/net/ipv4/tcp_bic "1" 为快速长距离网络启用 Binary Increase Congestion;这样可以更好地利用以 GB 速度进行操作的链接;对于 WAN 通信应该启用这个选项。

与任何调优努力一样,最好的方法实际上就是不断进行实验。您的应用程序的行为、处理器的速度以及可用内存的多少都会影响到这些参数影响性能的方式。在某些情况中,您认为有益的操作可能恰恰是有害的(反之亦然)。因此,我们需要逐一试验各个选项,然后检查每个选项的结果。换而言之,我们需要相信自己的经验,但是对每次修改都要进行验证。

提示:下面介绍一个有关永久性配置的问题。注意,如果您重新启动了 GNU/Linux 系统,那么您所需要的任何可调节的内核参数都会恢复成默认值。为了将您所设置的值作为这些参数的默认值,可以使用 /etc/sysctl.conf 在系统启动时将这些参数配置成您所设置的值。



回页首


GNU/Linux 工具

GNU/Linux 对我非常有吸引力,这是因为其中有很多工具可以使用。尽管其中大部分都是命令行工具,但是它们都非常有用,而且非常直观。GNU/Linux 提供了几个工具 —— 有些是 GNU/Linux 自己提供的,有些是开放源码软件 —— 用于调试网络应用程序,测量带宽/吞吐量,以及检查链接的使用情况。

表 2 列出最有用的几个 GNU/Linux 工具,以及它们的用途。表 3 列出了 GNU/Linux 发行版没有提供的几个有用工具。有关表 3 中工具的更多信息请参阅 参考资料

表 2. 任何 GNU/Linux 发行版中都可以找到的工具
GNU/Linux 工具 用途
ping 这是用于检查主机的可用性的最常用的工具,但是也可以用于识别带宽延时产品计算的 RTT。
traceroute 打印某个连接到网络主机所经过的包括一系列路由器和网关的路径(路由),从而确定每个 hop 之间的延时。
netstat 确定有关网络子系统、协议和连接的各种统计信息。
tcpdump 显示一个或多个连接的协议级的报文跟踪信息;其中还包括时间信息,您可以使用这些信息来研究不同协议服务的报文时间。

表 3. GNU/Linux 发行版中没有提供的有用性能工具
GNU/Linux 工具 用途
netlog 为应用程序提供一些有关网络性能方面的信息。
nettimer 为瓶颈链接带宽生成一个度量标准;可以用于协议的自动优化。
Ethereal 以一个易于使用的图形化界面提供了 tcpump(报文跟踪)的特性。
iperf 测量 TCP 和 UDP 的网络性能;测量最大带宽,并汇报延时和数据报的丢失情况。



回页首


结束语

尝试使用本文中介绍的技巧和技术来提高 socket 应用程序的性能,包括通过禁用 Nagle 算法来减少传输延时,通过设置缓冲区的大小来提高 socket 带宽的利用,通过最小化系统调用的个数来降低系统调用的负载,以及使用可调节的内核参数来优化 Linux 的 TCP/IP 栈。

在进行优化时还需要考虑应用程序的特性。例如,您的应用程序是基于 LAN 的还是会通过 Internet 进行通信?如果您的应用程序仅仅会在 LAN 内部进行操作,那么增大 socket 缓冲区的大小可能不会带来太大的改进,不过启用巨帧却一定会极大地改进性能!

最后,还要使用 tcpdumpEthereal 来检查优化之后的结果。在报文级看到的变化可以帮助展示使用这些技术进行优化之后所取得的成功效果。



回页首


参考资料

学习

获得产品和技术

讨论
posted @ 2006-02-15 09:34 深蓝色心情 阅读(415) | 评论 (0)编辑 收藏

Oracle Database 10g (10.1.0.2) Installation On RedHat Advanced Server 4.0

In this article I'll describe the installation of Oracle Database 10g (10.1.0.2) on RedHat Advanced Server 4.0. The article is based on a server installation with a minimum of 2G swap, secure Linux disabled and the following package groups installed:
  • X Window System
  • GNOME Desktop Environment
  • Editors
  • Graphical Internet
  • Text-based Internet
  • Server Configuration Tools
  • Development Tools
  • Administration Tools
  • System Tools
Alternative installations may require additional packages to be loaded in addition to the ones listed below.

Download Software

Download the following software:

Unpack Files

First unzip the files:
gunzip ship.db.cpio.gz
Next unpack the contents of the files:
cpio -idmv < ship.db.cpio
You should now have a single directory (Disk1) containing installation files.

Hosts File

The /etc/hosts file must contain a fully qualified name for the server:
<IP-address>  <fully-qualified-machine-name>  <machine-name>

Set Kernel Parameters

Add the following lines to the /etc/sysctl.conf file:
kernel.shmall = 2097152
kernel.shmmax = 2147483648
kernel.shmmni = 4096
# semaphores: semmsl, semmns, semopm, semmni
kernel.sem = 250 32000 100 128
fs.file-max = 65536
net.ipv4.ip_local_port_range = 1024 65000
Run the following command to change the current kernel parameters:
/sbin/sysctl -p
Add the following lines to the /etc/security/limits.conf file:
*               soft    nproc   2047
*               hard    nproc   16384
*               soft    nofile  1024
*               hard    nofile  65536
Add the following line to the /etc/pam.d/login file, if it does not already exist:
session    required     /lib/security/pam_limits.so
Note by Kent Anderson: In the event that pam_limits.so cannot set privilidged limit settings see Bug 115442.

Disable secure linux by editing the /etc/selinux/config file, making sure the SELINUX flag is set as follows:
SELINUX=disabled
Alternatively, this alteration can be done using the GUI tool (Applications > System Settings > Security Level). Click on the SELinux tab and disable the feature.

Setup

Install the following packages:
# From RedHat AS4 Disk 2
cd /media/cdrom/RedHat/RPMS
rpm -Uvh setarch-1.6-1.i386.rpm
rpm -Uvh compat-libstdc++-33-3.2.3-47.3.i386.rpm

# From RedHat AS4 Disk 3
cd /media/cdrom/RedHat/RPMS
rpm -Uvh openmotif-2.2.3-6.RHEL4.2.i386.rpm
rpm -Uvh compat-db-4.1.25-9.i386.rpm

# From RedHat AS4 Disk 4
cd /media/cdrom/RedHat/RPMS
rpm -Uvh compat-gcc-32-3.2.3-47.3.i386.rpm
rpm -Uvh compat-gcc-32-c++-3.2.3-47.3.i386.rpm
Create the new groups and users:
groupadd oinstall
groupadd dba
groupadd oper

useradd -g oinstall -G dba oracle
passwd oracle
Create the directories in which the Oracle software will be installed:
mkdir -p /u01/app/oracle/product/10.1.0/db_1
chown -R oracle.oinstall /u01
Login as root and issue the following command:
xhost +<machine-name>
Edit the /etc/redhat-release file replacing the current release information (Red Hat Enterprise Linux AS release 4 (Nahant)) with the following:
redhat-3
Login as the oracle user and add the following lines at the end of the .bash_profile file:
# Oracle Settings
TMP=/tmp; export TMP
TMPDIR=$TMP; export TMPDIR

ORACLE_BASE=/u01/app/oracle; export ORACLE_BASE
ORACLE_HOME=$ORACLE_BASE/product/10.1.0/db_1; export ORACLE_HOME
ORACLE_SID=TSH1; export ORACLE_SID
ORACLE_TERM=xterm; export ORACLE_TERM
PATH=/usr/sbin:$PATH; export PATH
PATH=$ORACLE_HOME/bin:$PATH; export PATH

LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/lib; export LD_LIBRARY_PATH
CLASSPATH=$ORACLE_HOME/JRE:$ORACLE_HOME/jlib:$ORACLE_HOME/rdbms/jlib; export CLASSPATH
#LD_ASSUME_KERNEL=2.4.1; export LD_ASSUME_KERNEL

if [ $USER = "oracle" ]; then
  if [ $SHELL = "/bin/ksh" ]; then
    ulimit -p 16384
    ulimit -n 65536
  else
    ulimit -u 16384 -n 65536
  fi
fi

Installation

Log into the oracle user. If you are using X emulation then set the DISPLAY environmental variable:
DISPLAY=<machine-name>:0.0; export DISPLAY
Start the Oracle Universal Installer (OUI) by issuing the following command in the Disk1 directory:
./runInstaller
During the installation enter the appropriate ORACLE_HOME and name then continue with a "software only" installation.

Post Installation

Create a new instance using the DBCA. If you get the "ORA-27125: unable to create shared memory segment" error when using the DBCA issue the following commands as the oracle user then try again:
cd $ORACLE_HOME/bin

mv oracle oracle.bin

cat >oracle <<"EOF"
#!/bin/bash
 
export DISABLE_HUGETLBFS=1
exec $ORACLE_HOME/bin/oracle.bin $@
EOF
 
chmod +x oracle
I didn't encounter the previous issue myself, so hopefully you won't either.

Edit the /etc/redhat-release file restoring the original release information:
Red Hat Enterprise Linux AS release 4 (Nahant)
Finally edit the /etc/oratab file setting the restart flag for each instance to 'Y':
TSH1:/u01/app/oracle/product/10.1.0/db_1:Y
Create a file called /etc/init.d/dbora containing the following:
#!/bin/sh
# description: Oracle auto start-stop script.
# chkconfig: - 20 80
#
# Set ORA_HOME to be equivalent to the $ORACLE_HOME
# from which you wish to execute dbstart and dbshut;
#
# Set ORA_OWNER to the user id of the owner of the 
# Oracle database in ORA_HOME.
ORA_HOME=/u01/app/oracle/product/10.1.0/db_1
ORA_OWNER=oracle
if [ ! -f $ORA_HOME/bin/dbstart ]
then
    echo "Oracle startup: cannot start"
    exit
fi
case "$1" in
    'start')
        # Start the Oracle databases:
        # The following command assumes that the oracle login 
        # will not prompt the user for any values
        su - $ORA_OWNER -c "$ORA_HOME/bin/lsnrctl start"
        su - $ORA_OWNER -c $ORA_HOME/bin/dbstart
        ;;
    'stop')
        # Stop the Oracle databases:
        # The following command assumes that the oracle login 
        # will not prompt the user for any values
        su - $ORA_OWNER -c $ORA_HOME/bin/dbshut
        su - $ORA_OWNER -c "$ORA_HOME/bin/lsnrctl stop"
        ;;
esac
Use chmod to set the privileges to 750:
chmod 750 /etc/init.d/dbora
Link the file into the appropriate run-level script directories:
ln -s /etc/init.d/dbora /etc/rc0.d/K10dbora
ln -s /etc/init.d/dbora /etc/rc3.d/S99dbora
Associate the dbora service with the appropriate run levels:
chkconfig --level 345 dbora on
The relevant instances should now startup/shutdown automatically at system startup/shutdown.

For more information see:
Hope this helps. Regards Tim...

Back to the Top.
posted @ 2006-01-19 14:08 深蓝色心情 阅读(830) | 评论 (0)编辑 收藏

     摘要: Here is a summary (HOWTO) how I installed: Oracle 9iR2 (9.2.0.6.0) Database on Red Hat Advanced Server 4 (x86, kernel 2.6.9-5.EL, glibc-2.3.4-2) Oracle 9iR2 (9.2.0) Database on Red Hat Advanced Server...  阅读全文
posted @ 2006-01-19 13:51 深蓝色心情 阅读(2329) | 评论 (0)编辑 收藏



Hibernate配置文件可以有两种格式,一种是 hibernate.properties ,另一种是 hibernate.cfg.xml 

后者稍微方便一些,当增加hbm映射文件的时候,可以直接在 hibernate.cfg.xml 里面增加,不必像 hibernate.properties 必须在初始化代码中加入。

但不管怎么说,两种的配置项都是一样的,下面详细介绍:

在Hibernate的src目录下有一个 hibernate.properties 模板,我们不必自己从头写,修改模板就可以了:)

hibernate.query.substitutions true 1, false 0, yes 'Y', no 'N' 


这个配置意思是当你在Hibernate里面输入true的时候,Hibernate会转化为1插入数据库,当你在Hibernate里面输入false的时候,Hibernate会转化为0插入数据库,后面的Y,N同理。

对于某些数据库,例如Oracle来说,没有boolean数据类型,就是采用1代表true,0代表false,因此使用这个配置在Hibernate里面直接用true/false会非常直观。

1hibernate.dialect net.sf.hibernate.dialect.MySQLDialect 
2hibernate.connection.driver_class com.mysql.jdbc.Driver 
3hibernate.connection.url jdbc:mysql:///test 
4hibernate.connection.username root 
5hibernate.connection.password  
6


这是一个连接MySQL数据库的例子,很直观,不必解释,不同的数据库的连接参数模板中全部给出了。


hibernate.connection.pool_size 1
hibernate.statement_cache.size 25

这是Hibernate自带的连接池的配置参数,在默认情况下将采用。意义很直观,不多解释。

只是提醒一点,Hibernate这个连接池是非常原始非常简单的连接池,如果你在项目中用Hibernate的话,建议你首选App Server的连接池,次选Hibernate带的DBCP连接池。自带的连接池应该做为末选。

如果你采用DBCP连接池,除了要配置DBCP连接池以外,还需要取消掉下行的注释:

hibernate.connection.provider_class net.sf.hibernate.connection.DBCPConnectionProvider

其它的连接池同理。

如果采用App Server的连接池,假设App Server连接池的DataSource的JNDI名称为"mypool"的话,配置应该如下:

hibernate.dialect net.sf.hibernate.dialect.MySQLDialect
hibernate.connection.datasource mypool
hibernate.connection.provider_class net.sf.hibernate.connection.DatasourceConnectionProvider

其它参数就不必写了,因为已经在App Server配置连接池的时候指定好了。

如果你不是在App Server环境中使用Hibernate,例如远程客户端程序,但是你又想用App Server的数据库连接池,那么你还需要配置JNDI的参数,例如Hibernate连接远程Weblogic上的数据库连接池:

hibernate.dialect net.sf.hibernate.dialect.MySQLDialect
hibernate.connection.datasource mypool
hibernate.connection.provider_class net.sf.hibernate.connection.DatasourceConnectionProvider
hibernate.jndi.class weblogic.jndi.WLInitialContextFactory
hibernate.jndi.url t3://servername:7001/


最后,如果你需要在EJB或者JTA中使用Hibernate,需要取消下行的注释:

hibernate.transaction.factory_class net.sf.hibernate.transaction.JTATransactionFactory

杂项配置:


hibernate.show_sql false

是否将Hibernate发送给数据库的sql显示出来,这是一个非常非常有用处的功能。当你在调试Hibernate的时候,让Hibernate打印sql语句,可以帮助你迅速解决问题。


#hibernate.connection.isolation 4

指定数据库的隔离级别,往往不同的数据库有自己定义的隔离级别,未必是Hibernate的设置所能更改的,所以也不必去管它了。

hibernate.jdbc.fetch_size 50 
hibernate.jdbc.batch_size 25 


这两个选项非常非常非常重要!!!将严重影响Hibernate的CRUD性能!

C = create, R = read, U = update, D = delete

Fetch Size 是设定JDBC的Statement读取数据的时候每次从数据库中取出的记录条数。

例如一次查询1万条记录,对于Oracle的JDBC驱动来说,是不会1次性把1万条取出来的,而只会取出Fetch Size条数,当纪录集遍历完了这些记录以后,再去数据库取Fetch Size条数据。

因此大大节省了无谓的内存消耗。当然Fetch Size设的越大,读数据库的次数越少,速度越快;Fetch Size越小,读数据库的次数越多,速度越慢。

这有点像平时我们写程序写硬盘文件一样,设立一个Buffer,每次写入Buffer,等Buffer满了以后,一次写入硬盘,道理相同。

Oracle数据库的JDBC驱动默认的Fetch Size=10,是一个非常保守的设定,根据我的测试,当Fetch Size=50的时候,性能会提升1倍之多,当Fetch Size=100,性能还能继续提升20%,Fetch Size继续增大,性能提升的就不显著了。

因此我建议使用Oracle的一定要将Fetch Size设到50。

不过并不是所有的数据库都支持Fetch Size特性,例如MySQL就不支持。

MySQL就像我上面说的那种最坏的情况,他总是一下就把1万条记录完全取出来,内存消耗会非常非常惊人!这个情况就没有什么好办法了 :(

Batch Size是设定对数据库进行批量删除,批量更新和批量插入的时候的批次大小,有点相当于设置Buffer缓冲区大小的意思。

Batch Size越大,批量操作的向数据库发送sql的次数越少,速度就越快。我做的一个测试结果是当Batch Size=0的时候,使用Hibernate对Oracle数据库删除1万条记录需要25秒,Batch Size = 50的时候,删除仅仅需要5秒!!!

可见有多么大的性能提升!很多人做Hibernate和JDBC的插入性能测试会奇怪的发现Hibernate速度至少是JDBC的两倍,就是因为Hibernate使用了Batch Insert,而他们写的JDBC没有使用Batch的缘故。

以我的经验来看,Oracle数据库 Batch Size = 30 的时候比较合适,50也不错,性能会继续提升,50以上,性能提升的非常微弱,反而消耗内存更加多,就没有必要了。


#hibernate.jdbc.use_scrollable_resultset true

设定是否可以使用JDBC2.0规范的可滚动结果集,这对Hibernate的分页显示有一定的作用,默认就好了。

#hibernate.cglib.use_reflection_optimizer false 


默认打开,启用cglib反射优化。cglib是用来在Hibernate中动态生成PO字节码的,打开优化可以加快字节码构造的速度。

不过,当你在调试程序过程中,特别是和proxy,lazy loading相关的应用中,代码出错,但是出错提示信息有语焉不详,那么你可以把cglib优化关掉,这样Hibernate会输出比较详细的调试信息,帮助你debug。
posted @ 2005-12-02 11:48 深蓝色心情 阅读(487) | 评论 (0)编辑 收藏

 
数据库驱动更新为classes12-9i.jar
修改hibernate的配置如下
代码
<bean id="nativeJdbcExtractor" class="org.springframework.jdbc.support.nativejdbc.SimpleNativeJdbcExtractor"/>

<bean id="oracleLobHandle" class="org.springframework.jdbc.support.lob.OracleLobHandler" Lazy-init="true">
 
<property name="nativeJdbcExtractor">
   
<ref local="nativejdbcExtractor"/>
 
</property>
</bean>


在有clob类型sessionFactory(org.springframework.com.hibernate.LocalSessionFractoryBean)中加入
<property name="lobHandler"><ref bean="oracleLobHandle"/></property>

在需要clob的JavaBean对应的hbm.xml中,改对应的clob类型的字段

代码
<property
 
name=""
 type
="org.springframework.orm.hibernate.support.ClobStringType"
 clumn
=""
 length
="XXXXXX" <!--定义clob字段大小(以字节为单位,最大2GB)-->
>

JavaBean的对应的属性类型为String

------------------------------------------------------------------------------
----hibernate3 使用blob 和 clob 演例代码-----

hibernate3 使用blob 和 clob 演例代码:

 1import java.io.File;
 2import java.io.FileInputStream;
 3import java.io.OutputStream;
 4import java.io.Writer;
 5import java.sql.Clob;
 6import oracle.sql.CLOB;
 7import org.hibernate.LockMode;
 8import org.hibernate.Transaction;
 9import org.hibernate.Session;
10import org.hibernate.Hibernate;
11import org.hibernate.lob.SerializableBlob;
12import org.hibernate.lob.SerializableClob;
13
14
15public class test1 {
16
17        /**
18         * @param args
19         */

20        static Session session = HibernateSessionFactory.currentSession();
21        
22        public boolean inserted(TStu obj){
23                
24                Transaction tran = session.beginTransaction();
25                session.save(obj);
26                session.flush();
27                session.refresh(obj,LockMode.UPGRADE);
28                try
29                {
30                SerializableBlob sb = (SerializableBlob)obj.getImg();
31                java.sql.Blob wrapblob = sb.getWrappedBlob();
32                if(wrapblob instanceof oracle.sql.BLOB){
33                         oracle.sql.BLOB blob = (oracle.sql.BLOB) wrapblob;
34                OutputStream bout = blob.getBinaryOutputStream();
35                FileInputStream fin = new FileInputStream("d:\\a.jpg");//修改你要存入的图片
36                byte [] buf = new byte[10240];//做为10K的缓存写入
37                int len;
38                while((len = fin.read(buf))>0){
39                        bout.write(buf,0,len);
40                }

41                bout.close();
42                fin.close();
43                }

44                
45                SerializableClob  sc = (SerializableClob)obj.getResu();
46                Clob wrapclob = sc.getWrappedClob();
47                if(wrapclob instanceof CLOB){
48                        CLOB clob = (CLOB)wrapclob; 
49                        Writer cout = clob.getCharacterOutputStream();
50                        File file = new File("C:\\log_2005_8.txt");//修改你要存如的文本
51                        FileInputStream fin = new FileInputStream(file);
52                        int read;
53                        while((read = fin.read())!= -1){
54                                cout.write(read);
55                        }

56                        fin.close();
57                        cout.close();
58                }

59                
60                tran.commit();
61                return true;
62                }
catch(Exception ex){
63                        ex.printStackTrace();
64                        tran.rollback();
65                        return false;
66                }

67        }

68        
69        public static void main(String[] args) {
70                // TODO Auto-generated method stub         
71                test1 t = new test1();
72                 TStu stu = new TStu();
73                 stu.setAge(new Integer("23"));
74                 stu.setName("lilei");
75                 stu.setImg(Hibernate.createBlob(new byte[1]));
76                 stu.setResu(Hibernate.createClob(" "));
77                 t.inserted(stu);        
78        }

79}

80
81



org link: http://www.matrix.org.cn/thread.shtml?topicId=27138&forumId=23
posted @ 2005-11-18 10:42 深蓝色心情 阅读(2539) | 评论 (2)编辑 收藏

仅列出标题
共4页: 上一页 1 2 3 4 下一页