太阳雨

痛并快乐着

语源科技BlogJava 首页 新随笔 联系 聚合 管理
  67 Posts :: 3 Stories :: 33 Comments :: 0 Trackbacks

2008年11月10日 #

     摘要:   阅读全文
posted @ 2012-07-02 14:55 小虫旺福 阅读(514) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2010-04-29 17:33 小虫旺福 阅读(1018) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2010-04-29 17:30 小虫旺福 阅读(409) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2010-04-28 21:51 小虫旺福 阅读(5961) | 评论 (11)编辑 收藏

     摘要:   阅读全文
posted @ 2010-04-14 17:58 小虫旺福 阅读(569) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2010-04-14 17:55 小虫旺福 阅读(2159) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2010-03-05 11:44 小虫旺福 阅读(469) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2010-03-05 11:43 小虫旺福 阅读(300) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2010-03-05 11:41 小虫旺福 阅读(6940) | 评论 (2)编辑 收藏

     摘要:   阅读全文
posted @ 2010-03-05 11:39 小虫旺福 阅读(2757) | 评论 (0)编辑 收藏

婚嫁过完上班,发现自己好像什么都不会了,仿佛又变成了新入职的员工,看了一遍需求文档,找了找感觉,看了看代码,感觉回复了一些Power。
最近要研究ExtJS,烦。
突然发现钱很重要。努力挣钱,外加努力让媳妇挣钱。哈哈,
最近为租房很是烦恼,努力挣钱买房。++U

posted @ 2010-02-01 23:20 小虫旺福 阅读(304) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2010-02-01 10:04 小虫旺福 阅读(395) | 评论 (0)编辑 收藏

http://www.javaeye.com/topic/53834
mark
posted @ 2010-02-01 09:34 小虫旺福 阅读(428) | 评论 (1)编辑 收藏

http://static.raibledesigns.com/downloads/struts-resume/api/
posted @ 2010-02-01 09:33 小虫旺福 阅读(267) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2010-02-01 09:32 小虫旺福 阅读(1125) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2010-01-07 13:42 小虫旺福 阅读(7843) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2009-11-06 01:51 小虫旺福 阅读(238) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2009-11-06 01:44 小虫旺福 阅读(322) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2009-10-22 17:22 小虫旺福 阅读(386) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2009-10-22 17:19 小虫旺福 阅读(267) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2009-10-22 17:18 小虫旺福 阅读(352) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2009-10-22 17:17 小虫旺福 阅读(237) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2009-10-22 17:16 小虫旺福 阅读(263) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2009-08-06 11:01 小虫旺福 阅读(952) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2009-07-15 14:24 小虫旺福 阅读(564) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2009-07-15 14:18 小虫旺福 阅读(248) | 评论 (0)编辑 收藏

     摘要: 直接从Eclipse SDK的快捷键帮助里面copy下来的,贴出来玩。 类型 功能说明 快捷键 ...  阅读全文
posted @ 2009-07-14 12:00 小虫旺福 阅读(930) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2009-07-04 05:42 小虫旺福 阅读(309) | 评论 (0)编辑 收藏

 

                新的工作开始了,希望能有一个美好的开似乎,努力!努力!!努力!!!
                 
                付出总会有回报,加油吧!

                希望新的工作,新的环境,会有新的收获。
posted @ 2009-04-29 08:24 小虫旺福 阅读(168) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2009-03-06 17:26 小虫旺福 阅读(2385) | 评论 (1)编辑 收藏

     摘要:   阅读全文
posted @ 2009-03-04 19:16 小虫旺福 阅读(387) | 评论 (0)编辑 收藏

Iframe跨域访问的问题,困扰了我两三天

1.框架的Iframe 自动适应高度的问题.

2.Iframe框架包含的页面提交到服务器的session 丢失的问题.

 

解决办法.

1. 在iframe包含的页面 加上

<script language="javascript">document.domain=www.域名.com;</script>

2.在iframe 保航的页面服务器(resin)写一个filter 设置一下返回的((HttpServletResponse)response).setHeader("P3P","CP=CAO PSA OUR");

 

这样就可以解决以上两个问题了..

posted @ 2009-02-27 14:37 小虫旺福 阅读(6021) | 评论 (2)编辑 收藏

马上要做信息知识库了,可能会用到这个东东,提交写好,到时候方便使用(最近实在是太忙了!-_- )在ORACLE数据字典视图user_tab_columns 中提供了表的字段详细信息

用如下语句即可得到基本的信息

select column_id, column_name, data_type, data_length, data_precision, data_scale,nullable,data_default from user_tab_columns where table_name = 'Tablename' order by column_id


另外可能有一个需求一直没有想到好的解决方案,希望哪位高手能够提供建议:
我们要根据传来的数据库连接的基本信息,去连接到数据源,然后根据表名,查询出来这张表的结构(上面已经做了,不难),然后在我们的信息库中根据该表结构创建表。并复制数据。到这位置,都没有什么难的,只是方便大家理解。
后面的事情是这样,在查询出来的数据库信息中,需要显示成一个列表,但是其中有部分不是业务信息,而是另一张表的外键,这个时侯,我们要再根据这个外键来查询出来相对应的表的信息。有点像报表。
疑惑的地方在于如果是一对一的,很简单,把这个字段信息做成一个url,先不考虑性能问题,方案是可行的。但是如果是一对多的时候,就会比较麻烦。
posted @ 2009-02-20 17:28 小虫旺福 阅读(3888) | 评论 (0)编辑 收藏

今天在部署应用的时候,发现Tomcat报错:java.lang.OutOfMemoryError: PermGen space,第一感觉就是Tomcat内存分配的太小了。上网Google了一把发现了一堆资料,就不多说了,大家可以自己查。下面主要说我的解决办法。
先说我的机器的环境:
cpu                  双核2.66GHz * 2
内存                8G 
操作系统       Win2003

修改Tomcat\bin\catalina.bat文件。
找到set JAVA_OPTS=%JAVA_OPTS% -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config.file="%CATALINA_BASE%\conf\logging.properties"这句话。在前面加上rem注释掉。
在它下面加入:
set JAVA_OPTS=-server -Xms1024m -Xmx1024m -Xss512k -XX:PermSize=64M -XX:MaxNewSize=256m -XX:MaxPermSize=128m -Djava.awt.headless=true
重新启动Tomcat,正常启动了
posted @ 2009-01-07 11:46 小虫旺福 阅读(8113) | 评论 (4)编辑 收藏

     摘要:   阅读全文
posted @ 2008-12-22 12:05 小虫旺福 阅读(378) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2008-12-22 11:56 小虫旺福 阅读(230) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2008-12-09 18:35 小虫旺福 阅读(619) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2008-12-02 13:24 小虫旺福 阅读(240) | 评论 (0)编辑 收藏

     摘要: <html>  <head>  <meta http-equiv="Content-Type" content="text/html; charset=gb2312">  <style type="text/css">*{}{font-size:14px}button{}{m...  阅读全文
posted @ 2008-12-02 13:21 小虫旺福 阅读(1397) | 评论 (0)编辑 收藏

1上面的文本框只能输入数字代码(小数点也不能输入):

<input  onkeyup="this.value=this.value.replace(/\D/g,'')"  onafterpaste="this.value=this.value.replace(/\D/g,'')">

2只能输入数字,能输小数点.(注意汉字.用输入法和复制上面三个是有区别的在这里)

<input  onkeyup="if(isNaN(value))execCommand('undo')"  onafterpaste="if(isNaN(value))execCommand('undo')">
<input  name=txt1  onchange="if(/\D/.test(this.value)){alert('只能输入数字');this.value='';}">
<input type=text t_value="" o_value="" onkeypress="if(!this.value.match(/^[\+\-]?\d*?\.?\d*?$/))this.value=this.t_value;else this.t_value=this.value;if(this.value.match(/^(?:[\+\-]?\d+(?:\.\d+)?)?$/))this.o_value=this.value" onkeyup="if(!this.value.match(/^[\+\-]?\d*?\.?\d*?$/))this.value=this.t_value;else this.t_value=this.value;if(this.value.match(/^(?:[\+\-]?\d+(?:\.\d+)?)?$/))this.o_value=this.value" onblur="if(!this.value.match(/^(?:[\+\-]?\d+(?:\.\d+)?|\.\d*?)?$/))this.value=this.o_value;else{if(this.value.match(/^\.\d+$/))this.value=0+this.value;if(this.value.match(/^\.$/))this.value=0;this.o_value=this.value}">

3只能输入字母和汉字

<input onkeyup="value=value.replace(/[\d]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[\d]/g,''))" maxlength=10 name="Numbers">

4只能输入英文字母和数字,不能输入中文

<input onkeyup="value=value.replace(/[^\w\.\/]/ig,'')">

5只能输入数字和英文chun

<input onKeyUp="value=value.replace(/[^\d|chun]/g,'')">

6小数点后只能有最多两位(数字,中文都可输入),不能输入字母和运算符号:

<input onKeyPress="if((event.keyCode<48 || event.keyCode>57) && event.keyCode!=46 || /\.\d\d$/.test(value))event.returnValue=false">
7小数点后只能有最多两位(数字,字母,中文都可输入),可以输入运算符号
<input onkeyup="this.value=this.value.replace(/^(\-)*(\d+)\.(\d\d).*$/,'$1$2.$3')">
附:
正则表达式用于字符串处理,表单验证等场合,实用高效,但用到时总是不太把握,以致往往要上网查一番。我将一些常用的表达式收藏在这里,作备忘之用。本贴随时会更新。

匹配中文字符的正则表达式: [\u4e00-\u9fa5]

匹配双字节字符(包括汉字在内):[^\x00-\xff]

应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)

String.prototype.len=function(){return this.replace([^\x00-\xff]/g,"aa").length;}

匹配空行的正则表达式:\n[\s| ]*\r

匹配HTML标记的正则表达式:/<(.*)>.*<\/\1>|<(.*) \/>/

匹配首尾空格的正则表达式:(^\s*)|(\s*$)

应用:javascript中没有像vbscript那样的trim函数,我们就可以利用这个表达式来实现,如下:

String.prototype.trim = function()
{
    return this.replace(/(^\s*)|(\s*$)/g, "");
}

利用正则表达式分解和转换IP地址:

下面是利用正则表达式匹配IP地址,并将IP地址转换成对应数值的Javascript程序:

function IP2V(ip)
{
re=/(\d+)\.(\d+)\.(\d+)\.(\d+)/g  //匹配IP地址的正则表达式
if(re.test(ip))
{
return RegExp.$1*Math.pow(255,3))+RegExp.$2*Math.pow(255,2))+RegExp.$3*255+RegExp.$4*1
}
else
{
throw new Error("Not a valid IP address!")
}
}

不过上面的程序如果不用正则表达式,而直接用split函数来分解可能更简单,程序如下:

var ip="10.100.20.168"
ip=ip.split(".")
alert("IP值是:"+(ip[0]*255*255*255+ip[1]*255*255+ip[2]*255+ip[3]*1))

匹配Email地址的正则表达式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*

匹配网址URL的正则表达式:http://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?

利用正则表达式去除字串中重复的字符的算法程序:[注:此程序不正确,原因见本贴回复]

var s="abacabefgeeii"
var s1=s.replace(/(.).*\1/g,"$1")
var re=new RegExp("["+s1+"]","g"?琼?渦獢p?????浜睹扥潜桴牥摜極慢?瑨m?)
var s2=s.replace(re,"")
alert(s1+s2)  //结果为:abcefgi

我原来在CSDN上发贴寻求一个表达式来实现去除重复字符的方法,最终没有找到,这是我能想到的最简单的实现方法。思路是使用后向引用取出包括重复的字符,再以重复的字符建立第二个表达式,取到不重复的字符,两者串连。这个方法对于字符顺序有要求的字符串可能不适用。

得用正则表达式从URL地址中提取文件名的javascript程序,如下结果为page1

s="http://www.9499.net/page1.htm"
s=s.replace(/(.*\/){0,}([^\.]+).*/ig,"$2")
alert(s)

利用正则表达式限制网页表单里的文本框输入内容:

用正则表达式限制只能输入中文:onkeyup="value=value.replace(/[^\u4E00-\u9FA5]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\u4E00-\u9FA5]/g,''))"

用正则表达式限制只能输入全角字符: onkeyup="value=value.replace(/[^\uFF00-\uFFFF]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\uFF00-\uFFFF]/g,''))"

用正则表达式限制只能输入数字:onkeyup="value=value.replace(/[^\d]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))"

用正则表达式限制只能输入数字和英文:onkeyup="value=value.replace(/[\W]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))"

补充:
^\d+$  //匹配非负整数(正整数 + 0)
^[0-9]*[1-9][0-9]*$  //匹配正整数
^((-\d+)|(0+))$  //匹配非正整数(负整数 + 0)
^-[0-9]*[1-9][0-9]*$  //匹配负整数
^-?\d+$    //匹配整数
^\d+(\.\d+)?$  //匹配非负浮点数(正浮点数 + 0)
^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$  //匹配正浮点数
^((-\d+(\.\d+)?)|(0+(\.0+)?))$  //匹配非正浮点数(负浮点数 + 0)
^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$  //匹配负浮点数
^(-?\d+)(\.\d+)?$  //匹配浮点数
^[A-Za-z]+$  //匹配由26个英文字母组成的字符串
^[A-Z]+$  //匹配由26个英文字母的大写组成的字符串
^[a-z]+$  //匹配由26个英文字母的小写组成的字符串
^[A-Za-z0-9]+$  //匹配由数字和26个英文字母组成的字符串
^\w+$  //匹配由数字、26个英文字母或者下划线组成的字符串
^[\w-]+(\.[\w?琼?渦獢p?????浜睹扥潜桴牥摜極慢?瑨m?-]+)*@[\w-]+(\.[\w-]+)+$    //匹配email地址
^[a-zA-z]+://匹配(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\S*)?$  //匹配url


利用正则表达式去除字串中重复的字符的算法程序:

var s="abacabefgeeii"
var s1=s.replace(/(.).*\1/g,"$1")
var re=new RegExp("["+s1+"]","g")
var s2=s.replace(re,"")
alert(s1+s2) //结果为:abcefgi
===============================
如果var s = "abacabefggeeii"
结果就不对了,结果为:abeicfgg
正则表达式的能力有限
posted @ 2008-12-02 13:17 小虫旺福 阅读(479) | 评论 (0)编辑 收藏

 1判断select选项中 是否存在Value="paraValue"的Item 
 2向select选项中 加入一个Item 
 3从select选项中 删除一个Item 
 4删除select中选中的项 
 5修改select选项中 value="paraValue"的text为"paraText" 
 6设置select中text="paraText"的第一个Item为选中 
 7设置select中value="paraValue"的Item为选中 
 8得到select的当前选中项的value 
 9得到select的当前选中项的text 
10得到select的当前选中项的Index 
11清空select的项 

js 代码
// 1.判断select选项中 是否存在Value="paraValue"的Item        
function jsSelectIsExitItem(objSelect, objItemValue) {        
    
var isExit = false;        
    
for (var i = 0; i < objSelect.options.length; i++{        
        
if (objSelect.options[i].value == objItemValue) {        
            isExit 
= true;        
            
break;        
        }
        
    }
        
    
return isExit;        
}
         
   
// 2.向select选项中 加入一个Item        
function jsAddItemToSelect(objSelect, objItemText, objItemValue) {        
    
//判断是否存在        
    if (jsSelectIsExitItem(objSelect, objItemValue)) {        
        alert(
"该Item的Value值已经存在");        
    }
 else {        
        
var varItem = new Option(objItemText, objItemValue);      
        objSelect.options.add(varItem);     
        alert(
"成功加入");     
    }
        
}
        
   
// 3.从select选项中 删除一个Item        
function jsRemoveItemFromSelect(objSelect, objItemValue) {        
    
//判断是否存在        
    if (jsSelectIsExitItem(objSelect, objItemValue)) {        
        
for (var i = 0; i < objSelect.options.length; i++{        
            
if (objSelect.options[i].value == objItemValue) {        
                objSelect.options.remove(i);        
                
break;        
            }
        
        }
        
        alert(
"成功删除");        
    }
 else {        
        alert(
"该select中 不存在该项");        
    }
        
}
    
   
   
// 4.删除select中选中的项    
function jsRemoveSelectedItemFromSelect(objSelect) {        
    
var length = objSelect.options.length - 1;    
    
for(var i = length; i >= 0; i--){    
        
if(objSelect[i].selected == true){    
            objSelect.options[i] 
= null;    
        }
    
    }
    
}
      
   
// 5.修改select选项中 value="paraValue"的text为"paraText"        
function jsUpdateItemToSelect(objSelect, objItemText, objItemValue) {        
    
//判断是否存在        
    if (jsSelectIsExitItem(objSelect, objItemValue)) {        
        
for (var i = 0; i < objSelect.options.length; i++{        
            
if (objSelect.options[i].value == objItemValue) {        
                objSelect.options[i].text 
= objItemText;        
                
break;        
            }
        
        }
        
        alert(
"成功修改");        
    }
 else {        
        alert(
"该select中 不存在该项");        
    }
        
}
        
   
// 6.设置select中text="paraText"的第一个Item为选中        
function jsSelectItemByValue(objSelect, objItemText) {            
    
//判断是否存在        
    var isExit = false;        
    
for (var i = 0; i < objSelect.options.length; i++{        
        
if (objSelect.options[i].text == objItemText) {        
            objSelect.options[i].selected 
= true;        
            isExit 
= true;        
            
break;        
        }
        
    }
              
    
//Show出结果        
    if (isExit) {        
        alert(
"成功选中");        
    }
 else {        
        alert(
"该select中 不存在该项");        
    }
        
}
        
   
// 7.设置select中value="paraValue"的Item为选中    
document.all.objSelect.value = objItemValue;    
       
// 8.得到select的当前选中项的value    
var currSelectValue = document.all.objSelect.value;    
       
// 9.得到select的当前选中项的text    
var currSelectText = document.all.objSelect.options[document.all.objSelect.selectedIndex].text;    
       
// 10.得到select的当前选中项的Index    
var currSelectIndex = document.all.objSelect.selectedIndex;    
       
// 11.清空select的项    
document.all.objSelect.options.length = 0;   
posted @ 2008-12-02 10:57 小虫旺福 阅读(251) | 评论 (0)编辑 收藏

为什么要用日志(Log)?
这个……就不必说了吧。

为什么不用System.out.println()?
功能太弱;不易于控制。如果暂时不想输出了怎么办?如果想输出到文件怎么办?如果想部分输出怎么办?……

为什么同时使用commons-logging和Log4j?为什么不仅使用其中之一?
Commons-loggin的目的是为“所有的Java日志实现”提供一个统一的接口,它自身的日志功能平常弱(只有一个简单的SimpleLog?),所以一般不会单独使用它。

Log4j的功能非常全面强大,是目前的首选。我发现几乎所有的Java开源项目都会用到Log4j,但我同时发现,所有用到Log4j的项目一般也同时会用到commons-loggin。我想,大家都不希望自己的项目与Log4j绑定的太紧密吧。另外一个我能想到的“同时使用commons-logging和Log4j”的原因是,简化使用和配置。

       强调一点,“同时使用commons-logging和Log4j”,与“单独使用Log4j”相比,并不会带来更大的学习、配置和维护成本,反而更加简化了我们的工作。我想这也是为什么“所有用到Log4j的项目一般也同时会用到commons-loggin”的原因之一吧。


 


Commons-logging能帮我们做什么?
l         提供一个统一的日志接口,简单了操作,同时避免项目与某个日志实现系统紧密a耦合

l         很贴心的帮我们自动选择适当的日志实现系统(这一点非常好!)

l         它甚至不需要配置


 


这里看一下它怎么“‘很贴心的’帮我们‘自动选择’‘适当的’日志实现系统”:

1)        首先在classpath下寻找自己的配置文件commons-logging.properties,如果找到,则使用其中定义的Log实现类;

2)        如果找不到commons-logging.properties文件,则在查找是否已定义系统环境变量org.apache.commons.logging.Log,找到则使用其定义的Log实现类;

3)        否则,查看classpath中是否有Log4j的包,如果发现,则自动使用Log4j作为日志实现类;

4)        否则,使用JDK自身的日志实现类(JDK1.4以后才有日志实现类);

5)        否则,使用commons-logging自己提供的一个简单的日志实现类SimpleLog;

(以上顺序不保证完全准确,请参考官方文档)


 


可见,commons-logging总是能找到一个日志实现类,并且尽可能找到一个“最合适”的日志实现类。我说它“很贴心”实际上是因为:1、可以不需要配置文件;2、自动判断有没有Log4j包,有则自动使用之;3、最悲观的情况下也总能保证提供一个日志实现(SimpleLog)。

       可以看到,commons-logging对编程者和Log4j都非常友好。

       为了简化配置commons-logging,一般不使用commons-logging的配置文件,也不设置与commons-logging相关的系统环境变量,而只需将Log4j的Jar包放置到classpash中就可以了。这样就很简单地完成了commons-logging与Log4j的融合。如果不想用Log4j了怎么办?只需将classpath中的Log4j的Jar包删除即可。

就这么简单!

代码应该怎么写?
我们在需要输出日志信息的“每一人”类中做如下的三个工作:

1、导入所有需的commongs-logging类:

import org.apache.commons.logging.Log;

 

import org.apache.commons.logging.LogFactory;

 

如果愿意简化的话,还可以两行合为一行:

import org.apache.commons.logging.*;

 


 


2、在自己的类中定义一个org.apache.commons.logging.Log类的私有静态类成员:

private static Log log = LogFactory.getLog(YouClassName.class);

 

注意这里定义的是static成员,以避免产生多个实例。

LogFactory.getLog()方法的参数使用的是当前类的class,这是目前被普通认为的最好的方式。为什么不写作LogFactory.getLog(this.getClass())?因为static类成员访问不到this指针!


 


3、使用org.apache.commons.logging.Log类的成员方法输出日志信息:

log.debug("111");

 

log.info("222");

 

log.warn("333");

 

log.error("444");

 

log.fatal("555");

 

这里的log,就是上面第二步中定义的类成员变量,其类型是org.apache.commons.logging.Log,通过该类的成员方法,我们就可以将不同性质的日志信息输出到目的地(目的地是哪里?视配置可定,可能是stdout,也可能是文件,还可能是发送到邮件,甚至发送短信到手机……详见下文对log4j.properties的介绍):

l         debug()   输出“调试”级别的日志信息;

l         info()      输出“信息”级别的日志信息;

l         warn()    输出“警告”级别的日志信息;

l         error()     输出“错误”级别的日志信息;

l         fatal()      输出“致命错误”级别的日志信息;

根据不同的性质,日志信息通常被分成不同的级别,从低到高依次是:“调试(DEBUG)”“信息(INFO)”“警告(WARN)”“错误(ERROR)”“致命错误(FATAL)”。为什么要把日志信息分成不同的级别呢?这实际上是方便我们更好的控制它。比如,通过Log4j的配置文件,我们可以设置“输出‘调试’及以上级别的日志信息”(即“调试”“信息”“警告”“错误”“致命错误”),这对项目开发人员可能是有用的;我们还可以设置“输出“警告”及以上级别的日志信息”(即“警告”“错误”“致命错误”),这对项目最终用户可能是有用的。

       仅从字面上理解,也可以大致得出结论:最常用的应该是debug()和info();而warn()、error()、fatal()仅在相应事件发生后才使用。

 


从上面三个步骤可以看出,使用commons-logging的日志接口非常的简单,不需要记忆太多东西:仅仅用到了两个类Log, LogFactory,并且两个类的方法都非常少(后者只用到一个方法,前者经常用到的也只是上面第三步中列出的几个),同时参数又非常简单。

上面所介绍的方法是目前被普通应用的,可以说是被标准化了的方法,几乎所有的人都是这么用。如果不信,或想确认一下,就去下载几个知名的Java开源项目源代码看一下吧。


下面给出一个完整的Java类的代码:


package liigo.testlog;
 


import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;


public class TestLog

{

    private static Log log = LogFactory.getLog(TestLog.class);
    public void test()

    {

 

        log.debug("111");

        log.info("222");

        log.warn("333");

        log.error("444");

        log.fatal("555");

 

    }


 


    public static void main(String[] args)

 

    {

        TestLog testLog = new TestLog();

        testLog.test();

 

    }

}

 


只要保证commons-logging的jar包在classpath中,上述代码肯定可以很顺利的编译通过。那它的执行结果是怎么样的呢?恐怕会有很大的不同,请继续往下看。


Log4j在哪里呢?它发挥作用了吗?
应该注意到,我们上面给出的源代码,完全没有涉及到Log4j——这正是我们所希望的,这也正是commons-logging所要达到的目标之一。

可是,怎么才能让Log4j发挥它的作用呢?答案很简单,只需满足“classpath中有Log4j的jar包”。前面已经说过了,commons-logging会自动发现并应用Log4j。所以只要它存在,它就发挥作用。(它不存在呢?自然就不发挥作用,commons-logging会另行选择其它的日志实现类。)

 


注意:配置文件log4j.properties对Log4j来说是必须的。如果classpath中没有该配置文件,或者配置不对,将会引发运行时异常。


 
       这样,要正确地应用Log4j输出日志信息,log4j.properties的作用就很重要了。好在该文件有通用的模板,复制一份(稍加修改)就可以使用。几乎每一个Java项目目录内都会有一个log4j.properties文件,可下载几个Java开源项目源代码查看。本文最后也附一个模板性质的log4j.properties文件,直接复制过去就可以用,或者根据自己的需要稍加修改。后文将会log4j.properties文件适当作一些介绍。


 
       这里顺便提示一点:如果不用commons-logging,仅仅单独使用Log4j,操作上反而要稍微麻烦一些,因为Log4j需要多一点点的初始化代码(相比commons-logging而言):

import org.apache.log4j.Logger;

 

import org.apache.log4j.PropertyConfigurator;

 

public class TestLog4j {

 

   static Logger logger = Logger.getLogger(TestLog4j.class); //First step

 

   public static void main(String args[]) {

 

      PropertyConfigurator.configure("log4j.properties"); //Second step

 

      logger.debug("Here is some DEBUG"); //Third step

 

      logger.info("Here is some INFO");

 

      logger.warn("Here is some WARN");

 

      logger.error("Here is some ERROR");

 

      logger.fatal("Here is some FATAL");

 

   }

 

}

不过也就多出一行。但这至少说明,引用commons-logging并没有使问题复杂化,反而简单了一些。在这里1+1就小于2了。这也验证了前面的结论。

总结
将commons-logging和Log4j的jar包都放置到classpath下,同时也将Log4j的配置文件放到classpath中,两者就可以很好的合作。


采用Log4j配合commons-logging作为日志系统,是目前Java领域非常非常流行的模式,使用非常非常的普遍。两者的结合带来的结果就是:简单 + 强大。

commons-logging提供了简捷、统一的接口,不需要额外配置,简单;

Log4j功能非常全面、强大;

commons-logging仅仅对Log4j(当然还包括其它LOG实现)作了一层包装,具体的日志输出还是在内部转交给身后的Log4j来处理;而Log4j虽然做了所有的事情,却甘作绿叶,从不以真身示人。

两者堪称绝配。


对log4j.properties的一点介绍
下面对log4j.properties文件内容作一点点介绍,以后文所附log4j.properties文件为例:

除去以#开头的注释以及空行,第一行有用的内容是:

log4j.rootLogger = DEBUG, CONSOLE,A1

log4j.rootLogger是最最重要的一个属性了,它定义日志信息的“输出级别”和“输出目的地”。

关键看“=”后面的值,“DEBUG, CONSOLE,A1”这里我们要把它分成两部分:第一个逗号之前的是第一部分,指定“输出级别”;后面的是第二部分,指定“输出目的地”。可以同时指定多个“输出目的地”,以逗号隔开。

具体到上面这一行:它指定的“输出级别”是“DEBUG”;它指定的“输出目的地”是“CONSOLE”和“A1”。

注意:

l         “输出级别”有可选的五个值,分别是DEBUG、INFO、WARN、ERROR、FATAL,它们是由Log4j系统定义的。

l         “输出目的地”就是我们自己定义的了,就在log4j.properties的后面部分,此文件定义的“输出目的地”有CONSOLE、FILE、ROLLING_FILE、SOCKET、LF5_APPENDER、MAIL、DATABASE、A1、im。该文件之所以可作主模板,就是因为它比较全面地定义了各种常见的输出目的地(控制台、文件、电子邮件、数据库等)。

好,下面详细解释“log4j.rootLogger=DEBUG, CONSOLE,A1”这一行:

l         指定“输出级别”是“DEBUG”,即,仅输出级别大于等于“调试(DEBUG)”的日志信息。如果此处指定的是“WARN”则仅调用warn()、error()、fatal()方法输出的日志信息才被输出到“输出目的地”,而调用debug()、info()方法输出的日志信息不被输出到“输出目的地”。明白了吗?Log4j就是以这种方式来过滤控制日志信息的输出与否,这也是对日志信息进行级别分类的目的。

 

l         指定“输出目的地”是“CONSOLE”和“A1”,即,将指定的日志信息(根据日志级别已进行了过滤)同时输出到的“控制台”和“SampleMessages.log4j文件”。


为什么说“CONSOLE”表示将日志信息输出到“控制台”呢?那就要看一下后文的定义了:

# 应用于控制台

 

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender

 

log4j.appender.Threshold=DEBUG

 

log4j.appender.CONSOLE.Target=System.out

 

log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout

 

log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

#log4j.appender.CONSOLE.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD] n%c[CATEGORY]%n%m[MESSAGE]%n%n


为什么说“A1”表示将日志信息输出到“SampleMessages.log4j文件”呢?还要看后文的定义:

 

log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender

log4j.appender.A1.File=SampleMessages.log4j

 

log4j.appender.A1.DatePattern=yyyyMMdd-HH'.log4j'

 

log4j.appender.A1.layout=org.apache.log4j.xml.XMLLayout

 

注意:这里的定义没有指定输出文件的路径,它的路径实际上是 java.user.path的值。
 


您应该已经注意到,在定义“输出目的地”时,还可以指定日志格式、时间、布局等相关信息。略过。


好了,我可以根据需要,将这一行修改为:

log4j.rootLogger = ERROR, CONSOLE,FILE,MAIL

 

将“错误(ERROR)”及“致命错误(FATAL)”级别的日志信息同时输出到控制台、文件,并且发电子邮件向系统管理员报告。是不是很爽?(如果将“调试(DEBUG)”级别的日志信息邮件给管理员,恐怕迟早会把他/她的邮箱涨爆,哪怕用的是Gmail!再次理解了“将日志信息分为不同级别”的意图了吧?)

 


附:一个有用的log4j.properties文件模板
##Log4J的配置之简单使它遍及于越来越多的应用中了

##Log4J配置文件实现了输出到控制台、文件、回滚文件、发送日志邮件、输出到数据库日志表、自定义标签等全套功能。择其一二使用就够用了。

##此文件(log4j.properties)内容来自网络,非本文作者liigo原创。


log4j.rootLogger=DEBUG, CONSOLE,A1

log4j.addivity.org.apache=true

 


# 应用于控制台


log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender

log4j.appender.Threshold=DEBUG

log4j.appender.CONSOLE.Target=System.out

log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout

log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

#log4j.appender.CONSOLE.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD] n%c[CATEGORY]%n%m[MESSAGE]%n%n

 


#应用于文件


 
log4j.appender.FILE=org.apache.log4j.FileAppender

log4j.appender.FILE.File=file.log

log4j.appender.FILE.Append=false

log4j.appender.FILE.layout=org.apache.log4j.PatternLayout

log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

# Use this layout for LogFactor 5 analysis


# 应用于文件回滚


log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender

log4j.appender.ROLLING_FILE.Threshold=ERROR

log4j.appender.ROLLING_FILE.File=rolling.log

log4j.appender.ROLLING_FILE.Append=true

log4j.appender.ROLLING_FILE.MaxFileSize=10KB

log4j.appender.ROLLING_FILE.MaxBackupIndex=1

log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout

log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n


#应用于socket

log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender

log4j.appender.SOCKET.RemoteHost=localhost

log4j.appender.SOCKET.Port=5001

log4j.appender.SOCKET.LocationInfo=true

# Set up for Log Facter 5

log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout

log4j.appender.SOCET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]%n%c[CATEGORY]%n%m[MESSAGE]%n%n


# Log Factor 5 Appender

log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender

log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000


# 发送日志给邮件


log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender

log4j.appender.MAIL.Threshold=FATAL

log4j.appender.MAIL.BufferSize=10

log4j.appender.MAIL.From=web@www.wuset.com

log4j.appender.MAIL.SMTPHost=www.wusetu.com

log4j.appender.MAIL.Subject=Log4J Message

log4j.appender.MAIL.To=web@www.wusetu.com

log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout

log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n


# 用于数据库

log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender

log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test

log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver

log4j.appender.DATABASE.user=root

log4j.appender.DATABASE.password=

log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES ('[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n')

log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout

log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n


log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender

log4j.appender.A1.File=SampleMessages.log4j

log4j.appender.A1.DatePattern=yyyyMMdd-HH'.log4j'

log4j.appender.A1.layout=org.apache.log4j.xml.XMLLayout


#自定义Appender


log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender


log4j.appender.im.host = mail.cybercorlin.net

log4j.appender.im.username = username

log4j.appender.im.password = password

log4j.appender.im.recipient = corlin@cybercorlin.net


log4j.appender.im.layout=org.apache.log4j.PatternLayout

log4j.appender.im.layout.ConversionPattern =[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n


# 结束

posted @ 2008-11-10 23:47 小虫旺福 阅读(2886) | 评论 (2)编辑 收藏

 

函数是一种有零个或多个参数并且有一个返回值的程序。在SQL中Oracle内建了一系列函数,这些函数都可被称为SQL或PL/SQL语句,函数主要分为两大类:

单行函数、组函数

本文将讨论如何利用单行函数以及使用规则。

SQL中的单行函数

SQL和PL/SQL中自带很多类型的函数,有字符、数字、日期、转换、和混合型等多种函数用于处理单行数据,因此这些都可被统称为单行函数。这些函数均可用于SELECT,WHERE、ORDER BY等子句中,例如下面的例子中就包含了TO_CHAR,UPPER,SOUNDEX等单行函数。

 

SELECT ename,TO_CHAR(hiredate,'day,DD-Mon-YYYY')FROM empWhere
                        UPPER(ename) Like 'AL%'ORDER BY SOUNDEX(ename)

单行函数也可以在其他语句中使用,如update的SET子句,INSERT的VALUES子句,DELET的WHERE子句,认证考试特别注意在SELECT语句中使用这些函数,所以我们的注意力也集中在SELECT语句中。

NULL和单行函数

在如何理解NULL上开始是很困难的,就算是一个很有经验的人依然对此感到困惑。NULL值表示一个未知数据或者一个空值,算术操作符的任何一个操作数为NULL值,结果均为提个NULL值,这个规则也适合很多函数,只有CONCAT,DECODE,DUMP,NVL,REPLACE在调用了NULL参数时能够返回非NULL值。在这些中NVL函数时最重要的,因为他能直接处理NULL值,NVL有两个参数:NVL(x1,x2),x1和x2都式表达式,当x1为null时返回X2,否则返回x1。

下面我们看看emp数据表它包含了薪水、奖金两项,需要计算总的补偿

 

column name emp_id salary bonuskey type pk nulls/unique nn,
                        u nnfk table datatype number number numberlength 11.2 11.2

不是简单的将薪水和奖金加起来就可以了,如果某一行是null值那么结果就将是null,比如下面的例子:

 

update empset salary=(salary+bonus)*1.1

这个语句中,雇员的工资和奖金都将更新为一个新的值,但是如果没有奖金,即 salary + null,那么就会得出错误的结论,这个时候就要使用nvl函数来排除null值的影响。

所以正确的语句是:

 

update empset salary=(salary+nvl(bonus,0)*1.1

单行字符串函数

单行字符串函数用于操作字符串数据,他们大多数有一个或多个参数,其中绝大多数返回字符串

ASCII()

c1是一字符串,返回c1第一个字母的ASCII码,他的逆函数是CHR()

 

SELECT ASCII('A') BIG_A,ASCII('z') BIG_z FROM empBIG_A BIG_z65 122

CHR(<i>)[NCHAR_CS]

i是一个数字,函数返回十进制表示的字符

 

select CHR(65),CHR(122),CHR(223) FROM empCHR65 CHR122 CHR223A z B

CONCAT(,)

c1,c2均为字符串,函数将c2连接到c1的后面,如果c1为null,将返回c2.如果c2为null,则返回c1,如果c1、c2都为null,则返回null。他和操作符||返回的结果相同

 

select concat('slobo ','Svoboda') username from dualusernameslobo Syoboda

INITCAP()

c1为一字符串。函数将每个单词的第一个字母大写其它字母小写返回。单词由空格,控制字符,标点符号限制。

 

select INITCAP('veni,vedi,vici') Ceasar from dualCeasarVeni,Vedi,Vici

INSTR(,[,<i>[,]])

c1,c2均为字符串,i,j为整数。函数返回c2在c1中第j次出现的位置,搜索从c1的第i个字符开始。当没有发现需要的字符时返回0,如果i为负数,那么搜索将从右到左进行,但是位置的计算还是从左到右,i和j的缺省值为1.

 

select INSTR('Mississippi','i',3,3)
                        from dualINSTR('MISSISSIPPI','I',3,3)11
                        select INSTR('Mississippi','i',-2,3)
                        from dualINSTR('MISSISSIPPI','I',3,3)2

INSTRB(,[,i[,j])

与INSTR()函数一样,只是他返回的是字节,对于单字节INSTRB()等于INSTR()

LENGTH()

c1为字符串,返回c1的长度,如果c1为null,那么将返回null值。

 

select LENGTH('Ipso Facto') ergo from dualergo10

LENGTHb()

与LENGTH()一样,返回字节。

lower()

返回c的小写字符,经常出现在where子串中

 

select LOWER(colorname) from itemdetail WHERE LOWER(colorname) LIKE '%white%'COLORNAMEWinterwhite

LPAD(,<i>[,])

c1,c2均为字符串,i为整数。在c1的左侧用c2字符串补足致长度i,可多次重复,如果i小于c1的长度,那么只返回i那么长的c1字符,其他的将被截去。c2的缺省值为单空格,参见RPAD。

 

select LPAD(answer,7,'') padded,answer unpadded from question;
                        PADDED UNPADDED Yes YesNO NOMaybe maybe

LTRIM(,)

把c1中最左边的字符去掉,使其第一个字符不在c2中,如果没有c2,那么c1就不会改变。

 

select LTRIM('Mississippi','Mis') from dualLTRppi

RPAD(,<i>[,])

在c1的右侧用c2字符串补足致长度i,可多次重复,如果i小于c1的长度,那么只返回i那么长的c1字符,其他的将被截去。c2的缺省值为单空格,其他与LPAD相似

RTRIM(,)

把c1中最右边的字符去掉,使其第后一个字符不在c2中,如果没有c2,那么c1就不会改变。

REPLACE(,[,])

c1,c2,c3都是字符串,函数用c3代替出现在c1中的c2后返回。

 

select REPLACE('uptown','up','down') from dualREPLACEdowntown

STBSTR(,<i>[,])

c1为一字符串,i,j为整数,从c1的第i位开始返回长度为j的子字符串,如果j为空,则直到串的尾部。

 

select SUBSTR('Message',1,4) from dualSUBSMess

SUBSTRB(,<i>[,])

与SUBSTR大致相同,只是I,J是以字节计算。

SOUNDEX()

返回与c1发音相似的词

 

select SOUNDEX('dawes') Dawes SOUNDEX('daws') Daws,
                        SOUNDEX('dawson') from dualDawes Daws DawsonD200 D200 D250

TRANSLATE(,,)

将c1中与c2相同的字符以c3代替

 

select TRANSLATE('fumble','uf','ar') test from dualTEXTramble

TRIM([[]] from c3)

将c3串中的第一个,最后一个,或者都删除。

 

select TRIM(' space padded ') trim from dual TRIMspace padded

UPPER()

返回c1的大写,常出现where子串中

 

select name from dual where UPPER(name) LIKE 'KI%'NAMEKING

单行数字函数

单行数字函数操作数字数据,执行数学和算术运算。所有函数都有数字参数并返回数字值。所有三角函数的操作数和值都是弧度而不是角度,oracle没有提供内建的弧度和角度的转换函数。

 

ABS()

返回n的绝对值

ACOS()

反余玄函数,返回-1到1之间的数。n表示弧度

 

select ACOS(-1) pi,ACOS(1) ZERO FROM dualPI ZERO3.14159265 0

ASIN()

反正玄函数,返回-1到1,n表示弧度

ATAN()

反正切函数,返回n的反正切值,n表示弧度。

CEIL()

返回大于或等于n的最小整数。

COS()

返回n的余玄值,n为弧度

COSH()

返回n的双曲余玄值,n 为数字。

 

select COSH(<1.4>) FROM dualCOSH(1.4)2.15089847

EXP()

返回e的n次幂,e=2.71828183.

FLOOR()

返回小于等于N的最大整数。

LN()

返回N的自然对数,N必须大于0

LOG(,)

返回以n1为底n2的对数

MOD()

返回n1除以n2的余数,

POWER(,)

返回n1的n2次方

ROUND(,)

返回舍入小数点右边n2位的n1的值,n2的缺省值为0,这回将小数点最接近的整数,如果n2为负数就舍入到小数点左边相应的位上,n2必须是整数。

 

select ROUND(12345,-2),ROUND(12345.54321,2)
            FROM dualROUND(12345,-2) ROUND(12345.54321,2)12300 12345.54

SIGN()

如果n为负数,返回-1,如果n为正数,返回1,如果n=0返回0.

SIN()

返回n的正玄值,n为弧度。

SINH()

返回n的双曲正玄值,n为弧度。

SQRT()

返回n的平方根,n为弧度

TAN()

返回n的正切值,n为弧度

TANH()

返回n的双曲正切值,n为弧度

TRUNC(,)

返回截尾到n2位小数的n1的值,n2缺省设置为0,当n2为缺省设置时会将n1截尾为整数,如果n2为负值,就截尾在小数点左边相应的位上。

单行日期函数

单行日期函数操作DATA数据类型,绝大多数都有DATA数据类型的参数,绝大多数返回的也是DATA数据类型的值。

ADD_MONTHS(,<i>)

返回日期d加上i个月后的结果。i可以使任意整数。如果i是一个小数,那么数据库将隐式的他转换成整数,将会截去小数点后面的部分。

LAST_DAY()

函数返回包含日期d的月份的最后一天

MONTHS_BETWEEN(,)

返回d1和d2之间月的数目,如果d1和d2的日的日期都相同,或者都使该月的最后一天,那么将返回一个整数,否则会返回的结果将包含一个分数。

NEW_TIME(,,)

d1是一个日期数据类型,当时区tz1中的日期和时间是d时,返回时区tz2中的日期和时间。tz1和tz2时字符串。

NEXT_DAY(,)

返回日期d后由dow给出的条件的第一天,dow使用当前会话中给出的语言指定了一周中的某一天,返回的时间分量与d的时间分量相同。

select NEXT_DAY('01-Jan-2000'

 

,'Monday') "1st Monday",
            NEXT_DAY('01-Nov-2004','Tuesday')+7 "2nd Tuesday")
            from dual;1st Monday 2nd Tuesday03-Jan-2000 09-Nov-2004

ROUND([,])

将日期d按照fmt指定的格式舍入,fmt为字符串。

SYADATE

函数没有参数,返回当前日期和时间。

TRUNC([,])

返回由fmt指定的单位的日期d.

单行转换函数

单行转换函数用于操作多数据类型,在数据类型之间进行转换。

CHARTORWID()

c 使一个字符串,函数将c转换为RWID数据类型。

 

SELECT test_id from test_case where rowid=CHARTORWID('AAAA0SAACAAAALiAAA')

CONVERT(,[,])

c尾字符串,dset、sset是两个字符集,函数将字符串c由sset字符集转换为dset字符集,sset的缺省设置为数据库的字符集。

HEXTORAW()

x为16进制的字符串,函数将16进制的x转换为RAW数据类型。

RAWTOHEX()

x是RAW数据类型字符串,函数将RAW数据类转换为16进制的数据类型。

ROWIDTOCHAR()

函数将ROWID数据类型转换为CHAR数据类型。

TO_CHAR([[,)

x是一个data或number数据类型,函数将x转换成fmt指定格式的char数据类型,如果x为日期nlsparm=NLS_DATE_LANGUAGE 控制返回的月份和日份所使用的语言。如果x为数字nlsparm=NLS_NUMERIC_CHARACTERS 用来指定小数位和千分位的分隔符,以及货币符号。

 

NLS_NUMERIC_CHARACTERS ="dg", NLS_CURRENCY="string"

TO_DATE([,[,)

c表示字符串,fmt表示一种特殊格式的字符串。返回按照fmt格式显示的c,nlsparm表示使用的语言。函数将字符串c转换成date数据类型。

TO_MULTI_BYTE()

c表示一个字符串,函数将c的担子截字符转换成多字节字符。

TO_NUMBER([,[,)

c表示字符串,fmt表示一个特殊格式的字符串,函数返回值按照fmt指定的格式显示。nlsparm表示语言,函数将返回c代表的数字。

TO_SINGLE_BYTE()

将字符串c中得多字节字符转化成等价的单字节字符。该函数仅当数据库字符集同时包含单字节和多字节字符时才使用

其它单行函数

BFILENAME( ,)

dir是一个directory类型的对象,file为一文件名。函数返回一个空的BFILE位置值指示符,函数用于初始化BFILE变量或者是BFILE列。

DECODE(,,[,,,[])

x是一个表达式,m1是一个匹配表达式,x与m1比较,如果m1等于x,那么返回r1,否则,x与m2比较,依次类推m3,m4,m5....直到有返回结果。

DUMP(,[,[,[,]]])

x是一个表达式或字符,fmt表示8进制、10进制、16进制、或则单字符。函数返回包含了有关x的内部表示信息的VARCHAR2类型的值。如果指定了n1,n2那么从n1开始的长度为n2的字节将被返回。

EMPTY_BLOB()

该函数没有参数,函数返回 一个空的BLOB位置指示符。函数用于初始化一个BLOB变量或BLOB列。

EMPTY_CLOB()

该函数没有参数,函数返回 一个空的CLOB位置指示符。函数用于初始化一个CLOB变量或CLOB列。

GREATEST()

exp_list是一列表达式,返回其中最大的表达式,每个表达式都被隐含的转换第一个表达式的数据类型,如果第一个表达式是字符串数据类型中的任何一个,那么返回的结果是varchar2数据类型,同时使用的比较是非填充空格类型的比较。

LEAST()

exp_list是一列表达式,返回其中最小的表达式,每个表达式都被隐含的转换第一个表达式的数据类型,如果第一个表达式是字符串数据类型中的任何一个,将返回的结果是varchar2数据类型,同时使用的比较是非填充空格类型的比较。

UID

该函数没有参数,返回唯一标示当前数据库用户的整数。

USER

返回当前用户的用户名

USERENV()

基于opt返回包含当前会话信息。opt的可选值为:

ISDBA    会话中SYSDBA脚色响应,返回TRUE

SESSIONID  返回审计会话标示符

ENTRYID   返回可用的审计项标示符

INSTANCE  在会话连接后,返回实例标示符。该值只用于运行Parallel 服务器并且有 多个实例的情况下使用。

LANGUAGE  返回语言、地域、数据库设置的字符集。

LANG    返回语言名称的ISO缩写。

TERMINAL  为当前会话使用的终端或计算机返回操作系统的标示符。

VSIZE()

x是一个表达式。返回x内部表示的字节数。

SQL中的组函数

组函数也叫集合函数,返回基于多个行的单一结果,行的准确数量无法确定,除非查询被执行并且所有的结果都被包含在内。与单行函数不同的是,在解析时所有的行都是已知的。由于这种差别使组函数与单行函数有在要求和行为上有微小的差异.

组(多行)函数

与单行函数相比,oracle提供了丰富的基于组的,多行的函数。这些函数可以在select或select的having子句中使用,当用于select子串时常常都和GROUP BY一起使用。

AVG([{DISYINCT|ALL}])

返回数值的平均值。缺省设置为ALL.

 

SELECT AVG(sal),AVG(ALL sal),AVG(DISTINCT sal)
            FROM scott.empAVG(SAL) AVG(ALL SAL) AVG(DISTINCT SAL)
            1877.94118 1877.94118 1916.071413

COUNT({*|DISTINCT|ALL} )

返回查询中行的数目,缺省设置是ALL,*表示返回所有的行。

MAX([{DISTINCT|ALL}])

返回选择列表项目的最大值,如果x是字符串数据类型,他返回一个VARCHAR2数据类型,如果X是一个DATA数据类型,返回一个日期,如果X是numeric数据类型,返回一个数字。注意distinct和all不起作用,应为最大值与这两种设置是相同的。

MIN([{DISTINCT|ALL}])

返回选择列表项目的最小值。

STDDEV([{DISTINCT|ALL}])

返回选者的列表项目的标准差,所谓标准差是方差的平方根。

SUM([{DISTINCT|ALL}])

返回选择列表项目的数值的总和。

VARIANCE([{DISTINCT|ALL}])

返回选择列表项目的统计方差。

用GROUP BY给数据分组

正如题目暗示的那样组函数就是操作那些已经分好组的数据,我们告诉数据库用GROUP BY怎样给数据分组或者分类,当我们在SELECT语句的SELECT子句中使用组函数时,我们必须把为分组或非常数列放置在GROUP BY子句中,如果没有用group by进行专门处理,那么缺省的分类是将整个结果设为一类。

 

select stat,counter(*) zip_count from zip_codes GROUP BY state;
            ST ZIP_COUNT-- ---------AK 360AL 1212AR 1309AZ 768CA 3982

在这个例子中,我们用state字段分类;如果我们要将结果按照zip_codes排序,可以用ORDER BY语句,ORDER BY子句可以使用列或组函数。

 

select stat,counter(*) zip_count from zip_codes GROUP
            BY state ORDER BY COUNT(*) DESC;ST COUNT(*)-- --------
            NY 4312PA 4297TX 4123CA 3982

用HAVING子句限制分组数据

现在你已经知道了在查询的SELECT语句和ORDER BY子句中使用主函数,组函数只能用于两个子串中,组函数不能用于WHERE子串中,例如下面的查询是错误的:

 

错误SELECT sales_clerk,SUN(sale_amount)
            FROM gross_sales WHERE sales_dept='OUTSIDE'
            AND SUM(sale_amount)>10000 GROUP BY sales_clerk

这个语句中数据库不知道SUM()是什么,当我们需要指示数据库对行分组,然后限制分组后的行的输出时,正确的方法是使用HAVING语句:

 

SELECT sales_clerk,SUN(sale_amount)
            FROM gross_sales WHERE sales_dept='OUTSIDE'
            GROUP BY sales_clerkHAVING SUM(sale_amount)>10000;
posted @ 2008-11-10 23:42 小虫旺福 阅读(287) | 评论 (0)编辑 收藏

本文摘自:http://www.acnis.com/modules.php?name=ArticlE&file=article&sid=214&mode=thread&order=0&thold=0
自己用来做个记录……

此文描述了自ubuntu 5.10版本之后的系统所代命令参数,dapper,edgy以及7.04版本中可能会有一些变动,于此文不同,如有疑问可以发邮件给isher或访问wiki.ubuntu.com.cn

下面内容及向心内文的内容均为ubuntu(cn)的wiki中摘录,为方便广大是用ubuntu的使用者查找和使用,特摘录安装

查看软件xxx安装内容
  • dpkg -L xxx

查找软件
  • apt-cache search 正则表达式

查找文件属于哪个包
  • dpkg -S filename
    apt-file search filename

查询软件xxx依赖哪些包
  • apt-cache depends xxx


查询软件xxx被哪些包依赖
  • apt-cache rdepends xxx

增加一个光盘源
  • sudo apt-cdrom add

系统升级
  • sudo apt-get update
    sudo apt-get upgrade
    sudo apt-get dist-upgrade

清除所以删除包的残余配置文件
  • dpkg -l |grep ^rc|awk '{print $2}' |tr ["n"] [" "]|sudo xargs dpkg -P -

编译时缺少h文件的自动处理
  • sudo auto-apt run ./configure

查看安装软件时下载包的临时存放目录
  • ls /var/cache/apt/archives

备份当前系统安装的所有包的列表
  • dpkg --get-selections | grep -v deinstall > ~/somefile

从上面备份的安装包的列表文件恢复所有包
  • dpkg --set-selections < ~/somefile
    sudo dselect

清理旧版本的软件缓存
  • sudo apt-get autoclean

清理所有软件缓存
  • sudo apt-get clean

删除系统不再使用的孤立软件
  • sudo apt-get autoremove

查看包在服务器上面的地址
  • apt-get -qq --print-uris install ssh | cut -d' -f2

系统

查看内核
  • uname -a

查看Ubuntu版本
  • cat /etc/issue

查看内核加载的模块
  • lsmod

查看PCI设备
  • lspci

查看USB设备
  • lsusb

查看网卡状态
  • sudo ethtool eth0

查看CPU信息
  • cat /proc/cpuinfo

显示当前硬件信息
  • lshw

硬盘

查看硬盘的分区
  • sudo fdisk -l

查看IDE硬盘信息
  • sudo hdparm -i /dev/hda

查看STAT硬盘信息
  • sudo hdparm -I /dev/sda

    sudo apt-get install blktool
    sudo blktool /dev/sda id

查看硬盘剩余空间
  • df -h
    df -H

查看目录占用空间
  • du -hs 目录名

优盘没法卸载
  • sync
    fuser -km /media/usbdisk

内存

查看当前的内存使用情况
  • free -m

进程

查看当前有哪些进程
  • ps -A

中止一个进程
  • kill 进程号(就是ps -A中的第一列的数字)
    或者 killall 进程名

强制中止一个进程(在上面进程中止不成功的时候使用)
  • kill -9 进程号
    或者 killall -9 进程名

图形方式中止一个程序
  • xkill 出现骷髅标志的鼠标,点击需要中止的程序即可

查看当前进程的实时状况
  • top

查看进程打开的文件
  • lsof -p

ADSL

配置 ADSL
  • sudo pppoeconf

ADSL手工拨号
  • sudo pon dsl-provider

激活 ADSL
  • sudo /etc/ppp/pppoe_on_boot

断开 ADSL
  • sudo poff

查看拨号日志
  • sudo plog

如何设置动态域名
  • #首先去 http://www.3322.org 申请一个动态域名
    #然后修改 /etc/ppp/ip-up 增加拨号时更新域名指令
    sudo vim /etc/ppp/ip-up
    #在最后增加如下行
    w3m -no-cookie -dump 'http://username:password@members.3322.org/dyndns/update?system=dyndns&hostname=yourdns.3322.org'

网络

根据IP查网卡地址
  • arping IP地址

查看当前IP地址
  • ifconfig eth0 |awk '/inet/ {split($2,x,":");print x[2]}'

查看当前外网的IP地址
  • w3m -no-cookie -dump www.ip138.com|grep -o '[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}'
    w3m -no-cookie -dump www.123cha.com|grep -o '[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}'
    w3m -no-cookie -dump ip.loveroot.com|grep -o '[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}'

查看当前监听80端口的程序
  • lsof -i :80

查看当前网卡的物理地址
  • arp -a | awk '{print $4}'
    ifconfig eth0 | head -1 | awk '{print $5}'

立即让网络支持nat
  • echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
    sudo iptables -t nat -I POSTROUTING -j MASQUERADE

查看路由信息
  • netstat -rn
    sudo route -n

手工增加删除一条路由
  • sudo route add -net 192.168.0.0 netmask 255.255.255.0 gw 172.16.0.1
    sudo route del -net 192.168.0.0 netmask 255.255.255.0 gw 172.16.0.1

修改网卡MAC地址的方法
  • sudo ifconfig eth0 down #关闭网卡
    sudo ifconfig eth0 hw ether 00:AA:BB:CC:DD:EE #然后改地址
    sudo ifconfig eth0 up #然后启动网卡

统计当前IP连接的个数
  • netstat -na|grep ESTABLISHED|awk '{print $5}'|awk -F: '{print $1}'|sort|uniq -c|sort -r -n
    netstat -na|grep SYN|awk '{print $5}'|awk -F: '{print $1}'|sort|uniq -c|sort -r -n

统计当前20000个IP包中大于100个IP包的IP地址
  • tcpdump -tnn -c 20000 -i eth0 | awk -F "." '{print $1"."$2"."$3"."$4}' | sort | uniq -c | sort -nr | awk ' $1 > 100 '

屏蔽IPV6
  • echo "blacklist ipv6" | sudo tee /etc/modprobe.d/blacklist-ipv6

服务

添加一个服务
  • sudo update-rc.d 服务名 defaults 99

删除一个服务
  • sudo update-rc.d 服务名 remove

临时重启一个服务
  • /etc/init.d/服务名 restart

临时关闭一个服务
  • /etc/init.d/服务名 stop

临时启动一个服务
  • /etc/init.d/服务名 start

设置

配置默认Java使用哪个
  • sudo update-alternatives --config java

修改用户资料
  • sudo chfn userid

给apt设置代理
  • export http_proxy=http://xx.xx.xx.xx:xxx

修改系统登录信息
  • sudo vim /etc/motd

中文

转换文件名由GBK为UTF8
  • sudo apt-get install convmv
    convmv -r -f cp936 -t utf8 --notest --nosmart *

批量转换src目录下的所有文件内容由GBK到UTF8
  • find src -type d -exec mkdir -p utf8/{} ;
    find src -type f -exec iconv -f GBK -t UTF-8 {} -o utf8/{} ;
    mv utf8/* src
    rm -fr utf8

转换文件内容由GBK到UTF8
  • iconv -f gbk -t utf8 $i > newfile

转换 mp3 标签编码
  • sudo apt-get install python-mutagen
    find . -iname “*.mp3” -execdir mid3iconv -e GBK {} ;

控制台下显示中文
  • sudo apt-get install zhcon
    使用时,输入zhcon即可

文件

快速查找某个文件
  • whereis filename
  • find 目录 -name 文件名

查看文件类型
  • file filename

显示xxx文件倒数6行的内容
  • tail -n 6 xxx

让tail不停地读地最新的内容
  • tail -n 10 -f /var/log/apache2/access.log

查看文件中间的第五行(含)到第10行(含)的内容
  • sed -n '5,10p' /var/log/apache2/access.log

查找包含xxx字符串的文件
  • grep -l -r xxx .

查找关于xxx的命令
  • apropos xxx
    man -k xxx

通过ssh传输文件
  • scp -rp /path/filename username@remoteIP:/path #将本地文件拷贝到服务器上
    scp -rp username@remoteIP:/path/filename /path #将远程文件从服务器下载到本地

查看某个文件被哪些应用程序读写
  • lsof 文件名

把所有文件的后辍由rm改为rmvb
  • rename 's/.rm$/.rmvb/' *

把所有文件名中的大写改为小写
  • rename 'tr/A-Z/a-z/' *

删除特殊文件名的文件,如文件名:--help.txt
  • rm -- --help.txt 或者 rm ./--help.txt

查看当前目录的子目录
  • ls -d */. 或 echo */.

将当前目录下最近30天访问过的文件移动到上级back目录
  • find . -type f -atime -30 -exec mv {} ../back ;

将当前目录下最近2小时到8小时之内的文件显示出来
  • find . -mmin +120 -mmin -480 -exec more {} ;

删除修改时间在30天之前的所有文件
  • find . -type f -mtime +30 -mtime -3600 -exec rm {} ;

查找guest用户的以avi或者rm结尾的文件并删除掉
  • find . -name '*.avi' -o -name '*.rm' -user 'guest' -exec rm {} ;

查找的不以java和xml结尾,并7天没有使用的文件删除掉
  • find . ! -name *.java ! -name ‘*.xml’ -atime +7 -exec rm {} ;

统计当前文件个数
  • ls /usr/bin|wc -w

统计当前目录个数
  • ls -l /usr/bin|grep ^d|wc -l

显示当前目录下2006-01-01的文件名
  • ls -l |grep 2006-01-01 |awk '{print $8}'

压缩

解压缩 xxx.tar.gz
  • tar -zxvf xxx.tar.gz

解压缩 xxx.tar.bz2
  • tar -jxvf xxx.tar.bz2

压缩aaa bbb目录为xxx.tar.gz
  • tar -zcvf xxx.tar.gz aaa bbb

压缩aaa bbb目录为xxx.tar.bz2
  • tar -jcvf xxx.tar.bz2 aaa bbb

Nautilus

显示隐藏文件
  • Ctrl+h

显示地址栏
  • Ctrl+l

特殊 URI 地址
  • * computer:/// - 全部挂载的设备和网络
    * network:/// - 浏览可用的网络
    * burn:/// - 一个刻录 CDs/DVDs 的数据虚拟目录
    * smb:/// - 可用的 windows/samba 网络资源
    * x-nautilus-desktop:/// - 桌面项目和图标
    * file:/// - 本地文件
    * trash:/// - 本地回收站目录
    * ftp:// - FTP 文件夹
    * ssh:// - SSH 文件夹
    * fonts:/// - 字体文件夹,可将字体文件拖到此处以完成安装
    * themes:/// - 系统主题文件夹

查看已安装字体
  • 在nautilus的地址栏里输入”fonts:///“,就可以查看本机所有的fonts

程序

详细显示程序的运行信息
  • strace -f -F -o outfile <cmd>

日期和时间

设置日期
  • #date -s mm/dd/yy

设置时间
  • #date -s HH:MM

将时间写入CMOS
  • hwclock --systohc

读取CMOS时间
  • hwclock --hctosys

从服务器上同步时间
  • sudo ntpdate time.nist.gov
    sudo ntpdate time.windows.com

控制台

不同控制台间切换
  • Ctrl + ALT + ←
    Ctrl + ALT + →

指定控制台切换
  • Ctrl + ALT + Fn(n:1~7)

控制台下滚屏
  • SHIFT + pageUp/pageDown

控制台抓图
  • setterm -dump n(n:1~7)

数据库

mysql的数据库存放在地方
  • /var/lib/mysql

从mysql中导出和导入数据
  • mysqldump 数据库名 > 文件名 #导出数据库
    mysqladmin create 数据库名 #建立数据库
    mysql 数据库名 < 文件名 #导入数据库

忘了mysql的root口令怎么办
  • sudo /etc/init.d/mysql stop
    sudo mysqld_safe --skip-grant-tables &
    sudo mysqladmin -u user password 'newpassword''
    sudo mysqladmin flush-privileges

修改mysql的root口令
  • sudo mysqladmin -uroot -p password '你的新密码'

其它

下载网站文档
  • wget -r -p -np -k http://www.21cn.com
    · -r:在本机建立服务器端目录结构;
    · -p: 下载显示HTML文件的所有图片;
    · -np:只下载目标站点指定目录及其子目录的内容;
    · -k: 转换非相对链接为相对链接。

如何删除Totem电影播放机的播放历史记录
  • rm ~/.recently-used

如何更换gnome程序的快捷键
  • 点击菜单,鼠标停留在某条菜单上,键盘输入任意你所需要的键,可以是组合键,会立即生效;
    如果要清除该快捷键,请使用backspace

vim 如何显示彩色字符
  • sudo cp /usr/share/vim/vimcurrent/vimrc_example.vim /usr/share/vim/vimrc

如何在命令行删除在会话设置的启动程序
  • cd ~/.config/autostart
    rm 需要删除启动程序

如何提高wine的反应速度
  • sudo sed -ie '/GBK/,/^}/d' /usr/share/X11/locale/zh_CN.UTF-8/XLC_LOCALE
posted @ 2008-11-10 23:36 小虫旺福 阅读(318) | 评论 (0)编辑 收藏

sudo apt-get install 软件名 安装软件命令
sudo nautilus 打开文件(有root权限)
su root 切换到“root”

ls 列出当前目录文件(不包括隐含文件)
ls -a 列出当前目录文件(包括隐含文件)
ls -l 列出当前目录下文件的详细信息

cd .. 回当前目录的上一级目录
cd - 回上一次所在的目录
cd ~ 或 cd 回当前用户的宿主目录
mkdir 目录名 创建一个目录
rmdir 空目录名 删除一个空目录
rm 文件名 文件名 删除一个文件或多个文件
rm -rf 非空目录名 删除一个非空目录下的一切

mv 路经/文件 /经/文件 移动相对路经下的文件到绝对路经下
mv 文件名 新名称 在当前目录下改名
find 路经 -name “字符串” 查找路经所在范围内满足字符串匹配的文件和目录

fdisk fdisk -l 查看系统分区信息
fdisk fdisk /dev/sdb 为一块新的SCSI硬盘进行分区
chown chown root /home 把/home的属主改成root用户
chgrp chgrp root /home 把/home的属组改成root组

Useradd 创建一个新的用户
Groupadd 组名 创建一个新的组
Passwd 用户名 为用户创建密码
Passwd -d用户名 删除用户密码也能登陆
Passwd -S用户名 查询账号密码
Usermod -l 新用户名 老用户名 为用户改名
Userdel–r 用户名 删除用户一切

tar -c 创建包 –x 释放包 -v 显示命令过程 –z 代表压缩包
tar –cvf benet.tar /home/benet 把/home/benet目录打包
tar –zcvf benet.tar.gz /mnt 把目录打包并压缩
tar –zxvf benet.tar.gz 压缩包的文件解压恢复
tar –jxvf benet.tar.bz2 解压缩

make 编译
make install 安装编译好的源码包
reboot Init 6 重启LINUX系统
Halt Init 0 Shutdown –h now 关闭LINUX系统

uname -a 查看内核版本
cat /etc/issue 查看ubuntu版本
lsusb 查看usb设备
sudo ethtool eth0 查看网卡状态
cat /proc/cpuinfo 查看cpu信息
lshw 查看当前硬件信息
sudo fdisk -l 查看磁盘信息
df -h 查看硬盘剩余空间
free -m 查看当前的内存使用情况
ps -A 查看当前有哪些进程
kill 进程号(就是ps -A中的第一列的数字)或者 killall 进程名( 杀死一个进程)
kill -9 进程号 强制杀死一个进程

常用apt命令:

apt-cache search package 搜索包
apt-cache show package 获取包的相关信息,如说明、大小、版本等
sudo apt-get install package 安装包
sudo apt-get install package - - reinstall 重新安装包
sudo apt-get -f install 修复安装”-f = –fix-missing”
sudo apt-get remove package 删除包
sudo apt-get remove package - - purge 删除包,包括删除配置文件等
sudo apt-get update 更新源
sudo apt-get upgrade 更新已安装的包
sudo apt-get dist-upgrade 升级系统
sudo apt-get dselect-upgrade 使用 dselect 升级
apt-cache depends package 了解使用依赖
apt-cache rdepends package 是查看该包被哪些包依赖
sudo apt-get build-dep package 安装相关的编译环境
apt-get source package 下载该包的源代码
sudo apt-get clean && sudo apt-get autoclean 清理无用的包
sudo apt-get check 检查是否有损坏的依赖

清理所有软件缓存(即缓存在/var/cache/apt/archives目录里的deb包 )
sudo apt-get clean

删除系统不再使用的孤立软件
sudo apt-get autoremove
posted @ 2008-11-10 23:36 小虫旺福 阅读(268) | 评论 (0)编辑 收藏

     摘要: 看到一个很好的东西在国内没有被很多人使用起来,实在是不爽,所以花了很大功夫把这个手册翻译成中文,由于这篇文章很长,所以,翻译的工作量很大而且有些地方英文版也没有说清楚,虽得查看源代码,好在不是坚持做完了,大家鼓励下啊!^o^ prototype.js是一个非常优雅的javascript基础类库,对javascript做了大量的扩展,而且很好的支持Ajax,国外有多个基于此类库实现的效果库,也做得...  阅读全文
posted @ 2008-11-10 23:27 小虫旺福 阅读(275) | 评论 (0)编辑 收藏

今天碰见一到一个很郁闷的事情,当使用mvn archetype:create -DgroupId=com.mycompany.app -DartifactId=my-app来创建一个新项目时,有时候会出现以下错误:解决过程如下:

[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'archetype'.
[INFO]
----------------------------------------------------------------------------
[INFO] Building Maven Default Project
[INFO]    task-segment: [archetype:create] (aggregator-style)
[INFO]
----------------------------------------------------------------------------
。。。。。。。
[INFO] Velocimacro : initialization complete.
[INFO] Velocity successfully started.
[INFO] [archetype:create]
[INFO] Defaulting package to group ID: com.mycompany.app
[INFO]
------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO]
------------------------------------------------------------------------
[INFO] Failed to resolve artifact.

GroupId: org.apache.maven.archetypes
ArtifactId: maven-archetype-quickstart
Version: RELEASE

Reason: Unable to determine the release version

Try downloading the file manually from the project website.

Then, install it using the command:
    mvn install:install-file -DgroupId=org.apache.maven.archetypes
-DartifactId=maven-arch
etype-quickstart \
        -Dversion=RELEASE -Dpackaging=jar -Dfile=/path/to/file

  org.apache.maven.archetypes:maven-archetype-quickstart:jar:RELEASE

 [INFO]
------------------------------------------------------------------------
[INFO] For more information, run Maven with the -e switch
[INFO]
------------------------------------------------------------------------
[INFO] Total time: 1 second
[INFO] Finished at: Tue Apr 17 07:08:50 MDT 2007
[INFO] Final Memory: 4M/8M
[INFO]
------------------------------------------------------------------------

        请注意红色部分为错误产生的根本原因,  由于maven还处于开发过程中,开发方极有可能已经更新某个plug-in的版本,但本地plug-in metadata没有版本的信息或者没有最新版本的信息,致使maven无法下载正确的版本。同时请注意蓝色部分,这是提示的解决办法。具体步骤如下:
    1.打开网址:http://mirrors.ibiblio.org/pub/mirrors/maven2/org/apache/maven/archetypes/maven-archetype-quickstart/
    2.选择最新版本并且下载最新的“maven-archetype-quickstart-1.0-alpha-4.jar ”文件
    3.安装这个archetype到maven本地仓库。使用命令如下:mvn install:install-file -DgroupId=org.apache.maven.archtypes -Dar
tifactId=maven-archetype-quickstart -Dversion=1.0-alpha-4 -Dpackaging=jar -Dfile=c:\7000\maven\maven-archetype-quickstart-1.0-alpha-4.jar。注意-Dfile是刚下载的文件的路径。
    现在在cmd中执行mvn archetype:create -DgroupId=com.mycompany.app -DartifactId=my-app就可以创建新项目了。
posted @ 2008-11-10 23:25 小虫旺福 阅读(277) | 评论 (0)编辑 收藏

在hibernate里面调用session的delete方法以后,无论这个被删除的对象有没有被人外键引用到,都可以被删除,并且此时的外键设为null,也就是说他会自动帮我们去查看他被谁引用到了。然后把引用全部去掉后,再把自己删掉。而在JPA里面,如果调用EntityManager.remove方法时,传进去的对象,有被外键引用到,则会失败。因为JPA里面的实现就是直接执行delete语句,也不管他有没有被外键引用,此时,当然会出错了。

测试时候使用的两个类分别如下:

举的例子是部门和员工的关系。一个部门可以有多个员工。然后把部门删掉的时候,员工的部门属性就为null了,不过,按照严谨来说,还是JPA的严谨一些。这样可以防止误操作,呵呵。


部门的实体对象
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 
*/
package com.hadeslee.jpaentity;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

/**
 *
 * 
@author hadeslee
 
*/
@Entity
@Table(name 
= "JPADepartment")
public class Department implements Serializable {

    
private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy 
= GenerationType.AUTO)
    
private Long id;
    @OneToMany(mappedBy 
= "department")
    
private Set<Person> persons = new HashSet<Person>();
    
private String deptName;
    
private String description;

    
public String getDeptName() {
        
return deptName;
    }

    
public void setDeptName(String deptName) {
        
this.deptName = deptName;
    }

    
public String getDescription() {
        
return description;
    }

    
public void setDescription(String description) {
        
this.description = description;
    }
    
    
public Set<Person> getPersons() {
        
return persons;
    }

    
public void setPersons(Set<Person> persons) {
        
this.persons = persons;
    }

    
public Long getId() {
        
return id;
    }

    
public void setId(Long id) {
        
this.id = id;
    }

    @Override
    
public int hashCode() {
        
int hash = 0;
        hash 
+= (id != null ? id.hashCode() : 0);
        
return hash;
    }

    @Override
    
public boolean equals(Object object) {
        
// TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Department)) {
            
return false;
        }
        Department other 
= (Department) object;
        
if ((this.id == null && other.id != null|| (this.id != null && !this.id.equals(other.id))) {
            
return false;
        }
        
return true;
    }

    @Override
    
public String toString() {
        
return "com.hadeslee.jpaentity.Department[id=" + id + "]";
    }
}

人员的实体对象

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 
*/
package com.hadeslee.jpaentity;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

/**
 *
 * 
@author hadeslee
 
*/
@Entity
@Table(name 
= "JPAPerson")
public class Person implements Serializable {

    
private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy 
= GenerationType.AUTO)
    
private Integer id;
    
private String name;
    
private int age;
    @ManyToOne
    
private Department department;

    
public int getAge() {
        
return age;
    }

    
public void setAge(int age) {
        
this.age = age;
    }

    
public Department getDepartment() {
        
return department;
    }

    
public void setDepartment(Department department) {
        
this.department = department;
    }

    
public String getName() {
        
return name;
    }

    
public void setName(String name) {
        
this.name = name;
    }

    
public Integer getId() {
        
return id;
    }

    
public void setId(Integer id) {
        
this.id = id;
    }

    @Override
    
public int hashCode() {
        
int hash = 0;
        hash 
+= (id != null ? id.hashCode() : 0);
        
return hash;
    }

    @Override
    
public boolean equals(Object object) {
        
// TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Person)) {
            
return false;
        }
        Person other 
= (Person) object;
        
if ((this.id == null && other.id != null|| (this.id != null && !this.id.equals(other.id))) {
            
return false;
        }
        
return true;
    }

    @Override
    
public String toString() {
        
return "com.hadeslee.jpaentity.Person[id=" + id + "]";
    }
}


由于JPA是不需要配置的,代码里面已经包括了注释,所以下面附上Hibernate的映射文件,为了使数据库里面更清楚一些,所以两者使用的表不是同一张表,JPA的表是带JPA前缀的,用@Table这个注释声明了这一点。

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC
  "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>
<hibernate-mapping package="com.hadeslee.jpaentity">
    
<class name="Department" table="Department">
        
<id name="id" column="departId" type="long">
            
<generator class="native"/>
        
</id>
        
<property name="deptName"/>
        
<property name="description"/>
        
<set name="persons">
            
<key column="deptId"/>
            
<one-to-many class="Person"/>
        
</set>
    
</class>
    
<class name="Person" table="Person">
        
<id name="id" column="personId" type="long">
            
<generator class="native"/>
        
</id>
        
<property name="name"/>
        
<property name="age"/>
        
<many-to-one name="department" column="deptId" class="Department"/>
     
</class>
</hibernate-mapping>

调用JPA的代码如下:

 EntityManagerFactory emf = Persistence.createEntityManagerFactory("TestSSH1PU2");
        EntityManager em 
= emf.createEntityManager();
        em.getTransaction().begin();
        com.hadeslee.jpaentity.Person p 
= new com.hadeslee.jpaentity.Person();
        p.setAge(
26);
        p.setName(
"千里冰封");

        com.hadeslee.jpaentity.Department dept 
= em.find(com.hadeslee.jpaentity.Department.class, Long.valueOf("3"));
        System.out.println(
"找到的dept=" + dept);
        em.remove(dept);
        em.getTransaction().commit();

调用hibernate的代码如下:

Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.getTransaction().begin();
        Department dept 
= (Department) session.load(Department.class2);
        session.delete(dept);
        session.getTransaction().commit();

最后发现是JPA是不能删除的,而hibernate这边的调用可以删除,一开始我还以为是toplink的实现问题,后来特意把实现改成hibernate的实现,也同样。所以有可能是JPA的要求必须得这样做,不能替我们自动完成一些东西,是利于安全。这可能就是标准和流行的差别吧。呵呵。
posted @ 2008-11-10 23:24 小虫旺福 阅读(260) | 评论 (0)编辑 收藏

在维护系统时,难免会时不时地跟代码再次打些交道。今天想再操刀做个小工具时,居然不太记得了log4j的配置,不得不从apache再重新down了相关的jar与DOC,匆匆看看了一下,快点写下来,日后肯定还用得着,同时也希望对网友们有用。 

    Log4j基本上已经是java里的首选日志工具了,它主要由三部分组成:Loggers, Appenders和Layouts (注意后面都加了s啦,顾名思义一个配置中可以分别允许有多个此类对象存在,后面将详细介绍)。

    Loggers-用来定义日志消息的类型及级别;

    Appenders-用来定义日志消息的输出终端;

    Layouts-用来定义日志消息的输出格式。

  
   
Logger

    Loggers层次:

    logger的名字是大小写敏感。

规则-如果类P的名字是另一个类C的名字的前缀,且P与C之间以“.”号连接起来,那么称P为祖先层次;如果层次A与其子层次之间没有任何父层次,则认为层次A为父层次。

    例如,org.apache.log4j是org.apache.log4j.Logger的父层次;而org.apache是org.apache.log4j与org.apache.log4j.Logger的祖先层次。

    另外,注意log4j中有个默认的root级别的logger,在所有logger中,它是最高级别,其它所有logger均继承于root,root有以下二个特性:

    1. 它总是存在的。

    2. 它不能通过名字直接获取其实例(root实例可以通过类Logger的静态方法Logger.getRootLogger获得,而其它logger则可以直接通过名字来获取Logger.getLogger)。

    关于Loggers中的级别:

   对每个logger,可以指定其级别,在系统org.apache.log4j.Level中,已经定义了五个级别,分别为debug, info, warn, error, fatal。

规则-设当前logger为X,从X开始往X的父类方向开始算(包括X本身),直到名为root的logger,第一个不为null的级别值就是X的级别值。

    日志显示:  
    
级别的定义是为了过滤性地选择日志。

规则-若当前请方式级别为P,而当前的logger的级别为Q,当且仅当在P>=Q的情况下,日志信息才能显示。


   
关于日志中级别的关系为:DEBUG < INFO < WARN < ERROR < FATAL
    关于此规则的说明,有以下代码为实例:   

// get a logger instance named "com.foo"

   Logger logger = Logger.getLogger("com.foo");

   // Now set its level. Normally you do not need to set the

   // level of a logger programmatically. This is usually done

   // in configuration files.

   logger.setLevel(Level.INFO);

   Logger barlogger = Logger.getLogger("com.foo.Bar");

   // This request is enabled, because WARN >= INFO.

  logger.warn("Low fuel level.");

   // This request is disabled, because DEBUG < INFO.

   logger.debug("Starting search for nearest gas station.");

   // The logger instance barlogger, named "com.foo.Bar",

   // will inherit its level from the logger named

   // "com.foo" Thus, the following request is enabled

   // because INFO >= INFO.

   barlogger.info("Located nearest gas station.");

   // This request is disabled, because DEBUG < INFO.

   barlogger.debug("Exiting gas station search");

Appenders与Layouts

Appender正如前面所述,是用来定义日志信息的输出终端,最觉的输出终端有console与file了,另外还有其它如GUI components, JMS, NT Event Loggers, remote socket servers等等。

    Appender也有类似继承的原则,即当前logger的appender包括其它父类的appender。这样就会出现一个logger可能拥有多个appender了,在现实中看来,就是log4j的日志信息可以同进输出到console, file等等终端了。当然,为了不使此appender恶性叠加,可以通过设置additivity标志来阻止继承。

    规则-若当前logger为C,则C拥有包括其自己及其父类的所有appender。另外,若C的父logger为P,且P的additivity标志已经设置成为false,则C只拥有自己及P的appender了,而P则只能拥有本身的appender。

    以下表格可以清晰说明此规则:
    
Logger
Name
Added
Appenders
Additivity
Flag
Output Targets Comment
root A1 not applicable A1 The root logger is anonymous but can be accessed with the Logger.getRootLogger() method. There is no default appender attached to root.
x A-x1, A-x2 true A1, A-x1, A-x2 Appenders of "x" and root.
x.y none true A1, A-x1, A-x2 Appenders of "x" and root.
x.y.z A-xyz1 true A1, A-x1, A-x2, A-xyz1 Appenders in "x.y.z", "x" and root.
security A-sec false A-sec No appender accumulation since the additivity flag is set to false.
security.access none true A-sec Only appenders of "security" because the additivity flag in "security" is set to false.
    
    
    对于layout,也正如前面所述,是用来定义日志信息的输出格式,它的与C语言中
printf函数的格式定义基本相似,本人对printf中的格式参数不太熟悉,总感觉有些复杂,一般是平时看到自己认为有用的格式就记一下,到时直接搬过来。如

log4j.appender.R.layout.ConversionPattern=--->%-d{yyyy-MM-dd HH:mm:ss} [%5p]%l - %m%n

时,日志信息格式为:

--->2008-07-11 01:13:40 [ INFO]com.test.Log4jTest.main(Log4jTest.java:27) - Exiting application.

    
    好啦,现在log4j的理论很肤浅地扯了一下,现在可以开始配置了。

   配置:   

    Log4j
的配置可以通过加载Java的properties配置文件或者XML文件来完成。

    Log4j默认的配置为,通过读取系统变量log4j.configuration来找到配置文件,当然变量的默认值为log4j.properties,所以若没有设置此系统变量,可以直接将配置文件命名为log4j.properties,然后放到类路径下即可。另外,若想引用通过其它配置文件,则可以通过

    Loader.getResource(java.lang.String)来读取指定的配置文件。

    其它:

    1. 由于有了log4j中的级别继承机制,所以可以很方便地过滤信息了,不仅可以很方便地限制日志的输出量,也可以同时将日志输出到不同的终端。
    另外,因为在java文件中,文件的物理层次关系也是直接通过“.”符号来控制的,且在很在程度上这个物理层次也决定了文件的逻辑层次,所以我们在当前文件中获取logger时,可以直接通过当前文件的类名来获取,如:
    
    static Logger logger = Logger.getLogger(MyApp.class);
    这样,在过滤消息时就很简单了,简单示例如下:
    在配置文件中有
    log4j.rootLogger=ERROR,stdout,R
    log4j.category.com.db=DEBUG
    log4j.category.com.i18n=INFO
    log4j.category.com.zyx=fatal

    默认的root logger的日志级别为Error,根据级别关系这个级别也相当高了,这样可以减少系统中日志的输出量,但有些地方可能得输出更详细信息,如数据库部分,所以可以将com.db设置成了debug。另外,我在com.zyx下,我只想看到类型为fatal的日志,也可以如上所设。

 

    2. log4j.rootLogger=ERROR,stdout, ROLLING_FILE这个定义表示root logger的日志级别为Error,后面的stdout, ROLLING_FILE表示此root有二个appender,通常可以通过这样来定义日志可以同时向多个终端输出,因为子logger可以继承所有父logger的appender.

    如我可以通过以下定义将日志同时往console及file输出:

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=--->%-d{yyyy-MM-dd HH:mm:ss} [%5p]%l - %m%n

 

log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender

log4j.appender.ROLLING_FILE.File=myapp.log

log4j.appender.ROLLING_FILE.Append=true

log4j.appender.ROLLING_FILE.MaxFileSize=1024KB

log4j.appender.ROLLING_FILE.MaxBackupIndex=10

log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout

log4j.appender.ROLLING_FILE.layout.ConversionPattern==[slf5s.start]%d{DATE}[slf5s.DATE]%n"

   %p[slf5s.PRIORITY]%n%x[slf5s.NDC]%n%t[slf5s.THREAD]%n"

   %c[slf5s.CATEGORY]%n%l[slf5s.LOCATION]%n%m[slf5s.MESSAGE]%n%n

 

    马马虎虎总结了一下,但也花费了二个多小时,呵呵!

posted @ 2008-11-10 23:24 小虫旺福 阅读(264) | 评论 (0)编辑 收藏