随笔 - 42, 文章 - 1, 评论 - 0, 引用 - 0
数据加载中……

2011年12月28日

Jquery操作select

     摘要: 以下是操作 下拉列表的常用功能:1.获取列表项中候选项的数目。2.获得选中项的索引值。3.获得当前选中项的值4.设定选择值5.设定选择项 1 //得到select项的个数     2 jQuery.fn.size = function(){     ...  阅读全文

posted @ 2012-04-05 14:00 段旭 阅读(1140) | 评论 (0)编辑 收藏

Oracle全角変換

SELECT 

               UTL_I18N.TRANSLITERATE (TO_MULTI_BYTE(NAME), 'KANA_HIRAGANA') NAME--半角カタカナ・英数字-->全角ひらかな
             , UTL_I18N.TRANSLITERATE (TO_MULTI_BYTE(KANA), 'KANA_FWKATAKANA') KANA--半角カタカナ-->全角カタカナ
             , UTL_I18N.TRANSLITERATE (TO_MULTI_BYTE(SEIKINAME), 'KANA_HIRAGANA') SEIKINAME--半角カタカナ-->全角ひらかな
             , UTL_I18N.TRANSLITERATE (TO_MULTI_BYTE(SEIKIKANA), 'HIRAGANA_HWKATAKANA') SEIKIKANA --全角ひらかな・カタカナ-->半角タカ
             , UTL_I18N.TRANSLITERATE (TO_MULTI_BYTE(ZYUSHO), 'KANA_HIRAGANA') ZYUSHO--半角カタカナ-->全角ひらかな

posted @ 2012-03-27 18:52 段旭 阅读(634) | 评论 (0)编辑 收藏

mysql 取整函数

1.ceil () /ceiling() 向上取整

    ex: ceil(1.2) = 2

 2.floor () 向下取整

     ex: floor(1.2) = 1

 3.round() 四舍五入

posted @ 2012-03-07 16:32 段旭 阅读(2368) | 评论 (0)编辑 收藏

mysql 日期

这里是一个使用日期函数的例子。下面的查询选择了所有记录,其date_col的值是在最后30天以内:

mysql> SELECT something FROM table 
WHERE TO_DAYS(NOW()) - TO_DAYS(date_col) <= 30;

DAYOFWEEK(date) 
返回日期date的星期索引(1=星期天,2=星期一, ……7=星期六)。这些索引值对应于ODBC标准。 
mysql> select DAYOFWEEK('1998-02-03'); 
-> 3

WEEKDAY(date) 
返回date的星期索引(0=星期一,1=星期二, ……6= 星期天)。 
mysql> select WEEKDAY('1997-10-04 22:23:00'); 
-> 5 
mysql> select WEEKDAY('1997-11-05'); 
-> 2

DAYOFMONTH(date) 
返回date的月份中日期,在1到31范围内。 
mysql> select DAYOFMONTH('1998-02-03'); 
-> 3

DAYOFYEAR(date) 
返回date在一年中的日数, 在1到366范围内。 
mysql> select DAYOFYEAR('1998-02-03'); 
-> 34

MONTH(date) 
返回date的月份,范围1到12。 
mysql> select MONTH('1998-02-03'); 
-> 2

DAYNAME(date) 
返回date的星期名字。 
mysql> select DAYNAME("1998-02-05"); 
-> 'Thursday'

MONTHNAME(date) 
返回date的月份名字。 
mysql> select MONTHNAME("1998-02-05"); 
-> 'February'

QUARTER(date) 
返回date一年中的季度,范围1到4。 
mysql> select QUARTER('98-04-01'); 
-> 2

WEEK(date)

WEEK(date,first) 
对于星期天是一周的第一天的地方,有一个单个参数,返回date的周数,范围在0到52。2个参数形式WEEK()允许 
你指定星期是否开始于星期天或星期一。如果第二个参数是0,星期从星期天开始,如果第二个参数是1, 
从星期一开始。 
mysql> select WEEK('1998-02-20'); 
-> 7 
mysql> select WEEK('1998-02-20',0); 
-> 7 
mysql> select WEEK('1998-02-20',1); 
-> 8

YEAR(date) 
返回date的年份,范围在1000到9999。 
mysql> select YEAR('98-02-03'); 
-> 1998

HOUR(time) 
返回time的小时,范围是0到23。 
mysql> select HOUR('10:05:03'); 
-> 10

MINUTE(time) 
返回time的分钟,范围是0到59。 
mysql> select MINUTE('98-02-03 10:05:03'); 
-> 5

SECOND(time) 
回来time的秒数,范围是0到59。 
mysql> select SECOND('10:05:03'); 
-> 3

PERIOD_ADD(P,N) 
增加N个月到阶段P(以格式YYMM或YYYYMM)。以格式YYYYMM返回值。注意阶段参数P不是日期值。 
mysql> select PERIOD_ADD(9801,2); 
-> 199803

PERIOD_DIFF(P1,P2) 
返回在时期P1和P2之间月数,P1和P2应该以格式YYMM或YYYYMM。注意,时期参数P1和P2不是日期值。 
mysql> select PERIOD_DIFF(9802,199703); 
-> 11

DATE_ADD(date,INTERVAL expr type)

DATE_SUB(date,INTERVAL expr type)

ADDDATE(date,INTERVAL expr type)

SUBDATE(date,INTERVAL expr type) 
这些功能执行日期运算。对于MySQL 3.22,他们是新的。ADDDATE()和SUBDATE()是DATE_ADD()和DATE_SUB()的同义词。 
在MySQL 3.23中,你可以使用+和-而不是DATE_ADD()和DATE_SUB()。(见例子)date是一个指定开始日期的 
DATETIME或DATE值,expr是指定加到开始日期或从开始日期减去的间隔值一个表达式,expr是一个字符串;它可以以 
一个“-”开始表示负间隔。type是一个关键词,指明表达式应该如何被解释。EXTRACT(type FROM date)函数从日期 
中返回“type”间隔。下表显示了type和expr参数怎样被关联: type值 含义 期望的expr格式 
SECOND 秒 SECONDS 
MINUTE 分钟 MINUTES 
HOUR 时间 HOURS 
DAY 天 DAYS 
MONTH 月 MONTHS 
YEAR 年 YEARS 
MINUTE_SECOND 分钟和秒 "MINUTES:SECONDS" 
HOUR_MINUTE 小时和分钟 "HOURS:MINUTES" 
DAY_HOUR 天和小时 "DAYS HOURS" 
YEAR_MONTH 年和月 "YEARS-MONTHS" 
HOUR_SECOND 小时, 分钟, "HOURS:MINUTES:SECONDS" 
DAY_MINUTE 天, 小时, 分钟 "DAYS HOURS:MINUTES" 
DAY_SECOND 天, 小时, 分钟, 秒 "DAYS HOURS:MINUTES:SECONDS"

MySQL在expr格式中允许任何标点分隔符。表示显示的是建议的分隔符。如果date参数是一个DATE值并且你的计算仅仅 
包含YEAR、MONTH和DAY部分(即,没有时间部分),结果是一个DATE值。否则结果是一个DATETIME值。

mysql> SELECT "1997-12-31 23:59:59" + INTERVAL 1 SECOND; 
-> 1998-01-01 00:00:00 
mysql> SELECT INTERVAL 1 DAY + "1997-12-31"; 
-> 1998-01-01 
mysql> SELECT "1998-01-01" - INTERVAL 1 SECOND; 
-> 1997-12-31 23:59:59 
mysql> SELECT DATE_ADD("1997-12-31 23:59:59", 
INTERVAL 1 SECOND); 
-> 1998-01-01 00:00:00 
mysql> SELECT DATE_ADD("1997-12-31 23:59:59", 
INTERVAL 1 DAY); 
-> 1998-01-01 23:59:59 
mysql> SELECT DATE_ADD("1997-12-31 23:59:59", 
INTERVAL "1:1" MINUTE_SECOND); 
-> 1998-01-01 00:01:00 
mysql> SELECT DATE_SUB("1998-01-01 00:00:00", 
INTERVAL "1 1:1:1" DAY_SECOND); 
-> 1997-12-30 22:58:59 
mysql> SELECT DATE_ADD("1998-01-01 00:00:00", 
INTERVAL "-1 10" DAY_HOUR); 
-> 1997-12-30 14:00:00 
mysql> SELECT DATE_SUB("1998-01-02", INTERVAL 31 DAY); 
-> 1997-12-02 
mysql> SELECT EXTRACT(YEAR FROM "1999-07-02"); 
-> 1999 
mysql> SELECT EXTRACT(YEAR_MONTH FROM "1999-07-02 01:02:03"); 
-> 199907 
mysql> SELECT EXTRACT(DAY_MINUTE FROM "1999-07-02 01:02:03"); 
-> 20102

如果你指定太短的间隔值(不包括type关键词期望的间隔部分),MySQL假设你省掉了间隔值的最左面部分。例如, 
如果你指定一个type是DAY_SECOND,值expr被希望有天、小时、分钟和秒部分。如果你象"1:10"这样指定值, 
MySQL假设日子和小时部分是丢失的并且值代表分钟和秒。换句话说,"1:10" DAY_SECOND以它等价于"1:10" MINUTE_SECOND 
的方式解释,这对那MySQL解释TIME值表示经过的时间而非作为一天的时间的方式有二义性。如果你使用确实不正确的日期, 
结果是NULL。如果你增加MONTH、YEAR_MONTH或YEAR并且结果日期大于新月份的最大值天数,日子在新月用最大的天调整。

mysql> select DATE_ADD('1998-01-30', Interval 1 month); 
-> 1998-02-28

注意,从前面的例子中词INTERVAL和type关键词不是区分大小写的。 
TO_DAYS(date) 
给出一个日期date,返回一个天数(从0年的天数)。 
mysql> select TO_DAYS(950501); 
-> 728779 
mysql> select TO_DAYS('1997-10-07'); 
-> 729669

TO_DAYS()不打算用于使用格列高里历(1582)出现前的值。

FROM_DAYS(N) 
给出一个天数N,返回一个DATE值。 
mysql> select FROM_DAYS(729669); 
-> '1997-10-07'

TO_DAYS()不打算用于使用格列高里历(1582)出现前的值。

DATE_FORMAT(date,format) 
根据format字符串格式化date值。下列修饰符可以被用在format字符串中: %M 月名字(January……December) 
%W 星期名字(Sunday……Saturday) 
%D 有英语前缀的月份的日期(1st, 2nd, 3rd, 等等。) 
%Y 年, 数字, 4 位 
%y 年, 数字, 2 位 
%a 缩写的星期名字(Sun……Sat) 
%d 月份中的天数, 数字(00……31) 
%e 月份中的天数, 数字(0……31) 
%m 月, 数字(01……12) 
%c 月, 数字(1……12) 
%b 缩写的月份名字(Jan……Dec) 
%j 一年中的天数(001……366) 
%H 小时(00……23) 
%k 小时(0……23) 
%h 小时(01……12) 
%I 小时(01……12) 
%l 小时(1……12) 
%i 分钟, 数字(00……59) 
%r 时间,12 小时(hh:mm:ss [AP]M) 
%T 时间,24 小时(hh:mm:ss) 
%S 秒(00……59) 
%s 秒(00……59) 
%p AM或PM 
%w 一个星期中的天数(0=Sunday ……6=Saturday ) 
%U 星期(0……52), 这里星期天是星期的第一天 
%u 星期(0……52), 这里星期一是星期的第一天 
%% 一个文字“%”。

所有的其他字符不做解释被复制到结果中。

mysql> select DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y'); 
-> 'Saturday October 1997' 
mysql> select DATE_FORMAT('1997-10-04 22:23:00', '%H:%i:%s'); 
-> '22:23:00' 
mysql> select DATE_FORMAT('1997-10-04 22:23:00', 
'%D %y %a %d %m %b %j'); 
-> '4th 97 Sat 04 10 Oct 277' 
mysql> select DATE_FORMAT('1997-10-04 22:23:00', 
'%H %k %I %r %T %S %w'); 
-> '22 22 10 10:23:00 PM 22:23:00 00 6' 
MySQL3.23中,在格式修饰符字符前需要%。在MySQL更早的版本中,%是可选的。

TIME_FORMAT(time,format) 
这象上面的DATE_FORMAT()函数一样使用,但是format字符串只能包含处理小时、分钟和秒的那些格式修饰符。 
其他修饰符产生一个NULL值或0。 
CURDATE()

CURRENT_DATE 
以'YYYY-MM-DD'或YYYYMMDD格式返回今天日期值,取决于函数是在一个字符串还是数字上下文被使用。 
mysql> select CURDATE(); 
-> '1997-12-15' 
mysql> select CURDATE() + 0; 
-> 19971215

CURTIME()

CURRENT_TIME 
以'HH:MM:SS'或HHMMSS格式返回当前时间值,取决于函数是在一个字符串还是在数字的上下文被使用。 
mysql> select CURTIME(); 
-> '23:50:26' 
mysql> select CURTIME() + 0; 
-> 235026

NOW()

SYSDATE()

CURRENT_TIMESTAMP 
以'YYYY-MM-DD HH:MM:SS'或YYYYMMDDHHMMSS格式返回当前的日期和时间,取决于函数是在一个字符串还是在数字的 
上下文被使用。 
mysql> select NOW(); 
-> '1997-12-15 23:50:26' 
mysql> select NOW() + 0; 
-> 19971215235026

UNIX_TIMESTAMP()

UNIX_TIMESTAMP(date) 
如果没有参数调用,返回一个Unix时间戳记(从'1970-01-01 00:00:00'GMT开始的秒数)。如果UNIX_TIMESTAMP()用一 
个date参数被调用,它返回从'1970-01-01 00:00:00' GMT开始的秒数值。date可以是一个DATE字符串、一个DATETIME 
字符串、一个TIMESTAMP或以YYMMDD或YYYYMMDD格式的本地时间的一个数字。 
mysql> select UNIX_TIMESTAMP(); 
-> 882226357 
mysql> select UNIX_TIMESTAMP('1997-10-04 22:23:00'); 
-> 875996580

当UNIX_TIMESTAMP被用于一个TIMESTAMP列,函数将直接接受值,没有隐含的“string-to-unix-timestamp”变换。

FROM_UNIXTIME(unix_timestamp) 
以'YYYY-MM-DD HH:MM:SS'或YYYYMMDDHHMMSS格式返回unix_timestamp参数所表示的值,取决于函数是在一个字符串 
还是或数字上下文中被使用。 
mysql> select FROM_UNIXTIME(875996580); 
-> '1997-10-04 22:23:00' 
mysql> select FROM_UNIXTIME(875996580) + 0; 
-> 19971004222300

FROM_UNIXTIME(unix_timestamp,format) 
返回表示 Unix 时间标记的一个字符串,根据format字符串格式化。format可以包含与DATE_FORMAT()函数列出的条 
目同样的修饰符。 
mysql> select FROM_UNIXTIME(UNIX_TIMESTAMP(), 
'%Y %D %M %h:%i:%s %x'); 
-> '1997 23rd December 03:43:30 x'

SEC_TO_TIME(seconds) 
返回seconds参数,变换成小时、分钟和秒,值以'HH:MM:SS'或HHMMSS格式化,取决于函数是在一个字符串还是在数字 
上下文中被使用。 
mysql> select SEC_TO_TIME(2378); 
-> '00:39:38' 
mysql> select SEC_TO_TIME(2378) + 0; 
-> 3938

TIME_TO_SEC(time) 
返回time参数,转换成秒。 
mysql> select TIME_TO_SEC('22:23:00'); 
-> 80580 
mysql> select TIME_TO_SEC('00:39:38'); 
-> 2378
DATE_FORMAT(date,format) 
根据format字符串格式化date值。下列修饰符可以被用在format字符串中: %M 月名字(January……December) 
%W 星期名字(Sunday……Saturday) 
%D 有英语前缀的月份的日期(1st, 2nd, 3rd, 等等。) 
%Y 年, 数字, 4 位 
%y 年, 数字, 2 位 
%a 缩写的星期名字(Sun……Sat) 
%d 月份中的天数, 数字(00……31) 
%e 月份中的天数, 数字(0……31) 
%m 月, 数字(01……12) 
%c 月, 数字(1……12) 
%b 缩写的月份名字(Jan……Dec) 
%j 一年中的天数(001……366) 
%H 小时(00……23) 
%k 小时(0……23) 
%h 小时(01……12) 
%I 小时(01……12) 
%l 小时(1……12) 
%i 分钟, 数字(00……59) 
%r 时间,12 小时(hh:mm:ss [AP]M) 
%T 时间,24 小时(hh:mm:ss) 
%S 秒(00……59) 
%s 秒(00……59) 
%p AM或PM 
%w 一个星期中的天数(0=Sunday ……6=Saturday ) 
%U 星期(0……52), 这里星期天是星期的第一天 
%u 星期(0……52), 这里星期一是星期的第一天 
%% 一个文字“%”。 所有的其他字符不做解释被复制到结果中。

mysql> select DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y'); 
-> 'Saturday October 1997' 
mysql> select DATE_FORMAT('1997-10-04 22:23:00', '%H:%i:%s'); 
-> '22:23:00' 
mysql> select DATE_FORMAT('1997-10-04 22:23:00', 
'%D %y %a %d %m %b %j'); 
-> '4th 97 Sat 04 10 Oct 277' 
mysql> select DATE_FORMAT('1997-10-04 22:23:00', 
'%H %k %I %r %T %S %w'); 
-> '22 22 10 10:23:00 PM 22:23:00 00 6' 
MySQL3.23中,在格式修饰符字符前需要%。在MySQL更早的版本中,%是可选的。

TIME_FORMAT(time,format) 
这象上面的DATE_FORMAT()函数一样使用,但是format字符串只能包含处理小时、分钟和秒的那些格式修饰符。

其他修饰符产生一个NULL值或0。 
CURDATE()

CURRENT_DATE 
以'YYYY-MM-DD'或YYYYMMDD格式返回今天日期值,取决于函数是在一个字符串还是数字上下文被使用。 
mysql> select CURDATE(); 
-> '1997-12-15' 
mysql> select CURDATE() + 0; 
-> 19971215

CURTIME()

CURRENT_TIME 
以'HH:MM:SS'或HHMMSS格式返回当前时间值,取决于函数是在一个字符串还是在数字的上下文被使用。 
mysql> select CURTIME(); 
-> '23:50:26' 
mysql> select CURTIME() + 0; 
-> 235026

NOW()

SYSDATE()

CURRENT_TIMESTAMP 
以'YYYY-MM-DD HH:MM:SS'或YYYYMMDDHHMMSS格式返回当前的日期和时间,取决于函数是在一个字符串还是在数字的 
上下文被使用。 
mysql> select NOW(); 
-> '1997-12-15 23:50:26' 
mysql> select NOW() + 0; 
-> 19971215235026

UNIX_TIMESTAMP()

UNIX_TIMESTAMP(date) 
如果没有参数调用,返回一个Unix时间戳记(从'1970-01-01 00:00:00'GMT开始的秒数)。如果UNIX_TIMESTAMP()用一个date参数被调用,它返回从'1970-01-01 00:00:00' GMT开始的秒数值。date可以是一个DATE字符串、一个DATETIME字符串、一个TIMESTAMP或以YYMMDD或YYYYMMDD格式的 本地时间的一个数字。 
mysql> select UNIX_TIMESTAMP(); 
-> 882226357 
mysql> select UNIX_TIMESTAMP('1997-10-04 22:23:00'); 
-> 875996580

当UNIX_TIMESTAMP被用于一个TIMESTAMP列,函数将直接接受值,没有隐含的“string-to-unix-timestamp”变换 www.knowsky.com

FROM_UNIXTIME(unix_timestamp) 
以'YYYY-MM-DD HH:MM:SS'或YYYYMMDDHHMMSS格式返回unix_timestamp参数所表示的值,取决于函数是在一个字符串还是或数字上下文中被使用。 
mysql> select FROM_UNIXTIME(875996580); 
-> '1997-10-04 22:23:00' 
mysql> select FROM_UNIXTIME(875996580) + 0; 
-> 19971004222300

FROM_UNIXTIME(unix_timestamp,format) 
返回表示 Unix 时间标记的一个字符串,根据format字符串格式化。format可以包含与DATE_FORMAT()函数列出的条目同样的修饰符。 
mysql> select FROM_UNIXTIME(UNIX_TIMESTAMP(), 
'%Y %D %M %h:%i:%s %x'); 
-> '1997 23rd December 03:43:30 x'

SEC_TO_TIME(seconds) 
返回seconds参数,变换成小时、分钟和秒,值以'HH:MM:SS'或HHMMSS格式化,取决于函数是在一个字符串还是在数字上下文中被使用。 
mysql> select SEC_TO_TIME(2378); 
-> '00:39:38' 
mysql> select SEC_TO_TIME(2378) + 0; 
-> 3938

TIME_TO_SEC(time) 
返回time参数,转换成秒。 
mysql> select TIME_TO_SEC('22:23:00'); 
-> 80580 
mysql> select TIME_TO_SEC('00:39:38'); 
-> 2378

posted @ 2012-03-07 16:31 段旭 阅读(256) | 评论 (0)编辑 收藏

构建jQuery对象

(function( window, undefined ) {

   

    var jQuery = (function() {

       // 构建jQuery对象

       var jQuery = function( selector, context ) {

           return new jQuery.fn.init( selector, context, rootjQuery );

       }

   

       // jQuery对象原型

       jQuery.fn = jQuery.prototype = {

           constructor: jQuery,

           init: function( selector, context, rootjQuery ) {

              // selector有以下7种分支情况:

              // DOM元素

              // body(优化)

              // 字符串:HTML标签、HTML字符串、#id、选择器表达式

              // 函数(作为ready回调函数)

              // 最后返回伪数组

           }

       };

   

       // Give the init function the jQuery prototype for later instantiation

       jQuery.fn.init.prototype = jQuery.fn;

   

       // 合并内容到第一个参数中,后续大部分功能都通过该函数扩展

       // 通过jQuery.fn.extend扩展的函数,大部分都会调用通过jQuery.extend扩展的同名函数

       jQuery.extend = jQuery.fn.extend = function() {};

      

       // jQuery上扩展静态方法

       jQuery.extend({

           // ready bindReady

           // isPlainObject isEmptyObject

           // parseJSON parseXML

           // globalEval

           // each makeArray inArray merge grep map

           // proxy

           // access

           // uaMatch

           // sub

           // browser

       });

 

        // 到这里,jQuery对象构造完成,后边的代码都是对jQueryjQuery对象的扩展

       return jQuery;

   

    })();

   

    window.jQuery = window.$ = jQuery;

})(window);

posted @ 2012-02-22 13:10 段旭 阅读(770) | 评论 (0)编辑 收藏

常用正则式

常用的数字正则(严格匹配)
正则 含义
^[1-9]\d*$ 匹配正整数
^-[1-9]\d*$ 匹配负整数
^-?[1-9]\d*$ 匹配整数
^[1-9]\d*|0$ 匹配非负整数(正整数 + 0)
^-[1-9]\d*|0$ 匹配非正整数(负整数 + 0)
^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 匹配正浮点数
^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 匹配负浮点数
^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$ 匹配浮点数
^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$ 匹配非负浮点数(正浮点数 + 0)
^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$ 匹配非正浮点数(负浮点数 + 0)

常用字符串正则
正则 含义 补充
^[A-Za-z]+$ 匹配由26个英文字母组成的字符串 或 /^[a-z]+$/i
^[A-Z]+$ 匹配由26个英文字母的大写组成的字符串
^[a-z]+$ 匹配由26个英文字母的小写组成的字符串
^[A-Za-z0-9]+$ 匹配由数字和26个英文字母组成的字符串 注意\w包含下划线_
^\w+$ 匹配由数字、26个英文字母或者下划线组成的字符串

匹配中文字符
普遍使用的正则是[\u4e00-\u9fa5],但这个范围并不完整。例如:
/[\u4e00-\u9fa5]/.test( '⻏' ) // 测试部首⻏,返回false
根据Unicode 5.0版编码,要准确的判断一个中文字符要包括:
范围 含义 范围 含义
2E80-2EFF CJK 部首补充 2F00-2FDF 康熙字典部首
3000-303F CJK 符号和标点 31C0-31EF CJK 笔画
3200-32FF 封闭式 CJK 文字和月份 3300-33FF CJK 兼容
3400-4DBF CJK 统一表意符号扩展 A 4DC0-4DFF 易经六十四卦符号
4E00-9FBF CJK 统一表意符号 F900-FAFF CJK 兼容象形文字
FE30-FE4F CJK 兼容形式 FF00-FFEF 全角ASCII、全角标点
因此,正确的匹配中文字符正则表达式为:
var rcjk = /[\u2E80-\u2EFF\u2F00-\u2FDF\u3000-\u303F\u31C0-\u31EF\u3200-\u32FF\u3300-\u33FF\u3400-\u4DBF\u4DC0-\u4DFF\u4E00-\u9FBF\uF900-\uFAFF\uFE30-\uFE4F\uFF00-\uFFEF]+/g;
如果不希望匹配标点、符号,在正则中去掉对应的范围即可:
3000-303F CJK 符号和标点 FF00-FFEF 全角ASCII、全角标点

匹配双字节字符(包括汉字在内)
[^\x00-\xff],可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1),代码示例如下:
console.info( "abc".replace( /[^\x00-\xff]/g,"aa" ).length ) // 3
console.info( "汉字".replace( /[^\x00-\xff]/g,"aa" ).length ) // 4
console.info( "abc汉字".replace( /[^\x00-\xff]/g,"aa").length ) // 7

posted @ 2012-02-22 10:57 段旭 阅读(265) | 评论 (0)编辑 收藏

JQuery总体架构

(function( window, undefined ) {
// 构造jQuery对象
var jQuery = function( selector, context ) {
return new jQuery.fn.init( selector, context, rootjQuery );
}
// 工具函数 Utilities
// 异步队列 Deferred
// 浏览器测试 Support
// 数据缓存 Data
// 队列 queue
// 属性操作 Attribute
// 事件处理 Event
// 选择器 Sizzle
// DOM遍历
// DOM操作
// CSS操作
// 异步请求 Ajax
// 动画 FX
// 坐标和大小
window.jQuery = window.$ = jQuery;
})(window);
从上边的注释看,jQuery的源码结构相当清晰、条理,不像代码那般晦涩和让人纠结。

posted @ 2012-02-22 10:43 段旭 阅读(224) | 评论 (0)编辑 收藏

自调用匿名函数 self-invoking anonymous function

(function( window, undefined ) {

    // jquery code

})(window);

1.这是一个自调用匿名函数。什么东东呢?在第一个括号内,创建一个匿名函数;第二个括号,立即执行

2.为什么要创建这样一个“自调用匿名函数”呢?

通过定义一个匿名函数,创建了一个“私有”的命名空间,该命名空间的变量和方法,不会破坏全局的命名空间。这点非常有用也是一个JS框架必须支持的功能,jQuery被应用在成千上万的JavaScript程序中,必须确保jQuery创建的变量不能和导入他的程序所使用的变量发生冲突。

3.匿名函数从语法上叫函数直接量,JavaScript语法需要包围匿名函数的括号,事实上自调用匿名函数有两种写法(注意标红了的右括号):

(function() {

    console.info( this );

    console.info( arguments );

 }( window ) 
);

(function() {

    console.info( this );

    console.info( arguments );

 }
)( window );

4.为什么要传入window呢?

通过传入window变量,使得window由全局变量变为局部变量,当在jQuery代码块中访问window时,不需要将作用域链回退到顶层作用域,这样可以更快的访问window;这还不是关键所在,更重要的是,将window作为参数传入,可以在压缩代码时进行优化,看看jquery-1.6.1.min.js:

 

(function(a,b){})(window); // window 被优化为 a   

5.为什么要在在参数列表中增加undefined呢?

在 自调用匿名函数 的作用域内,确保undefined是真的未定义。因为undefined能够被重写,赋予新的值。

  undefined = "now it's defined";

  alert( undefined );

浏览器测试结果:

浏览器

测试结果

 结论

ie

    now it's defined    

  可以改变

firefox

undefined

  不能改变

chrome

now it's defined

  可以改变

opera

now it's defined

  可以改变


 6. 注意到源码最后的分号了吗?

分号是可选的,但省略分号并不是一个好的编程习惯;为了更好的兼容性和健壮性,请在每行代码后加上分号并养成习惯。

 

 

posted @ 2012-02-22 10:41 段旭 阅读(1133) | 评论 (0)编辑 收藏

jquery设置元素的readonly和disabled

Jquery的api中提供了对元素应用disabled和readonly属性的方法,在这里记录下。如下:
 1.readonly
    $('input').attr("readonly","readonly")//将input元素设置为readonly
    $('input').removeAttr("readonly");//去除input元素的readonly属性
  
    if($('input').attr("readonly")==true)//判断input元素是否已经设置了readonly属性

 

    对于为元素设置readonly属性和取消readonly属性的方法还有如下两种:
    $('input').attr("readonly",true)//将input元素设置为readonly
    $('input').attr("readonly",false)//去除input元素的readonly属性

 

    $('input').attr("readonly","readonly")//将input元素设置为readonly
    $('input').attr("readonly","")//去除input元素的readonly属性
 2.disabled
 

    $('input').attr("disabled","disabled")//将input元素设置为disabled
    $('input').removeAttr("disabled");//去除input元素的disabled属性
  
    if($('input').attr("disabled")==true)//判断input元素是否已经设置了disabled属性

  

  对于为元素设置disabled属性和取消disabled属性的方法还有如下两种:
    $('input').attr("disabled",true)//将input元素设置为disabled
    $('input').attr("disabled",false)//去除input元素的disabled属性

 

    $('input').attr("disabled","disabled")//将input元素设置为disabled
    $('input').attr("disabled","")//去除input元素的disabled属性

posted @ 2012-02-21 15:29 段旭 阅读(253) | 评论 (0)编辑 收藏

网友整理三亚防宰攻略手册

  针对微博热议的“三亚旅游被宰”经历,新浪旅游根据网友留言及评论整理了一份三亚拒绝挨宰攻略。

  跟团游

  团队旅行中,最大块的挨宰费主要是购物店、烧香;小的费用主要是看人妖、潜水、互动节目。总之最后你的花销很可能超出团费。

  有些人在当地报名参加“一日游”等,常见的被宰方式是从这家旅行社被“卖”到另一家旅行社,可能还要忍受非常恶劣的服务态度。

  防宰攻略:

  1.选择正规、规模大的旅行社。

  2.在签订合同的时候,细节一定要问清楚,有些东西需要额外注明在合同中,以确保自身的利益能够得到保障。

  3.在切身利益受到侵害的时候,立刻拨打相关投诉电话,必要时报警。

  自助游

  【吃海鲜】

  要么缺斤短两,要么就是被天价的海鲜所“打败”,少则几百,多则几千,普通游客难以承受。

  防宰攻略:

  1.如果有导游、出租车司机、摩托车夫、三轮车夫向你极力推荐某某海鲜店,要多留个心眼,或许到了那里你就身不由己了……不要听信路边发广告、发名片的游说。

  2.吃海鲜可以考虑海鲜市场。可以买海鲜直接加工,成本相对低廉,方便且便宜。

  3.远离黑心海鲜店。

  黑心海鲜店一般分布在高端酒店旁或者离市区较远的地方,骗人的方法有的极其夸张。

  A.当你指向一个东西、问价格的时候,小二顺势拿出就在你眼前拍死,你还没回过神这个东西已经需要你来买单了!

  B.你问价格的时候,老板热情地告诉你不贵啦才4元每斤啦,但等你结账的时候可能是40元每斤或者400元每斤。

  C.严重缺斤短两。

  【买水果】

  在三亚买美味的热带水果,也要格外注意。

  1.自带小秤。

  缺斤短两是小商贩们最惯用的伎俩,而我们也应该同样细心一些,称一称所购买的物品到底多重(先谈价钱再亮秤)。

  2.去正规的水果市场,店铺多,市场管理相对完善。

  3.如果当地有熟人,可以让他带你去买。

  【景点游玩】

  1.网上提前订门票。一般网络订票能更优惠,建议提前购票。

  2.不必每个景点都去,去一些重点和有代表性的景点便可。

  3.充分利用公交车、旅游专线巴士、机场巴士等公共资源。

  4.包车线路一定要自己设计,否则容易被宰。

  5.慎买珍珠、水晶等。

  6.三轮车和两轮摩的,建议不要乘坐,危险并且很容易被“宰”。

  7.住小酒店,建议不要让服务员帮你叫车,说不定会叫来跟他们有利益链条的相关车辆。

  8.无招胜有招。在亚龙湾、海棠湾的酒店尽情享受阳光,尽量避免外出。

posted @ 2012-01-30 17:12 段旭 阅读(218) | 评论 (0)编辑 收藏

[IBM]构建轻量级 Batch 框架处理 DB2 Content Manager 8.3 大量数据导入

【来源】http://www.ibm.com/developerworks/cn/data/library/techarticles/dm-0908luyx/

本文介绍了如何使用多线程来构建轻量级 Batch 框架,将大量的数据迁移到 IBM DB2 Content Manager 8.3 中。通过本文的学习,读者可以了解如何通过使用多线程调用 IBM DB2 Content Manager API 构建的框架来启动,暂停,恢复,停止,放缓等操作。

在用 API 导入大量数据的过程中,如果没有框架很难有效的对整个过程控制,仅仅通过日志来分析解决问题总是很浪费时间,并且效率不太理想。

本文的内容放在了如何使用多线程和配置文件来构建 Batch 框架来处理大数量导入的问题。

随着 IBM DB2 Content Manager(简称 IBM CM)产品的不断成熟,越来越多的内容管理系统需要迁移到 IBM CM 中来,这些需要迁移的数据通常首先把结构化的内容导到文本文件中,与之相对应的图像和 pdf 文件通常放在对应的文件夹中,图像和 pdf 对应的文件夹路径也通常存放在文本文件中,然后迁移程序遍历文本文件,把对应的 Item 迁移到 IBM CM 中。这些需要迁移的数据通常都有几百 G,如何有效的控制迁移过程是一个很大的挑战,因此我们必须构建一个轻量级的 batch 处理框架来控制整个数据的迁移周期,记录处理过程中的错误,保证数据的一致性。

同时,在用 API 导入数据的过程中,被导入数据总是千边万化,无效的映射导入数据和 DB2 Content Manager 的项,导致工作变得复杂,同时使的设计和代码冗余,并且使重用,维护和扩展履步为艰难。

为了克服所提到的挑战,这个 batch 框架必须要有以下功能:

  • 用户出于不影响生产环境性能的考虑,可以暂时停止数据的迁移,或者减缓迁移处理的频率,即框架必须具有 suspend 和 slowdown 功能。
  • 用户可以让暂停处理的系统继续处理,即框架必须具有 resume 功能。
  • 用户可以让系统停止处理,修改某些配置,然后继续处理,即框架必须有 re-start 功能。
  • 处理过程中发生的错误,警告系统必须记录下来,用户可以根据这些记录来修正数据。
  • 通过配置文件建立规则来解决数据千边万化的问题。

构建框架

构建交互性

要使框架有交互性,我们必须有三个个线程:客户端线程,服务端线程,工作线程。客户端线程负责发出工作指令,服务端线程接受这些指令并调用工作线程来做实际的工作。对于客户端和服务器交互,在没有 web 服务器支持的情况下,我们可以采用一种古老但是很有效的做法:socket 编程。 Java socket 对象的 accept 方法会一直阻塞直到客户端有程序输入,当客户端有新的命令输入的时候,服务器端从 socket 中读出命令,然后执行命令。下面是示例程序,Client.java 代表客户端程序,Server.java 代表服务器端程序,Worker.java 代表工作程序 ,Config.java 代表系统中一些参数配置。


清单 1. 客户端程序
package com.ibm.batch.sample;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import org.apache.log4j.Logger;

public class Client {
	private Config config = null;
	public void setConfig(Config config) {
		this.config = config;
	}
	private Logger logger = Logger.getLogger(Client.class);
	public void sendCommand(String command) {
		Socket socket = null;
		OutputStream out = null;
		BufferedWriter writer = null;
		try {
			// establish the connection with server.
			socket = new Socket(config.getHost(), config.getSocketPort());
			out = socket.getOutputStream();
			writer = new BufferedWriter(new OutputStreamWriter(out));
			// send the command to server
			writer.write(command);
			writer.flush();
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
			throw new RuntimeException(e);
		}
	}
}


清单 2. 服务器端程序
package com.ibm.batch.sample;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import com.ibm.batch.sample.util.ResourceUtils;

public class Server {
	private Config config = null;
	private boolean processing = true;	
	private Worker worker = null;
	public void setConfig(Config config) {
		this.config = config;
	}
	public static void main(String[] args) {
		Server server = new Server();
		// create the work thread
		Worker worker = server.createWorker(args);
		worker.start();		
		server.receiveAndExecuteCommand();
	}
	private Worker createWorker(String[] args) {
		Worker worker = new Worker();
		this.worker = worker;
		return worker;
	}
	/**
	 * receive the command from client and execute the command. the method is
	 * keeping running until client send the 'stop' command.
	 * 
	 * @throws Exception
	 */
	public void receiveAndExecuteCommand() {
		ServerSocket serverSocket = buildSocketConnection();
		// loop until client send 'stop' command
		while (processing) {
			Socket socket = null;
			try {
			socket = serverSocket.accept();
			String commandLine = readCommandFromSocket(socket);
                executeCommand(commandLine);
			} catch (Exception e) {
				throw new RuntimeException(e);
			} finally {
				ResourceUtils.closeSocket(socket);
			}
		}
	}
	private void executeCommand(String commandLine) {
		// TODO Auto-generated method stub
	}

	/**
	 * read the command from the socket
	 * 
	 * @param socket
	 * @return
	 */
	private String readCommandFromSocket(Socket socket) {
		InputStream in = null;
		BufferedReader bufferedReader = null;
		String commandLine = null;
		try {
			in = socket.getInputStream();
			bufferedReader = new BufferedReader(new InputStreamReader(in));
			commandLine = bufferedReader.readLine();
		} catch (IOException e) {
			throw new RuntimeException(e);
		} finally {
			ResourceUtils.closeInputStream(in);
			ResourceUtils.closeReader(bufferedReader);
		}
		return commandLine;
	}
	/**
	 * build the socket.
	 * 
	 * @return
	 */
	private ServerSocket buildSocketConnection() {
		// prepare the socket for client to connect.
		ServerSocket serverSocket;
		try {
			serverSocket = new ServerSocket(config.getSocketPort());
		} catch (java.net.BindException e1) {
			throw new RuntimeException("Socket port already in use.", e1);
		} catch (IOException ioe) {
			throw new RuntimeException(ioe);
		}
		return serverSocket;
	}
}


清单 3. 工作程序
package com.ibm.batch.sample;

import org.apache.log4j.Logger;

public class Worker extends Thread {
	Logger logger = Logger.getLogger(Worker.class);
	/**
	 * the main method for create item function.
	 */
	public void run() {
		createItem();
	}
	/**
	 * do the real job
	 */
	private void createItem() {	 		
	}
}

添加 suspend 和 slowdown 处理命令

大数量的数据迁移一般是在周末或者晚上进行,但是如果客户的历史数据太大,在周末或者晚上数据可能处理不完,为了不影响生产环境的性能,我们必须能够在客户的工作时间暂缓处理或者降低处理的频率,把 cpu 等资源让给客户程序,也就是说处理线程 worker 的工作可以 suspend 或者 slowdow 。为了让 worker 线程知道需要 suspend 当前处理,我们可以在 worker 内部设置一个布尔变量 isSuspend,当程序在循环创建 CM item 的时候,我们每次都判断一下这个布尔变量 isSuspend,当其为 ture 的时候,程序就调用线程的 wait 方法中断当前线程的处理,wait 方法还可以接受一个以微秒为单位的时间参数,当时间到达 wait 指定的时间的时候,程序继续创建 CM Item 。为了多线程之间的变量可见性,我们必须把 worker 的 isSuspend 变量和 suspendTime 设置为 volatile 。同理我们设置一个布尔变量 isSlowdown 以及 slowdowTime 。示例程序如下:


清单 4. 工作程序
package com.ibm.batch.sample;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import org.apache.log4j.Logger;
import com.ibm.batch.sample.util.ResourceUtils;

public class Worker extends Thread {
	Logger logger = Logger.getLogger(Worker.class);	
	private volatile boolean isSlowdown = false;
	private volatile Double slowdownTime;
	private volatile boolean isSuspend;
	private volatile Double suspendTime;
	public void setSlowdown(boolean isSlowdown) {
		this.isSlowdown = isSlowdown;
	}
	public void setSlowdownTime(Double slowdownTime) {
		this.slowdownTime = slowdownTime;
	}
	public void setSuspend(boolean isSuspend) {
		this.isSuspend = isSuspend;
	}
	public void setSuspendTime(Double suspendTime) {
		this.suspendTime = suspendTime;
	}
	public boolean isSlowdown() {
		return isSlowdown;
	}
	public Double getSlowdownTime() {
		return slowdownTime;
	}
	public boolean isSuspend() {
		return isSuspend;
	}
	public Double getSuspendTime() {
		return suspendTime;
	}
	protected Object semaphore = new Object();
	private Config config;
	public void setConfig(Config config) {
		this.config = config;
	}


清单 5. 主方法
/**
	 * the main method for create item function.
	 */
	public void run() {
		BufferedReader reader = null;
		try {
			reader = getFileReader();
			String oneLine = null;
			while ((oneLine = reader.readLine()) != null) {
				if (isSlowdown()) {
					sleep4GivenTime();
				}
				if (isSuspend()) {
					suspend4SomeTime();
				}
				createItem(oneLine);
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			ResourceUtils.closeReader(reader);
		}
	}

	/**
	 * current thread sleep for some time,the unit is minute.
	 */
	protected void sleep4GivenTime() {
		try {
			Thread.sleep((long) (slowdownTime.doubleValue() * 1000));
		} catch (InterruptedException e) {
			// do nothing
		}
	}


清单 6.Suspend 方法
			
/**
 * suspend working for given time.
 */
protected void suspend4SomeTime() {
	synchronized (semaphore) {
	try {
	Double suspendTime = getSuspendTime();
	if (suspendTime != null) {
		double suspendTimeDouble = suspendTime.doubleValue() * 60 * 1000;
		semaphore.wait((long) suspendTimeDouble);
	} else {
	                     semaphore.wait();
	}
	} catch (InterruptedException e) {
	// tell user that the processing started
	logger.info("suspend is over,system is continue processing .");
	}
	}
	}
	/**
	 * do the real job
	 * 
	 * @throws Exception
	 */
	private void createItem(String oneLine) throws Exception {
	}
	private BufferedReader getFileReader() throws FileNotFoundException {
		String fileName = config.getFileName();
		File processingFile = new File(fileName);
		BufferedReader reader = new BufferedReader(new FileReader(
				processingFile));
		return reader;
	}
}

添加 resume 功能

在程序暂停处理以后,我们可以提前终止 suspend,让框架继续处理,也就是框架必须有 resume 功能。我们调用 Worker.java 对象上的 notify 方法来实现这个功能,示例如下:


清单 7.Resume
public class Worker extends Thread {
	/**
	 * resume the working.
	 */
	public void continueWorking() {
		cleanSuspend();
		synchronized (semaphore) {
			semaphore.notify();
		}
	}
}

 

添加 stop 和 re-start 功能

有时候用户因为一些原因(例如修改配置文件)想停止程序的执行,所以框架必须有 stop 的功能,但是 stop 的时候我们必须注意记录程序处理到的行数,这样客户再开始执行的时候能够从上次执行的断点继续执行,也就是框架具备了 re-start 功能,这是 batch 程序必须具备的一种很重要的功能,re-start 功能有多种实现方法,我们这里采取一种简单的方法,在 stop 的时候,把当前处理的记录到一个文本文件中去,下次启动的时候从上次最后处理的对象开始进行处理。所以我们在 Worker.java 中增加一个 keepProcessing 布尔变量,在循环创建 CM Item 的时候 , 我们每次都判断一下这个值是否为 true,如果为 false 的话,我们就停止循环处理,在 Worker.java 中还要增加一个 moveReaderToLastProcess 方法,把 reader 重新定向到上次处理点。


清单 8. 停止和重启
public class Worker extends Thread {
	private volatile boolean keepProcessing;
	public boolean isKeepProcessing() {
		return keepProcessing;
	}
	public void setKeepProcessing(boolean keepProcessing) {
		this.keepProcessing = keepProcessing;
	}
	/**
	 * the main method for create item function.
	 */
	public void run() {
		BufferedReader reader = null;
		try {
			long lastProcessedRow = config.getLastProcessedRow();	
			reader = moveReaderToLastProcess(lastProcessedRow);
			String oneLine = null;
			connectToCM();
			while (((oneLine = reader.readLine()) != null)
					&& isKeepProcessing()) {
				if (isSlowdown()) {
					sleep4GivenTime();
				}
				if (isSuspend()) {
					suspend4SomeTime();
				}
				createItem(oneLine);
				lastProcessedRow++;
			}
			logCurrentProcessingLine(lastProcessedRow);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			ResourceUtils.closeReader(reader);
		}
	}	
	private void logCurrentProcessingLine(long lastProcessedRow) {
		config.setLastProcessedRow(lastProcessedRow);
	}	
	/**
	 * move current reader position to last process postion
	 * @return
	 * @throws IOException
	 */
private BufferedReader moveReaderToLastProcess(long lastProcessedRow) 
         throws IOException {
		// get the file reader
		BufferedReader reader = getFileReader();	
			
		// move the reader to the start row -1.
		int count = 0;
		while (count < lastProcessedRow-1) {
			reader.readLine();			
			count++;
		}
		return reader;
	}
}

添加错误处理功能

刚才我们调用的 createItem 方法是直接抛出异常的,但是这样的处理实际上是错误的,因为在 batch 处理过程中,我们不希望在处理某一个 item 出错导致剩余的 item 不再处理,所以我们在 catch 里面对异常进行分类处理,我们 catch 住非检查异常(runtime exception),通常非检查异常是不可以恢复的,所以我们直接抛出,让程序结束处理。对于其余的异常,我们只是在日志中记录下来,并不抛出。在全部处理结束以后,用户可以检查日志来进行相应的处理。示例代码如下:


清单 9. 错误处理
public class Worker extends Thread {
	/**
	 * do the real job
	 * 
	 * @throws Exception
	 */
	private void createItem(String oneLine) throws Exception {
		try {
			//create the item from one line
		}catch (RuntimeException e) {
			throw e;
		}catch (Exception e) {
			logger.error(e.getMessage(),e);
		}
	}
}

添加创建 CM item 功能

下面的内容放在了如何使用配置文件来处理导入的问题。

通过调用和运行 API 来处理数据的导入,我们首先定义一个基本信息的配置文件,用来制定连接的信息,其他配置文件的目录,工作的目录等有关导入需要的参数。然后定义导入数据和 DB2 Content Manager 的项的映射配置文件。配置文件定义结束后,我们就可以调用API来启动相应的导入流程,在程序运行过程中,可以动态的更改配置,从而有效的处理导入的任务。

在开发过程中,您可以灵活地定义各种配置文件以便实现多种导入规则,同时在程序运行中进行数据校验,以防止冗余和非法数据被错误导入。

下面的一些配置和代码示例,以此介绍了如何定义配置文件,然后管理 API 来完成导入的任务。

定义基本信息配置文件:在该文件中,须先设定 IBM DB2 Content Manager 的一些连接参数, 如:

contentManagerDatabase=iCMnlsdb // 定义调用的数据库名字
 contentManagerUsername=iCMadmin // 定义用户名
 contentManagerPassword= password // 定义连接密码
 contentManagerSchema=ICMADMIN // 定义具体的 schema

您可以在代码中用以上参数来实现对 IBM DB2 Content Manager 的连接,代码示例:

DKDatastoreICM dsICM = new DKDatastoreICM(); 
// 创建连接 dsICM.connect("iCMnlsdb", "iCMadmin", "password", "SCHEMA=ICMADMIN");

还需指定哪个文件夹存放映射文件,以及需导入的数据文件,如:

mappingFilePath=config/rapid/mapping // 映射文件路径
 dataFileFolder=config/rapid/data // 数据文件路径

也可定义一些参数来增强该导入的流程控制,如:

runPhase=2 
// 指定是第二阶段导入,在导入时需更新已有的数据

定义映射文件:该配置文件主要用于将用户想要导入的数据映射到 IBM DB2 Content Manager 的 Item Type 中,您可自由定制该文件,使用户遵循您定义的规范顺利完成数据迁移。如:

C001.del=c01 
 C002.del=c01

该定义中 C001.del 和 C002.del 是需要导入的数据文件,c01 是对应的 Item Type 名字。这种定义方法可实现将多个数据文件导入同一个 Item Type 中。

具体的对应关系如下:

position=1|name=COMPANYNAME 
 position=2|name=COMPANYID 
 position=3|name=INPUTVALUE 
 position=-1|name=SPECIALVALUE|value=C1

这个映射关系反映了数据文件中列数和 Item Type 中 attribute 的关系,如第一列在 Item Type 中代表了名字为 COMPANYNAME 的 attribute 。您也可定义一些特殊规则,如将 position 设为负数,以便反映该列是一个特殊的 attribute, 它的值是固定的。 比如将 position 设为 -1 时,名为 SPECIALVALUE 的 attribute 的值总是为 C1 。

若您想实现将一个数据文件导入多个 Item Type 中,可在数据文件中加入一个特殊列,在映射文件中指定该列的列数,以及当该列的值和多种 Item Type 的映射关系。如:

C003.del(position:3)

这样,C003.del 就不是单一的对应一个 Item Type,而是先去取第三列 INPUTVALUE 的值,再去对应表中查找到关联的 Item Type 。该对应表可设成:

Value1=c01 
 Value2=c02

若第三列 INPUTDOCID 的值为 Value1 时,其对应的 Item Type 为 c01,同样的当值为 Value2 时,会将该行数据导入到 c02 的 Item Type 中。

调用 API 完成操作的代码示例:在编写代码过程中,需要调用 DB2 Content Manager 的 API 来完成 Item Type 以及它包含的 attribute 的创建。上文已给出了通过参数来连接 Content Manager 的方法,下面的示例代码用得到的 DKDatastoreICM 来实现具体的操作:


清单 10. API 调用
// Create an item / DDO / Root Component
DKDDO ddo = dsICM.createDDO("S_withChild", itemPropertyOrSemanticType); 
//createDDO(<Overall Item Type>, <Item Property / Semantic Type>);

// Adding Multivalue Attributes to DDOs, multiple type can be used, 
//here just give some example
 ddo.setData(ddo.dataId(DKConstant.DK_CM_NAMESPACE_ATTR,"S_varchar"), 
"this is a string value");  
  //string

ddo.setData(ddo.dataId(DKConstant.DK_CM_NAMESPACE_ATTR,"S_date"), 
java.sql.Date.valueOf("2001-08-12"));
 //date

ddo.setData(ddo.dataId(DKConstant.DK_CM_NAMESPACE_ATTR,"S_double"), 
new Double("123")); 
//double

结束语

通过本文的介绍,相信您对多线程构建的 Batch 框架实现大量数据迁移的过程,和通过配置文件的管理的 API 实现数据导入的过程也有了一定的了解和学习。您可灵活地实现一对一,一对多,多对多等各种映射关系,您也可以利用多线程来实现其他的功能的开发,编写出更加富有创造性的软件。


参考资料

学习

获得产品和技术

  • 使用可直接从 developerWorks 下载的 IBM 试用软件 构建您的下一个 Linux 开发项目。

posted @ 2011-12-28 17:16 段旭 阅读(439) | 评论 (0)编辑 收藏