- 2010年6月2日
- 修改悬浮层Bug
- 增加Flash MP3播放器
- 2010年6月1日
- 修改foreach方法张存在的Bug
- 增加问卷调查标签1.5版
- 2010年5月3日
- 增加Flash标签-底部-音乐播放器
- 修改Flash标签存在的不足
- 2010年05月10日
- 测试版v1.5.0可以内测
迅捷AJAX标签库更新记录说明
正則表達式集錦
只能输入 n 位的数字:"^\d{n}$"
只能输入至少 n 位的数字:"^\d{n,}$"
只能输入 m ~ n 位的数字:"^\d{m,n}$"
只能输入零和非零开头的数字:"^(0|[1-9][0-9]*)$"
只能输入有两位小数的正实数:"^[0-9]+(.[0-9]{2})?$"
只能输入有 1~3 位小数的正实数:"^[0-9]+(.[0-9]{1,3})?$"
只能输入非零的正整数:"^\+?[1-9][0-9]*$"
只能输入非零的负整数:"^\-[1-9][0-9]*$"
只能输入长度位 3 的字符:"^.{3}$"
只能输入由 26 个英文字母组成的字符串:"^[A-Za-z]+$"
只能输入由 26 个大写英文字母组成的字符串:"^[A-Z]+$"
只能输入由 26 个小写英文字母组成的字符串:"^[a-z]+$"
只能输入由数字和 26 个英文字母组成的字符串:"^[A-Za-z0-9]+$"
只能输入由数字、26个英文字母或者下划线组成的字符串:"^\w+$"
验证用户密码: "^[a-zA-Z]\w{5,17}$" 正确格式位:以字母开头,长度在6~18之间,只能包含字符、数字和下划线
验证是否含有非法字符 ^(?:[\u4e00-\u9fa5]*\w*\s*)+$
只能输入汉字:"^[\u4e00-\u9fa5]{0,}$"
验证 Email 地址:"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$"
验证 InternetURL:"^http://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?$"
中国电话号码验证
匹配形式如:0511-4405222 或者021-87888822 或者 021-44055520-555 或者 (0511)4405222
正则表达式 "((d{3,4})|d{3,4}-)?d{7,8}(-d{3})*"
中国邮政编码验证
匹配形式如:215421
正则表达式 "d{6}"
电子邮件验证
匹配形式如:justali@justdn.com
正则表达式 "w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*"
身份证验证
匹配形式如:15位或者18位身份证
正则表达式 "d{18}|d{15}"
常用数字验证
正则表达式
"d{n}" n为规定长度
"d{n,m}" n到m的长度范围
非法字符验证
匹配排除非法字符的字符如:
正则表达式 ^(?:[\u4e00-\u9fa5]*\w*\s*)+$
日期验证
匹配形式如:20030718,030718
范围:1900--2099
正则表达式((((19){1}|(20){1})d{2})|d{2})[01]{1}d{1}[0-3]{1}d{1}
使用实例:
Untitled Page
function Button1_onclick() {
if(!test_hanzi(document.form1.Text1.value))
{
alert("姓名只能是汉字");
return false;
}
return true;
}
//验证电子邮件
function test_email(strEmail) {
var myReg = /^[_a-z0-9]+@([_a-z0-9]+\.)+[a-z0-9]{2,3}$/;
if(myReg.test(strEmail)) return true;
return false;
}
//只能输入数字
function test_shuzi(strshuzi) {
var myReg =/^[0-9]*$/;
if(myReg.test(strshuzi)) return true;
return false;
}
//只能输入汉字
function test_hanzi(strhanzi) {
var myReg =/^[\u4e00-\u9fa5]{0,}$/;
if(myReg.test(strhanzi)) return true;
return false;
}
// -->
软件开发模式
1、结构化方法
结构化开发方法是由E.Yourdon 和 L.L.Constantine 提出的,即所谓的SASD 方 法, 也可称为面向功能的软件开发方法或面向数据流的软件开发方法。Yourdon方法是80年代 使用最广泛的软件开发方法。它首先用结构化分析(SA)对软件进行需求分析,然后用结构化设计(SD)方法进行总体设计,最后是结构化编程(SP)。它给 出了两类典型的软件结构(变换型和事务型)使软件开发的成功率大大提高。
2、面向数据结构的软件开发方法
Jackson方法是最典型的面向数据结构的软件开发方法,Jackson方法把问题分解为可由三种基本结构形式表示的各部分的层次结构。三种基本的结构 形式就是顺序、选择和重复。三种数据结构可以进行组合,形成复杂的结构体系。这一方法从目标系统的输入、输出数据结构入手,导出程序框架结构,再补充其它 细节,就可得到完整的程序结构图。这一方法对输入、输出数据结构明确的中小型系统特别有效,如商业应用中的文件表格处理。该方法也可与其它方法结合,用于 模块的详细设计。
3、 面向问题的分析法
PAM(Problem Analysis Method)是80年代末由日立公司提出的一种软件开发方法。 它的基本思想是考虑到输入、输出数据结构,指导系统的分解,在系统分析指导下逐步综 合。这一方法的具体步骤是:从输入、输出数据结构导出基本处理框;分析这些处理框之间的先后关系;按先后关系逐步综合处理框,直到画出整个系统的PAD 图。这一方法本质上是综合的自底向上的方法,但在逐步综合之前已进行了有目的的分解,这个目的就是充分考虑系统的输入、输出数据结构。PAM方法的另一个 优点是使用PAD图。这是一种二维树形结构图,是到目前为止最好的详细设计表示方法之一。当然由于在输入、输出数据结构与整个系统之间同样存在着鸿沟,这 一方法仍只适用于中小型问题。
4、原型化方法
产生原型化方法的原因很多,主要随着我们系统开发经验的增多,我们也发现并非所有的需求都能够预先定义而且反复修改是不可避免的。当然能够采用原型化方法 是因为开发工具的快速发展,比如用VB,DELPHI等工具我们可以迅速的开发出一个可以让用户看的见、摸的着的系统框架,这样,对于计算机不是很熟悉的 用户就可以根据这个样板提出自己的需求。
开发原型化系统一般由以下几个阶段:
(1) 确定用户需求
(2) 开发原始模型
(3) 征求用户对初始原型的改进意见
(4) 修改原型。
原型化开发比较适合于用户需求不清、业务理论不确定、需求经常变化的情况。当系统规模不是很大也不太复杂时采用该方法是比较好的。
5、面向对象的软件开发方法
当前计算机业界最流行的几个单词就是分布式、并行和面向对象这几个术语。由此可以看到面向对象这个概念在当前计算机业界的地位。比如当前流行的两大面向对 象技术DCOM和CORBA就是例子。当然我们实际用到的还是面向对象的编程语言,比如C++。不可否认,面向对象技术是软件技术的一次革命,在软件开发 史上具有里程碑的意义。
随着OOP(面向对象编程)向OOD(面向对象设计)和OOA(面向对象分析)的发展,最终形成面向对象的软件开发方法OMT (Object Modeling Technique)。这是一种自底向上和自顶向下相结合的方法,而且它以对象建模为基础,从而不仅考虑了输入、输出数据结构,实际上也包含了所有对象的 数据结构。所以OMT彻底实现了PAM没有完全实现的目标。不仅如此,OO技术在需求分析、可维护性和可靠性这三个软件开发的关键环节和质量指标上有了实 质性的突破,基本地解决了在这些方面存在的严重问题。
综上所述,面向对象系统采用了自底向上的归纳、自顶向下的分解的方法,它通过对对象模型的建立,能够真正建立基于用户的需求,而且系统的可维护性大大改善。当前业界关于面向对象建模的标准是UML(Unified Modeling Language)。
这里我们需要谈一下微软的MSF(Microsoft Solutions Framework)的框架,它简单的把系统设计分成三个阶段:概念设计、逻辑设计和物理设计。概念设计阶段就是从用户的角度出发可以得到多少个对象,并 且以对象为主体,画出业务框架。逻辑设计阶段就是对概念设计阶段的对象进行再分析、细分、整合、删除。并建立各个对象的方法属性以及对象之间的关系。而物 理设计实际上就是要确定我们实际需要的组件、服务和采用的框架结构、具体的编程语言等。MCF整个结构比较清楚是基于对象开发的一个比较好的可操作的框架 系统。
6、可视化开发方法
其实可视化开发并不能单独的作为一种开发方法,更加贴切的说可以认为它是一种辅助工具,比如用过SYBASE的S-Design的人都知道,用这个工具可 以进行显示的图形化的数据库模式的建立,并可以导入到不同的数据库中去。当然用过S-Design的人不一定很多,但用过VB,DELPHI,C++ Builder等开发工具的人一定不少,实际上你就是在使用可视化开发工具。
当然,不可否认的是,你只是在编程这个环节上用了可视化,而不是在系统分析和系统设计这个高层次上用了可视化的方法。实际上,建立系统分析和系统设计的可 视化工具是一个很好的卖点,国外有很多工具都致力于这方面产品的设计。比如Business Object就是一个非常好的数据库可视化分析工具。
可视化开发使我们把注意力集中在业务逻辑和业务流程上,用户界面可以用可视化工具方便的构成。通过操作界面元素,诸如菜单、按钮、对话框、编辑框、单选框、复选框、 列表框和滚动条等,由可视开发工具自动生成应用软件。
java 注释规范
JAVA注释规范
版本/状态 作者 版本日期
1.0 ghc 2008-07-02
一、背景
1、当我们第一次接触某段代码,但又被要求在极短的时间内有效地分析这段代码,我们需要什么样的注释信息?
2、怎么样避免我们的注释冗长而且凌乱不堪呢?
3、在多人协同开发、维护的今天,我们需要怎么样的注释来保证高质、高交的进行开发和维护工作呢?
二、意义
程序中的注释是程序设计者与程序阅读者之间通信的重要手段。应用注释规范对于软件本身和软件开发人员而言尤为重要。并且在流行的敏捷开发思想中已经提出了将注释转为代码的概念。好的注释规范可以尽可能的减少一个软件的维护成本 , 并且几乎没有任何一个软件,在其整个生命周期中,均由最初的开发人员来维护。好的注释规范可以改善软件的可读性,可以让开发人员尽快而彻底地理解新的代码。好的注释规范可以最大限度的提高团队开发的合作效率。长期的规范性编码还可以让开发人员养成良好的编码习惯,甚至锻炼出更加严谨的思维能力。
三、注释的原则
1、 注释形式统一
在整个应用程序中,使用具有一致的标点和结构的样式来构造注释。如果在其他项目组发现他们的注释规范与这份文档不同,按照他们的规范写代码,不要试图在既成的规范系统中引入新的规范。
2、 注释的简洁
内容要简单、明了、含义准确,防止注释的多义性,错误的注释不但无益反而有害。
3、 注释的一致性
在写代码之前或者边写代码边写注释,因为以后很可能没有时间来这样做。另外,如果有机会复查已编写的代码,在今天看来很明显的东西六周以后或许就不明显了。通常描述性注释先于代码创建,解释性注释在开发过程中创建,提示性注释在代码完成之后创建。修改代码的同时修改相应的注释,以保证代码与注释的同步。
4、 注释的位置
保证注释与其描述的代码相邻,即注释的就近原则。对代码的注释应放在其上方相邻或右方的位置,不可放在下方。避免在代码行的末尾添加注释;行尾注释使代码更难阅读。不过在批注变量声明时,行尾注释是合适的;在这种情况下,将所有行尾注释要对齐。
5、 注释的数量
注释必不可少,但也不应过多,在实际的代码规范中,要求注释占程序代码的比例达到20%左右。注释是对代码的“提示”,而不是文档,程序中的注释不可喧宾夺主,注释太多了会让人眼花缭乱,注释的花样要少。不要被动的为写注释而写注释。
6、删除无用注释
在代码交付或部署发布之前,必须删掉临时的或无关的注释,以避免在日后的维护工作中产生混乱。
7、 复杂的注释
如果需要用注释来解释复杂的代码,请检查此代码以确定是否应该重写它。尽一切可能不注释难以理解的代码,而应该重写它。尽管一般不应该为了使代码更简单便于使用而牺牲性能,但必须保持性能和可维护性之间的平衡。
8、 多余的注释
描述程序功能和程序各组成部分相互关系的高级注释是最有用的,而逐行解释程序如何工作的低级注释则不利于读、写和修改,是不必要的,也是难以维护的。避免每行代码都使用注释。如果代码本来就是清楚、一目了然的则不加注释,避免多余的或不适当的注释出现。
9、必加的注释
典型算法必须有注释。在代码不明晰或不可移植处必须有注释。在代码修改处加上修改标识的注释。在循环和逻辑分支组成的代码中添加注释。为了防止问题反复出现,对错误修复和解决方法的代码使用注释,尤其是在团队环境中。
10、注释在编译代码时会被忽略,不编译到最后的可执行文件中,所以注释不
会增加可执行文件的大小。
四、JAVA注释技巧
1、空行和空白字符也是一种特殊注释。利用缩进和空行,使代码与注释容易区
别,并协调美观。
2、当代码比较长,特别是有多重嵌套时,为了使层次清晰,应当在一些段落的
结束处加注释(在闭合的右花括号后注释该闭合所对应的起点),注释不能
写得很长,只要能表示是哪个控制语句控制范围的结束即可,这样便于阅读。
3、将注释与注释分隔符用一个空格分开,在没有颜色提示的情况下查看注释时,
这样做会使注释很明显且容易被找到。
4、不允许给块注释的周围加上外框。这样看起来可能很漂亮,但是难于维护。
5、每行注释(连同代码)不要超过120个字(1024×768),最好不要超过80
字(800×600) 。
6、Java编辑器(IDE)注释快捷方式。Ctrl+/ 注释当前行,再按则取消注释。
7、对于多行代码的注释,尽量不采用“/*......*/”,而采用多行“//”注释,
这样虽然麻烦,但是在做屏蔽调试时不用查找配对的“/*......*/”。
8、注释作为代码切换开关,用于临时测试屏蔽某些代码。
例一:
//*/
codeSegement1;
//*/
改动第一行就成了:
/*/
codeSegement1;
//*/
例二:
//----------------------第一段有效,第二段被注释
//*/
codeSegement1;
/*/
codeSegement2;
//*/
只需删除第一行的/就可以变成:
//----------------------第一段被注释,第二段有效
/*/
codeSegement1;
/*/
codeSegement2;
//*/
五、JAVA注释方法及格式
1、单行(single-line)--短注释://……
单独行注释:在代码中单起一行注释, 注释前最好有一行空行,并与其后的代码具有一样的缩进层级。如果单行无法完成,则应采用块注释。
注释格式:/* 注释内容 */
行头注释:在代码行的开头进行注释。主要为了使该行代码失去意义。
注释格式:// 注释内容
行尾注释:尾端(trailing)--极短的注释,在代码行的行尾进行注释。一般与代码行后空8(至少4)个格,所有注释必须对齐。
注释格式:代码 + 8(至少4)个空格 + // 注释内容
2、块(block)--块注释:/*……*/
注释若干行,通常用于提供文件、方法、数据结构等的意义与用途的说明,或者算法的描述。一般位于一个文件或者一个方法的前面,起到引导的作用,也可以根据需要放在合适的位置。这种域注释不会出现在HTML报告中。注释格式通常写成:
/*
* 注释内容
*/
3、文档注释:/**……*/
注释若干行,并写入javadoc文档。每个文档注释都会被置于注释定界符
/**......*/之中,注释文档将用来生成HTML格式的代码报告,所以注释文
档必须书写在类、域、构造函数、方法,以及字段(field)定义之前。注释文档由两部分组成——描述、块标记。注释文档的格式如下:
/**
* The doGet method of the servlet.
* This method is called when a form has its tag value method
* equals to get.
* @param request
* the request send by the client to the server
* @param response
* the response send by the server to the client
* @throws ServletException
* if an error occurred
* @throws IOException
* if an error occurred
*/
public void doGet (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
前两行为描述,描述完毕后,由@符号起头为块标记注释。更多有关文档注
释和javadoc的详细资料,参见javadoc的主页: http://java.sun.com/javadoc/index.html
4、javadoc注释标签语法
@author 对类的说明 标明开发该类模块的作者
@version 对类的说明 标明该类模块的版本
@see 对类、属性、方法的说明 参考转向,也就是相关主题
@param 对方法的说明 对方法中某参数的说明
@return 对方法的说明 对方法返回值的说明
@exception 对方法的说明 对方法可能抛出的异常进行说明
六、JAVA注释具体实现
1、源文件注释
源文件注释采用 /** …… */,在每个源文件的头部要有必要的注释信息,包括:文件名;文件编号;版本号;作者;创建时间;文件描述包括本文件历史修改记录等。中文注释模版:
/**
* 文 件 名 :
* CopyRright (c) 2008-xxxx:
* 文件编号:
* 创 建 人:
* 日 期:
* 修 改 人:
* 日 期:
* 描 述:
* 版 本 号:
*/
2、类(模块)注释:
类(模块)注释采用 /** …… */,在每个类(模块)的头部要有必要的注释信息,包括:工程名;类(模块)编号;命名空间;类可以运行的JDK版本;版本号;作者;创建时间;类(模块)功能描述(如功能、主要算法、内部各部分之间的关系、该类与其类的关系等,必要时还要有一些如特别的软硬件要求等说明);主要函数或过程清单及本类(模块)历史修改记录等。
英文注释模版:
/**
* CopyRright (c)2008-xxxx: <展望软件Forsoft >
* Project: <项目工程名 >
* Module ID: <(模块)类编号,可以引用系统设计中的类编号>
* Comments: <对此类的描述,可以引用系统设计中的描述>
* JDK version used:
* Namespace: <命名空间>
* Author: <作者中文名或拼音缩写>
* Create Date: <创建日期,格式:YYYY-MM-DD>
* Modified By: <修改人中文名或拼音缩写>
* Modified Date: <修改日期,格式:YYYY-MM-DD>
* Why & What is modified <修改原因描述>
* Version: <版本号>
*/
如果模块只进行部分少量代码的修改时,则每次修改须添加以下注释:
//Rewriter
//Rewrite Date:<修改日期:格式YYYY-MM-DD> Start1:
/* 原代码内容*/
//End1:
将原代码内容注释掉,然后添加新代码使用以下注释:
//Added by
//Add date:<添加日期,格式:YYYY-MM-DD> Start2:
//End2:
如果模块输入输出参数或功能结构有较大修改,则每次修改必须添加以下
注释:
//Log ID:
//Depiction:<对此修改的描述>
//Writer:修改者中文名
//Rewrite Date:<模块修改日期,格式:YYYY-MM-DD>
2、接口注释:
接口注释采用 /** …… */,在满足类注释的基础之上,接口注释应该包含描述接口的目的、它应如何被使用以及如何不被使用,块标记部分必须注明作者和版本。在接口注释清楚的前提下对应的实现类可以不加注释。
3、构造函数注释:
构造函数注释采用 /** …… */,描述部分注明构造函数的作用,不一定有块标记部分。
注释模版一:
/**
* 默认构造函数
*/
注释模版二:
/**
* Description : 带参数构造函数,
* 初始化模式名,名称和数据源类型
* @param schema: 模式名
* @param name: 名称
* @param type: 数据源类型
*/
4、函数注释:
函数注释采用 /** ……*/,在每个函数或者过程的前面要有必要的注释信息,包括:函数或过程名称;功能描述;输入、输出及返回值说明;调用关系及被调用关系说明等。函数注释里面可以不出现版本号(@version)。
注释模版一:
/**
* 函 数 名 :
* 功能描述:
* 输入参数: <按照参数定义顺序>
* <@param后面空格后跟着参数的变量名字 * (不是类型),空格后跟着对该参数的描述。>
*
* 返 回 值: - 类型 <说明>
* <返回为空(void)的构造函数或者函数, * @return可以省略; 如果返回值就是输入参数,必须 * 用与输入参数的@param相同的描述信息; 必要的时* 候注明特殊条件写的返回值。>
* 异 常:<按照异常名字的字母顺序>
* 创 建 人:
* 日 期:
* 修 改 人:
* 日 期:
*/
注释模版二:
/**
* FunName: getFirstSpell
* Description : 获取汉字拼音首字母的字符串,
* 被生成百家姓函数调用
* @param: str the String是包含汉字的字符串
* @return String:汉字返回拼音首字母字符串;
* 英文字母返回对应的大写字母;
* 其他非简体汉字返回 '0';
* @Author: ghc
* @Create Date: 2008-07-02
*/
5、方法注释:
方法注释采用 /** …… */,对于设置 (Set 方法 ) 与获取 (Get 方法 ) 成员的方法,在成员变量已有说明的情况下,可以不加注释;普通成员方法要求说明完成什么功能,参数含义是什么且返回值什么;另外方法的创建时间必须注释清楚,为将来的维护和阅读提供宝贵线索。
6、方法内部注释:
控制结构,代码做了些什么以及为什么这样做,处理顺序等,特别是复杂的逻辑处理部分,要尽可能的给出详细的注释。
7、 全局变量注释:
要有较详细的注释,包括对其功能、取值范围、哪些函数或者过程存取以及存取时注意事项等的说明。
8、局部(中间)变量注释:
主要变量必须有注释,无特别意义的情况下可以不加注释。
9、实参/参数注释:
参数含义、及其它任何约束或前提条件。
10、字段/属性注释: 字段描述,属性说明。
11、常量:常量通常具有一定的实际意义,要定义相应说明。
Hibernate包作用详解
Hibernate 分页
- Query q = session.createQuery("from Cat as c");;
- q.setFirstResult(20000);;
- q.setMaxResults(100);;
- List l = q.list();;
Query q = session.createQuery("from Cat as c");; q.setFirstResult(20000);; q.setMaxResults(100);; List l = q.list();;
那么Hibernate底层如何实现分页的呢?实际上Hibernate的查询定义在net.sf.hibernate.loader.Loader这个类里面,仔细阅读该类代码,就可以把问题彻底搞清楚。
Hibernate2.0.3的Loader源代码第480行以下:
- if (useLimit); sql = dialect.getLimitString(sql);;
- PreparedStatement st = session.getBatcher();.prepareQueryStatement(sql, scrollable);;
if (useLimit); sql = dialect.getLimitString(sql);; PreparedStatement st = session.getBatcher();.prepareQueryStatement(sql, scrollable);;
如果相应的数据库定义了限定查询记录的sql语句,那么直接使用特定数据库的sql语句。
然后来看net.sf.hibernate.dialect.MySQLDialect:
- public boolean supportsLimit(); {
- return true;
- }
- public String getLimitString(String sql); {
- StringBuffer pagingSelect = new StringBuffer(100);;
- pagingSelect.append(sql);;
- pagingSelect.append(" limit ?, ?");;
- return pagingSelect.toString();;
- }
public boolean supportsLimit(); { return true; } public String getLimitString(String sql); { StringBuffer pagingSelect = new StringBuffer(100);; pagingSelect.append(sql);; pagingSelect.append(" limit ?, ?");; return pagingSelect.toString();; }
这是MySQL的专用分页语句,再来看net.sf.hibernate.dialect.Oracle9Dialect:
- public boolean supportsLimit(); {
- return true;
- }
- public String getLimitString(String sql); {
- StringBuffer pagingSelect = new StringBuffer(100);;
- pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");;
- pagingSelect.append(sql);;
- pagingSelect.append(" ); row_ where rownum <= ?); where rownum_ > ?");;
- return pagingSelect.toString();;
- }
public boolean supportsLimit(); { return true; } public String getLimitString(String sql); { StringBuffer pagingSelect = new StringBuffer(100);; pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");; pagingSelect.append(sql);; pagingSelect.append(" ); row_ where rownum <= ?); where rownum_ > ?");; return pagingSelect.toString();; }
Oracle采用嵌套3层的查询语句结合rownum来实现分页,这在Oracle上是最快的方式,如果只是一层或者两层的查询语句的rownum不能支持order by。
除此之外,Interbase,PostgreSQL,HSQL也支持分页的sql语句,在相应的Dialect里面,大家自行参考。
如果数据库不支持分页的SQL语句,那么根据在配置文件里面
#hibernate.jdbc.use_scrollable_resultset true
默认是true,如果你不指定为false,那么Hibernate会使用JDBC2.0的scrollable result来实现分页,看Loader第430行以下:
- if ( session.getFactory();.useScrollableResultSets(); ); {
- // we can go straight to the first required row
- rs.absolute(firstRow);;
- }
- else {
- // we need to step through the rows one row at a time (slow);
- for ( int m=0; m
- }
if ( session.getFactory();.useScrollableResultSets(); ); { // we can go straight to the first required row rs.absolute(firstRow);; } else { // we need to step through the rows one row at a time (slow); for ( int m=0; m
如果支持scrollable result,使用ResultSet的absolute方法直接移到查询起点,如果不支持的话,使用循环语句,rs.next一点点的移过去。
可见使用Hibernate,在进行查询分页的操作上,是具有非常大的灵活性,Hibernate会首先尝试用特定数据库的分页sql,如果没用,再尝试Scrollable,如果不行,最后采用rset.next()移动的办法。
在查询分页代码中使用Hibernate的一大好处是,既兼顾了查询分页的性能,同时又保证了代码在不同的数据库之间的可移植性。
MySQL的重要語法
MySQL的重要語法
[帳號與權限] [資料庫/資料表/欄位的操作] [紀 錄的操作] [資料的 輸出]
一、帳號與權限
設定 root 和其他 user 的密碼
- mysqladmin -u root password '新密碼'
- mysqladmin -u root -p
- Enter password: 此時再輸入密碼(建議採用)
- use mysql;
mysql> UPDATE user SET password=password('新密碼') where user='root';
只改 root 的密碼,如果沒有用 where ,則表示改全部 user 的密碼 - mysql> FLUSH PRIVILEGES; 在 mysql 資料庫內,一定要用 flush 更新記憶體上的資料
刪除空帳號
- mysql> DELETE FROM user WHERE User = '';
- mysql> FLUSH PRIVILEGES;
建立新帳號
- mysql> GRANT 權限 ON 資料庫或資料表 TO 使用者 IDENTIFIED BY '密碼';
權限
資料庫或資料表
*.* 所有資料庫裡的所有資料表
* 預設資料庫裡的所有資料表
資料庫.* 某一資料庫裡的所有資料表
資料庫.資料表 某一資料庫裡的特定資料表
資料表 預設資料庫裡的某一資料表
設定/修改權限
- 用 root 登入 MySQL
mysqladmin -u root -p
Enter password: - mysql> GRANT all ON db35.* TO s35@'localhost' IDENTIFIED BY 's35';
把 db35 這個資料庫(含其下的所有資料表),授權給 s35,從 localhost 上來,密碼為s35
- mysql> GRANT all ON *.* 把所有資料庫及資料表授權給別人,太危險了!
- mysql> GRANT all??? ON www.* TO '*'@'*' IDENTIFIED BY '';
把 www 這個資料庫(含其下的所有資料表),授權給 任何機器任何人,無密碼(通常給不特定人士使用)
- mysql> FLUSH PRIVILEGES; (最後一定要強迫更新權限)
建立資料庫 CREATE DATABASE 資料庫名;
語法:CREATE DATABASE db_name
使用資料庫 USE 資料庫名;
語法:USE db_name
刪除資料庫 DROP DATABASE 資料庫名;
語法:DROP DATABASE [IF EXISTS] db_name
建立資料表
CREATE TABLE 資料表名 (欄位1 資料型態, 欄位2 資料型態, ......);
語法:
CREATE TABLE [IF NOT EXISTS] tbl_name (create_definition,...) [table_options] [select_statement]
例:
craete database basic;
use basic;
create table basic(
no char(4)
name char(10)
id char(10));
create_definition:
col_name type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT]
[PRIMARY KEY] [reference_definition]
or PRIMARY KEY (index_col_name,...)
or KEY [index_name] KEY(index_col_name,...)
or INDEX [index_name] (index_col_name,...)
or UNIQUE [INDEX] [index_name] (index_col_name,...)
or [CONSTRAINT symbol] FOREIGN KEY index_name (index_col_name,...)
[reference_definition]
or CHECK (expr)
資料結構(type):
| 資料型態 | 說明 |
TINYINT | 有符號的範圍是-128到127, 無符號的範圍是0到255。 |
SMALLINT | 有符號的範圍是-32768到32767, 無符號的範圍是0到65535。 |
MEDIUMINT | 有符號的範圍是-8388608到8388607, 無符號的範圍是0到16777215。 |
INT | 有符號的範圍是-2147483648到2147483647, 無符號的範圍是0到4294967295。 |
INTEGER | INT的同義詞。 |
BIGINT | 有符號的範圍是-9223372036854775808到 9223372036854775807,無符號的範圍是0到18446744073709551615。 |
FLOAT | 單精密浮點數字。不能無符號。允許的值是-3.402823466E+38到- 1.175494351E-38,0 和1.175494351E-38到3.402823466E+38。 |
DOUBLE | 雙精密)浮點數字。不能無符號。允許的值是- 1.7976931348623157E+308到-2.2250738585072014E-308、 0和2.2250738585072014E-308到1.7976931348623157E+308。 |
DOUBLE PRECISION | DOUBLE的同義詞。 |
REAL | DOUBLE的同義詞。 |
DECIMAL | DECIMAL值的最大範圍與DOUBLE相 同。 |
NUMERIC | DECIMAL的同義詞。 |
DATE | 日期。支援的範圍是'1000-01-01'到'9999-12-31'。 |
DATETIME | 日期和時間組合。支援的範圍是'1000-01-01 00:00:00'到'9999-12-31 23:59:59' |
TIMESTAMP | 時間戳記。範圍是'1970-01-01 00:00:00'到2037年的某時。 |
TIME | 一個時間。範圍是'-838:59:59'到'838:59:59'。 |
YEAR | 2或4位數字格式的年(內定是4位)。允許的值是1901到2155。 |
CHAR | 固定長度,1 ~ 255個字元。 |
| VARCHAR | 可變長度,1 ~ 255個字元。 |
| |
TINYTEXT | 最大長度為255(2^8-1)個字符。 |
| |
MEDIUMTEXT | 最大長度為16777215(2^24-1)個字符。 |
| |
LONGTEXT | 最大長度為4294967295(2^32-1)個字符。 |
ENUM | 一個ENUM最多能有65535不同的值。 |
SET | 一個SET最多能有64個成員。 |
index_col_name:
col_name [(length)]
reference_definition:
REFERENCES tbl_name [(index_col_name,...)]
[MATCH FULL | MATCH PARTIAL]
[ON DELETE reference_option]
[ON UPDATE reference_option]
reference_option:
RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT
table_options:
type = [ISAM | MYISAM | HEAP]
or max_rows = #
or min_rows = #
or avg_row_length = #
or comment = "string"
or auto_increment = #
select_statement:
[ | IGNORE | REPLACE] SELECT ... (Some legal select statement)
刪除資料表 DROP TABLE 資料表名;
語法:DROP TABLE [IF EXISTS] tbl_name [, tbl_name,...]
改變資料表結構(新增/刪除欄位、建立/取消索引、改變欄位資料型態、欄位重新命 名)
語法:
ALTER [IGNORE] TABLE tbl_name alter_spec [, alter_spec ...]
alter_specification:
ADD [COLUMN] create_definition [FIRST | AFTER column_name ]
or ADD INDEX [index_name] (index_col_name,...)
or ADD PRIMARY KEY (index_col_name,...)
or ADD UNIQUE [index_name] (index_col_name,...)
or ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}
or CHANGE [COLUMN] old_col_name create_definition
or MODIFY [COLUMN] create_definition
or DROP [COLUMN] col_name
or DROP PRIMARY KEY
or DROP INDEX key_name
or RENAME [AS] new_tbl_name
or table_option
範例:
欄位重新命名
mysql> ALTER TABLE t1 CHANGE a b INTEGER;
將資料表 t1 欄位 a 改名為 b (其資料型態是 integer)
改變欄位資料型態
mysql> ALTER TABLE t1 CHANGE b b BIGINT NOT NULL;
mysql> ALTER TABLE t1 MODIFY b BIGINT NOT NULL;
將資料表 t1 欄位 b 的資料型態改為 bigint not null
mysql> CREATE TABLE t1 (a INTEGER,b CHAR(10));
mysql> ALTER TABLE t1 RENAME t2;
將資料表 t1 改名為 t2
mysql> ALTER TABLE t2 MODIFY a TINYINT NOT NULL, CHANGE b c CHAR(20);
將資料表 t2 欄位 a 資料型態由 integer 改為 tinyint not null ,欄位 b 改名為 c 資料型態改為 char(20)
mysql> ALTER TABLE t2 ADD d TIMESTAMP;
在資料表 t2 增加新欄位 d 資料型態是 timestamp
mysql> ALTER TABLE t2 ADD INDEX (d), ADD PRIMARY KEY (a);
在資料表 t2 ,對 d 欄位做索引,並以欄位 a 作為主索引鍵
mysql> ALTER TABLE t2 DROP COLUMN c;
刪除欄位 c
mysql> ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT, ADD INDEX (c);
新增欄位 c,並做索引(做索引的欄位必須為 not null )
資料表最佳化 OPTIMIZE TABLE 資料表名
語法:OPTIMIZE TABLE tbl_name
欄位長度有變動、刪除大量資料,都應進行資料表最佳化
三、紀錄的操作
插入一筆或多筆紀錄 INSERT INTO 資料表(欄位1,欄位2,......) VALUES(值1,值2,......), (值1,值2,......), ........
(MySQL 3.22.5 以後可插入多筆記錄)
語法:
INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
[INTO] tbl_name [(col_name,...)]
VALUES (expression,...),(...),...
or INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
[INTO] tbl_name [(col_name,...)]
SELECT ...
or INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
[INTO] tbl_name
SET col_name=expression, col_name=expression, ...
範例:
mysql> INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2);
不可寫成
mysql> INSERT INTO tbl_name (col1,col2) VALUES(col2*2,15);
因為:欄位 col1 的值先填入後,才可以計算欄位 col2
從檔案讀入資料
語法:
LOAD DATA [LOCAL] INFILE 'file_name.txt' [REPLACE | IGNORE]
INTO TABLE tbl_name
[FIELDS
[TERMINATED BY '\t'] 每一欄位以某字元分開(內定是 tab)
[OPTIONALLY] ENCLOSED BY "] 每一欄位以某字元括住(內定是不使用括號)
[ESCAPED BY '\\' ]]
[LINES TERMINATED BY '\n'] 設定換行的字元(內 定是 \n)
[IGNORE number LINES] 忽略最前面幾行(最前面幾筆記錄不抄進來)
[(col_name,...)]
範例:
mysql> USE db1;
mysql> LOAD DATA INFILE "./data.txt" INTO TABLE db2.my_table;
從目前 MySQL 目錄讀入 data.txt
mysql> LOAD DATA INFILE "./88.txt" INTO TABLE TEACHER FIELDS TERMINATED BY ' ' ;
從目前 MySQL 目錄(我的在 /var/lib/mysql )讀入 data.txt ,每一欄位以 空白 分開
mysql> LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata (col1,col2,...);
只將 persondata.txt 裡某些欄位的資料抓過來
刪除紀錄 DELETE [LOW-PRIORITY] FROM 資料表名 WHERE 條件 [LIMIT rows]
語法:
DELETE [LOW_PRIORITY] FROM tbl_name
[WHERE where_definition] [LIMIT rows]
LOW-PRIORITY 是等到沒有用戶端使用時再刪
LIMIT rows 限制刪除紀錄的筆數
範例:
mysql> DELETE FROM 資料表名;
刪除所有紀錄
mysql> DELETE FROM 資料表名 WHERE 1>0;
刪除所有紀錄,但速度較慢,方便在螢幕上看
更新一筆紀錄 (語法與 INSERT 相同)
REPLACE INTO 資料表(欄位1,欄位2,......) VALUES(值1,值2,......)
語法:
REPLACE [LOW_PRIORITY | DELAYED]
[INTO] tbl_name [(col_name,...)]
VALUES (expression,...)
or REPLACE [LOW_PRIORITY | DELAYED]
[INTO] tbl_name [(col_name,...)]
SELECT ...
or REPLACE [LOW_PRIORITY | DELAYED]
[INTO] tbl_name
SET col_name=expression, col_name=expression,...
更新多筆紀錄
語法:
UPDATE [LOW_PRIORITY] tbl_name SET col_name1=expr1,col_name2=expr2,... [WHERE where_definition]
如果沒有設定 WHERE 條件,則整個資料表相關的欄位都更新
範例:
mysql> UPDATE persondata SET age=age+1;
將資料表 persondata 中,所有 age 欄位都加 1
mysql> UPDATE persondata SET age=age*2, age=age+1;
將資料表 persondata 中,所有 age 欄位都*2,再加 1
四、資料的輸出
SELECT
語法:
SELECT [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [DISTINCT | ALL]
select_expression,...
[INTO OUTFILE 'file_name' export_options]
[FROM table_references
[WHERE where_definition]
[GROUP BY col_name,...]
[HAVING where_definition]
[ORDER BY {unsigned_integer | col_name} [ASC | DESC] ,...]
[LIMIT [offset,] rows]
[PROCEDURE procedure_name] ]
範例:
排序輸出
select * from 資料表名 order by 欄位名1,欄位名2,欄位名3......
反向排序輸出
select * from 資料表名 order by 欄位名1,欄位名2,欄位名3...... desc
mysql> select concat(last_name,', ',first_name) AS full_name
from mytable ORDER BY full_name;
mysql> select t1.name, t2.salary from employee AS t1, info AS t2
where t1.name = t2.name;
顯示資料庫 employee(別名 t1) 裡,資料表 t1 的欄位 name 和 資料表 t2 的欄位 salary 當.....
mysql> select t1.name, t2.salary from employee t1, info t2 where t1.name = t2.name;
mysql> select college, region, seed from tournament
ORDER BY region, seed;
mysql> select college, region AS r, seed AS s from tournament
ORDER BY r, s;
mysql> select college, region, seed from tournament
ORDER BY 2, 3;
mysql> select col_name from tbl_name HAVING col_name > 0;
mysql> select col_name from tbl_name WHERE col_name > 0;
mysql> select user,max(salary) from users
group by user HAVING max(salary)>10;
mysql> select user,max(salary) AS sum from users
group by user HAVING sum>10;
mysql> select * from table LIMIT 5,10; # Retrieve rows 6-15
mysql> select * from table LIMIT 5; # Retrieve first 5 rows
在命令列下進行批次處理:
shell> mysql -h host -u user -p < batch-file
Enter password: ********
| Type | Bytes | From | To |
TINYINT | 1 | -128 | 127 |
SMALLINT | 2 | -32768 | 32767 |
MEDIUMINT | 3 | -8388608 | 8388607 |
INT | 4 | -2147483648 | 2147483647 |
BIGINT | 8 | -9223372036854775808 | 9223372036854775807 |
| Column type | ``Zero'' value |
DATETIME | '0000-00-00 00:00:00' |
DATE | '0000-00-00' |
TIMESTAMP | 00000000000000 (length depends on display size) |
TIME | '00:00:00' |
YEAR | 0000 |
| Column type | Display format |
TIMESTAMP(14) | YYYYMMDDHHMMSS |
TIMESTAMP(12) | YYMMDDHHMMSS |
TIMESTAMP(10) | YYMMDDHHMM |
TIMESTAMP(8) | YYYYMMDD |
TIMESTAMP(6) | YYMMDD |
TIMESTAMP(4) | YYMM |
TIMESTAMP(2) | YY |
| Type | Max.size | Bytes |
TINYTEXT or TINYBLOB | 2^8-1 | 255 |
TEXT or BLOB | 2^16-1 (64K-1) | 65535 |
MEDIUMTEXT or MEDIUMBLOB | 2^24-1 (16M-1) | 16777215 |
LONGBLOB | 2^32-1 (4G-1) | 4294967295 |
| Value | CHAR(4) | Storage required | VARCHAR(4) | Storage required |
'' | ' ' | 4 bytes | '' | 1 byte |
'ab' | 'ab ' | 4 bytes | 'ab' | 3 bytes |
'abcd' | 'abcd' | 4 bytes | 'abcd' | 5 bytes |
'abcdefgh' | 'abcd' | 4 bytes | 'abcd' | 5 bytes |
| Value | Index |
NULL | NULL |
"" | 0 |
"one" | 1 |
"two" | 2 |
"three" | 3 |
| Other vendor type | MySQL type |
BINARY(NUM) | CHAR(NUM) BINARY |
CHAR VARYING(NUM) | VARCHAR(NUM) |
FLOAT4 | FLOAT |
FLOAT8 | DOUBLE |
INT1 | TINYINT |
INT2 | SMALLINT |
INT3 | MEDIUMINT |
INT4 | INT |
INT8 | BIGINT |
LONG VARBINARY | MEDIUMBLOB |
LONG VARCHAR | MEDIUMTEXT |
MIDDLEINT | MEDIUMINT |
VARBINARY(NUM) | VARCHAR(NUM) BINARY |
| Column type | Storage required |
TINYINT | 1 byte |
SMALLINT | 2 bytes |
MEDIUMINT | 3 bytes |
INT | 4 bytes |
INTEGER | 4 bytes |
BIGINT | 8 bytes |
FLOAT(X) | 4 if X <= 24 or 8 if 25 <= X <= 53 |
FLOAT | 4 bytes |
DOUBLE | 8 bytes |
DOUBLE PRECISION | 8 bytes |
REAL | 8 bytes |
DECIMAL(M,D) | M+2 bytes if D > 0, M+1 bytes if D = 0 (D+2, if M <>) |
NUMERIC(M,D) | M+2 bytes if D > 0, M+1 bytes if D = 0 (D+2, if M <>) |
| Column type | Storage required |
DATE | 3 bytes |
DATETIME | 8 bytes |
TIMESTAMP | 4 bytes |
TIME | 3 bytes |
YEAR | 1 byte |
| Column type | Storage required |
CHAR(M) | M bytes, 1 <= M <= 255 |
VARCHAR(M) | L+1 bytes, where L <= M and 1 <= M <= 255 |
TINYBLOB, TINYTEXT | L+1 bytes, where L <> |
BLOB, TEXT | L+2 bytes, where L <> |
MEDIUMBLOB, MEDIUMTEXT | L+3 bytes, where L <> |
LONGBLOB, LONGTEXT | L+4 bytes, where L <> |
ENUM('value1','value2',...) | 1 or 2 bytes, depending on the number of enumeration values (65535 values maximum) |
SET('value1','value2',...) | 1, 2, 3, 4 or 8 bytes, depending on the number of set members (64 members maximum) |
常用JDBC连接用字符串
descript:各种常用数据库的jar,用于Java数据库连接
1) SQLServer2000:驱动包(msbase.jar mssqlserver.jar msutil.jar)
url: jdbc:microsoft:sqlserver://localhost:1433;databasename=pubs
driver: com.microsoft.jdbc.sqlserver.SQLServerDriver
2) SQLServer2005:驱动包(sqljdbc.jar)
url: jdbc:sqlserver://localhost:1433;databasename=pubs
driver: com.microsoft.sqlserver.jdbc.SQLServerDriver
===============================================================================
3) JTDS -----SQLServer(支持SQL2000和SQL2005)
url: jdbc:jtds:sqlserver://localhost:1433/pubs
driver: net.sourceforge.jtds.jdbc.Driver
4) Oracle:驱动包(classes12.jar)
url: jdbc:oracle:thin:@0735jb:1521:aptech
(语法:jdbc:oracle:thin:@[ip]:[port]:[sid])
driver: oracle.jdbc.driver.OracleDriver
5) mysql:驱动包(mysql-connector-java-3.1.12-bin.jar)
url: jdbc:mysql: //127.0.0.1:3306/mysql
driver:org.gjt.mm.mysql.Driver
IE和Firefox在JavaScript方面的兼容性(汇编)
IE和Firefox在JavaScript方面的兼容性(汇编)
IE和Firefox在JavaScript方面的兼容性(汇编)
1.document.formName.item("itemName") 问题
说明:IE下,可以使用document.formName.item("itemName")或document.formName.elements["elementName"];Firefox下,只能使用document.formName.elements["elementName"].
解决方法:统一使用document.formName.elements["elementName"].
2.集合类对象问题
说明:IE下,可以使用()或[]获取集合类对象;Firefox下,只能使用[]获取集合类对象.
解决方法:统一使用[]获取集合类对象.
3.自定义属性问题
说明:IE下,可以使用获取常规属性的方法来获取自定义属性,也可以使用getAttribute()获取自定义属性;Firefox下,只能使用getAttribute()获取自定义属性.
解决方法:统一通过getAttribute()获取自定义属性.
4.eval("idName")问题
说明:IE下,,可以使用eval("idName")或getElementById("idName")来取得id为idName的HTML对象;Firefox下只能使用getElementById("idName")来取得id为idName的HTML对象.
解决方法:统一用getElementById("idName")来取得id为idName的HTML对象.
5.变量名与某HTML对象ID相同的问题
说明:IE下,HTML对象的ID可以作为document的下属对象变量名直接使用;Firefox下则不能.Firefox下,可以使用与HTML对象ID相同的变量名;IE下则不能。
解决方法:使用document.getElementById("idName")代替document.idName.最好不要取HTML对象ID相同的变量名,以减少错误;在声明变量时,一律加上var,以避免歧义.
6.const问题
说明:Firefox下,可以使用const关键字或var关键字来定义常量;IE下,只能使用var关键字来定义常量.
解决方法:统一使用var关键字来定义常量.
7.input.type属性问题
说明:IE下input.type属性为只读;但是Firefox下input.type属性为读写.
8.window.event问题
说明:window.event只能在IE下运行,而不能在Firefox下运行,这是因为Firefox的event只能在事件发生的现场使用.
解决方法:
IE:
...
IE&Firefox:
...
9.event.x与event.y问题
说明:IE下,even对象有x,y属性,但是没有pageX,pageY属性;Firefox下,even对象有pageX,pageY属性,但是没有x,y属性.
解决方法:使用mX(mX = event.x ? event.x : event.pageX;)来代替IE下的event.x或者Firefox下的event.pageX.
10.event.srcElement问题
说明:IE下,even对象有srcElement属性,但是没有target属性;Firefox下,even对象有target属性,但是没有srcElement属性.
解决方法:使用obj(obj = event.srcElement ? event.srcElement : event.target;)来代替IE下的event.srcElement或者Firefox下的event.target.
11.window.location.href问题
说明:IE或者Firefox2.0.x下,可以使用window.location或window.location.href;Firefox1.5.x下,只能使用window.location.
解决方法:使用window.location来代替window.location.href.
12.模态和非模态窗口问题
说明:IE下,可以通过showModalDialog和showModelessDialog打开模态和非模态窗口;Firefox下则不能.
解决方法:直接使用window.open(pageURL,name,parameters)方式打开新窗口。
如果需要将子窗口中的参数传递回父窗口,可以在子窗口中使用window.opener来访问父窗口. 例如:var parWin = window.opener; parWin.document.getElementById("Aqing").value = "Aqing";
13.frame问题
以下面的frame为例:
(1)访问frame对象:
IE:使用window.frameId或者window.frameName来访问这个frame对象.
Firefox:只能使用window.frameName来访问这个frame对象.
另外,在IE和Firefox中都可以使用window.document.getElementById("frameId")来访问这个frame对象.
(2)切换frame内容:
在IE和Firefox中都可以使用window.document.getElementById("testFrame").src = "xxx.html"或window.frameName.location = "xxx.html"来切换frame的内容.
如果需要将frame中的参数传回父窗口,可以在frme中使用parent来访问父窗口。例如:parent.document.form1.filename.value="Aqing";
14.body问题
Firefox的body在body标签没有被浏览器完全读入之前就存在;而IE的body则必须在body标签被浏览器完全读入之后才存在.
例如:
Firefox:
IE&Firefox:
15. 事件委托方法
IE:document.body.onload = inject; //Function inject()在这之前已被实现
Firefox:document.body.onload = inject();
有人说标准是:
document.body.onload=new Function('inject()');
16. firefox与IE(parentElement)的父元素的区别
IE:obj.parentElement
firefox:obj.parentNode
解决方法: 因为firefox与IE都支持DOM,因此使用obj.parentNode是不错选择.
17.cursor:hand VS cursor:pointer
firefox不支持hand,但ie支持pointer
解决方法: 统一使用pointer
18.innerText在IE中能正常工作,但是innerText在FireFox中却不行.
解决方法:
if(navigator.appName.indexOf("Explorer") > -1){
document.getElementById('element').innerText = "my text";
} else{
document.getElementById('element').textContent = "my text";
}
19. FireFox中类似 obj.style.height = imgObj.height 的语句无效
解决方法:
obj.style.height = imgObj.height + 'px';