<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆:93 文章:11 評(píng)論:22 引用:0
    首頁(yè) 發(fā)新隨筆
    發(fā)新文章 聯(lián)系 聚合管理

    2011年5月31日

    --查詢表空間、表空間大小及表空間對(duì)應(yīng)物理路徑

    select a.tablespace_name,b.file_name,a.block_size,a.block_size,b.bytes/1024

    /1024 "Sum MB" from dba_tablespaces a,dba_data_files b where a.tablespace_name=b.tablespace_name;

    --查詢表空間使用情況

      SELECT UPPER(F.TABLESPACE_NAME) "表空間名",

      D.TOT_GROOTTE_MB "表空間大小(M)",

      D.TOT_GROOTTE_MB - F.TOTAL_BYTES "已使用空間(M)",

      TO_CHAR(ROUND((D.TOT_GROOTTE_MB - F.TOTAL_BYTES) / D.TOT_GROOTTE_MB * 100,2),'990.99') || '%' "使用比",

      F.TOTAL_BYTES "空閑空間(M)",

      F.MAX_BYTES "最大塊(M)"

      FROM (SELECT TABLESPACE_NAME,

      ROUND(SUM(BYTES) / (1024 * 1024), 2) TOTAL_BYTES,

      ROUND(MAX(BYTES) / (1024 * 1024), 2) MAX_BYTES

      FROM SYS.DBA_FREE_SPACE

      GROUP BY TABLESPACE_NAME) F,

      (SELECT DD.TABLESPACE_NAME,

       ROUND(SUM(DD.BYTES) / (1024 * 1024), 2) TOT_GROOTTE_MB

      FROM SYS.DBA_DATA_FILES DD

      GROUP BY DD.TABLESPACE_NAME) D

      WHERE D.TABLESPACE_NAME = F.TABLESPACE_NAME

      ORDER BY 1;

    --查詢表空間的free space

      select tablespace_name,

      count(*) as extends,

      round(sum(bytes) / 1024 / 1024, 2) as MB,

      sum(blocks) as blocks

      from dba_free_space

    group by tablespace_name;

     

    --查詢表空間的總?cè)萘?/h3>

      select tablespace_name, sum(bytes) / 1024 / 1024 as MB

      from dba_data_files

      group by tablespace_name;

     

     

    --查詢表空間使用率

      select total.tablespace_name,

      round(total.MB, 2) as Total_MB,考試大論壇

      round(total.MB - free.MB, 2) as Used_MB,

      round((1 - free.MB / total.MB) * 100, 2) || '%' as Used_Pct

      from (select tablespace_name, sum(bytes) / 1024 / 1024 as MB

      from dba_free_space

      group by tablespace_name) free,

      (select tablespace_name, sum(bytes) / 1024 / 1024 as MB

      from dba_data_files

      group by tablespace_name) total

      where free.tablespace_name = total.tablespace_name;

     

     

    1.查找當(dāng)前表級(jí)鎖的SQL如下:

    select sess.sid,

        sess.serial#,

        lo.oracle_username,

        lo.os_user_name,

        ao.object_name,

        lo.locked_mode

        from v$locked_object lo,

        dba_objects ao,

        v$session sess

    where ao.object_id = lo.object_id and lo.session_id = sess.sid;

     

    2.殺掉鎖表進(jìn)程:

    alter system kill session '436,35123';

     

    3.RAC環(huán)境中鎖查找:

    SELECT inst_id,DECODE(request,0,'Holder: ','Waiter: ')||sid sess,

            id1, id2, lmode, request, type,block,ctime

    FROM GV$LOCK

    WHERE (id1, id2, type) IN

           (SELECT id1, id2, type FROM GV$LOCK WHERE request>0)

    ORDER BY id1, request;

      

     

     

    4.監(jiān)控當(dāng)前數(shù)據(jù)庫(kù)誰(shuí)在運(yùn)行什么SQL語(yǔ)句

    select osuser, username, sql_text 

    from  v$session a, v$sqltext b

    where  a.sql_address =b.address order by address, piece;

     

     

     

    5.找使用CPU多的用戶session

    select a.sid,spid,status,substr(a.program,1,40) prog, a.terminal,osuser,value/60/100 value

    from  v$session a,v$process b,v$sesstat c

    where  c.statistic#=12 and 

           c.sid=a.sid and 

           a.paddr=b.addr 

           order by value desc;

     

     

    6.查看死鎖信息

    SELECT (SELECT username

              FROM v$session

             WHERE SID = a.SID) blocker, a.SID, 'is blocking',

           (SELECT username

              FROM v$session

             WHERE SID = b.SID) blockee, b.SID

      FROM v$lock a, v$lock b

     WHERE a.BLOCK = 1 AND b.request > 0 AND a.id1 = b.id1 AND a.id2 = b.id2;

     

     

    7.具有最高等待的對(duì)象

    SELECT   o.OWNER,o.object_name, o.object_type, a.event,

             SUM (a.wait_time + a.time_waited) total_wait_time

        FROM v$active_session_history a, dba_objects o

       WHERE a.sample_time BETWEEN SYSDATE - 30 / 2880 AND SYSDATE

         AND a.current_obj# = o.object_id

    GROUP BY o.OWNER,o.object_name, o.object_type, a.event

    ORDER BY total_wait_time DESC;

     

     

    SELECT   a.session_id, s.osuser, s.machine, s.program, o.owner, o.object_name,

             o.object_type, a.event,

             SUM (a.wait_time + a.time_waited) total_wait_time

        FROM v$active_session_history a, dba_objects o, v$session s

       WHERE a.sample_time BETWEEN SYSDATE - 30 / 2880 AND SYSDATE

         AND a.current_obj# = o.object_id

         AND a.session_id = s.SID

    GROUP BY o.owner,

             o.object_name,

             o.object_type,

             a.event,

             a.session_id,

             s.program,

             s.machine,

             s.osuser

    ORDER BY total_wait_time DESC;

     

     

     

    8.查詢當(dāng)前連接會(huì)話數(shù)

    select s.value,s.sid,a.username

    from

    v$sesstat S,v$statname N,v$session A

    where

    n.statistic#=s.statistic# and

    name='session pga memory'

    and s.sid=a.sid

    order by s.value;

     

     

     

    9.等待最多的用戶

    SELECT   s.SID, s.username, SUM (a.wait_time + a.time_waited) total_wait_time

        FROM v$active_session_history a, v$session s

       WHERE a.sample_time BETWEEN SYSDATE - 30 / 2880 AND SYSDATE

    GROUP BY s.SID, s.username

    ORDER BY total_wait_time DESC;

     

     

     

    10.等待最多的SQL

    SELECT   a.program, a.session_id, a.user_id, d.username, s.sql_text,

             SUM (a.wait_time + a.time_waited) total_wait_time

        FROM v$active_session_history a, v$sqlarea s, dba_users d

       WHERE a.sample_time BETWEEN SYSDATE - 30 / 2880 AND SYSDATE

         AND a.sql_id = s.sql_id

         AND a.user_id = d.user_id

    GROUP BY a.program, a.session_id, a.user_id, s.sql_text, d.username;

     

     

     

    11.查看消耗資源最多的SQL

    SELECT hash_value, executions, buffer_gets, disk_reads, parse_calls

    FROM V$SQLAREA

    WHERE buffer_gets > 10000000 OR disk_reads > 1000000

    ORDER BY buffer_gets + 100 * disk_reads DESC;

     

     

     

    12.查看某條SQL語(yǔ)句的資源消耗

    SELECT hash_value, buffer_gets, disk_reads, executions, parse_calls

    FROM V$SQLAREA

    WHERE hash_Value = 228801498 AND address = hextoraw('CBD8E4B0');

     

     

    13.查詢會(huì)話執(zhí)行的實(shí)際SQL

    SELECT   a.SID, a.username, s.sql_text

        FROM v$session a, v$sqltext s

       WHERE a.sql_address = s.address

         AND a.sql_hash_value = s.hash_value

         AND a.status = 'ACTIVE'

    ORDER BY a.username, a.SID, s.piece;

     

     

    14.顯示正在等待鎖的所有會(huì)話

    SELECT * FROM DBA_WAITERS;

     

    DDL

    --------------------------------------------------------------

    /*注意點(diǎn):

     

    1.如果在PL/SQL 等工具里打開(kāi)的話,直接修改下面的代碼中[斜體加粗部分]執(zhí)行

     

    2.確保路徑存在,比如【D:\oracle\oradata\Oracle9i\】也就是你要保存文件的路徑存在

     

    /*分為四步 */

     

    /*第1步:創(chuàng)建臨時(shí)表空間  */

     

    create temporary tablespace user_temp 

     

    tempfile 'D:\oracle\oradata\Oracle9i\user_temp.dbf'

     

    size 50m 

     

    autoextend on 

     

    next 50m maxsize 20480m 

     

    extent management local; 

     

     

     

    /*第2步:創(chuàng)建數(shù)據(jù)表空間  */

     

    create tablespace user_data 

     

    logging 

     

    datafile 'D:\oracle\oradata\Oracle9i\user_data.dbf'

     

    size 50m 

     

    autoextend on 

     

    next 50m maxsize 20480m 

     

    extent management local; 

     

     

     

    /*第3步:創(chuàng)建用戶并指定表空間  */

     

    create user username identified by password 

     

    default tablespace user_data 

     

    temporary tablespace user_temp; 

     

     

     

    /*第4步:給用戶授予權(quán)限  */

     

    grant connect,resource,dba to username; 

    posted @ 2014-03-03 15:48 redcoatjk 閱讀(346) | 評(píng)論 (0)編輯 收藏
     
    摘自: http://www.douban.com/note/235086917/
    http://jackleechina.iteye.com/blog/1595397

    為什么一般要采用事件監(jiān)聽(tīng)而不是直接對(duì)元素的事件屬性(如:onclick、onmouseover)賦值?

    原來(lái)用事件屬性只能賦值一種方法,即:

    button1.onclick = function() { alert(1); };
    button1.onclick = function() { alert(2); };

    這樣后面的賦值語(yǔ)句就將前面的onclick屬性覆蓋了

    而使用添加事件監(jiān)聽(tīng)的方式就可以實(shí)現(xiàn)并行。特別是當(dāng)團(tuán)隊(duì)合作時(shí),事件并行的需求增多,比如:監(jiān)聽(tīng)document對(duì)象的鼠標(biāo)事件或者window對(duì)象的載入事件等。使用事件屬性則很容易造成事件覆蓋掉

    使用事件監(jiān)聽(tīng)有兩種方式:attachEvent和addEventListener

    attachEvent與addEventListener區(qū)別
    適應(yīng)的瀏覽器版本不同,同時(shí)在使用的過(guò)程中要注意
    attachEvent方法 按鈕onclick
    addEventListener方法 按鈕click
    attachEvent方法, (ie系列)
    addEventListener方法 Mozilla系列

    例子如下:
     1<!DOCTYPE html>
     2<html>
     3
     4<SCRIPT LANGUAGE="JavaScript">
     5function method1(){
     6    alert("method1");
     7}

     8function method2(){
     9    alert("method2");
    10}

    11function method3(){
    12    alert("method3");
    13}

    14
    </SCRIPT>
    15<body>
    16<input type="button"  value="dom 元素事件屬性綁定的按鈕" id="button1"/>
    17<input type="button"  value="IE瀏覽器: attachEvent進(jìn)行事件綁定的按鈕" id="btn1"/>
    18<input type="button"  value="火狐瀏覽器: addEventListener進(jìn)行事件綁定的按鈕" id="btn2"/>
    19
    20<SCRIPT LANGUAGE="JavaScript">
    21     /**方法一: 使用元素的事件屬性. [這種方式事件只可綁定一次,最后綁定的執(zhí)行]**/
    22     button1.onclick = function() { alert("1-1"); };
    23     button1.onclick = function() { alert("1-2"); };
    24     /**方法二: 使用attachEvent注冊(cè)事件. 格式如下object.attachEvent(event,function);**/
    25   var btn1Obj = document.getElementById("btn1");
    26    btn1Obj.attachEvent("onclick", method1);
    27   btn1Obj.attachEvent("onclick", method2);
    28    btn1Obj.attachEvent("onclick", method3);
    29     /**方法三: addEventListener. 格式如下element.addEventListener(type,listener,useCapture);**/
    30    var btn2Obj = document.getElementById("btn2");
    31    btn2Obj.addEventListener("click",method1,false);
    32    btn2Obj.addEventListener("click",method2,false);
    33    btn2Obj.addEventListener("click",method3,false);
    34    //執(zhí)行順序?yàn)閙ethod1->method2->method3
    35
    </SCRIPT>
    36<br/>attachEvent按照注冊(cè)倒敘執(zhí)行:    執(zhí)行順序?yàn)閙ethod3->method2->method1 
    37<br/>addEventListener按照注冊(cè)順序執(zhí)行:    執(zhí)行順序?yàn)閙ethod1->method2->method3 
    38</body>
    39</html>

    相關(guān)衍生閱讀:

    JavaScript欲速則不達(dá)——基本處理事件詳解和阻止事件傳播

    posted @ 2013-11-04 14:22 redcoatjk 閱讀(438) | 評(píng)論 (0)編輯 收藏
     
         摘要: 摘自http://zhangjunhd.blog.51cto.com/113473/20629/ 1.Servlet過(guò)濾器 1.1 什么是過(guò)濾器 過(guò)濾器是一個(gè)程序,它先于與之相關(guān)的servlet或JSP頁(yè)面運(yùn)行在服務(wù)器上。過(guò)濾器可附加到一個(gè)或多個(gè)servlet或JSP頁(yè)面上,并且可以檢查進(jìn)入這些資源的請(qǐng)求信息。在這之后,過(guò)濾器可以作如下的選擇: ①以常規(guī)的方式調(diào)用資源(即,調(diào)...  閱讀全文
    posted @ 2013-04-16 17:28 redcoatjk 閱讀(264) | 評(píng)論 (0)編輯 收藏
     
         摘要: 摘自 http://www.sandzhang.com/blog/2010/04/07/mysql-show-status-explained-detail/ 要查看MySQL運(yùn)行狀態(tài),要優(yōu)化MySQL運(yùn)行效率都少不了要運(yùn)行show status查看各種狀態(tài),下面是參考官方文檔及網(wǎng)上資料整理出來(lái)的中文詳細(xì)解釋:  如有問(wèn)題,歡迎指正 狀態(tài)名 作用域 ...  閱讀全文
    posted @ 2012-09-05 15:33 redcoatjk 閱讀(2114) | 評(píng)論 (1)編輯 收藏
     
         摘要: 代碼中反復(fù)開(kāi)關(guān)自動(dòng)提交沒(méi)有必要. 其他方面寫(xiě)得還是很不錯(cuò)的.清晰.摘自 http://wangqinqin.iteye.com/blog/547277  PreparedStatement: 1) addBatch()將一組參數(shù)添加到PreparedStatement對(duì)象內(nèi)部。 2) executeBatch()將一批參數(shù)提交給數(shù)據(jù)庫(kù)來(lái)執(zhí)行,如果全部命令執(zhí)行成功...  閱讀全文
    posted @ 2012-07-20 15:04 redcoatjk 閱讀(18635) | 評(píng)論 (1)編輯 收藏
     
    摘自 http://neoremind.net/2010/12/preparedstatement_diff/

    JDBC中Statement與PreparedStatement的區(qū)別

    1. statement每次執(zhí)行sql語(yǔ)句,相關(guān)數(shù)據(jù)庫(kù)都要執(zhí)行sql語(yǔ)句的編譯;preparedstatement是預(yù)編譯的, 采用Cache機(jī)制(預(yù)編譯語(yǔ)句,放在Cache中,下次執(zhí)行相同SQL語(yǔ)句時(shí),則可以直接從Cache中取出來(lái),有利于sql生成查詢計(jì)劃。),對(duì)于批量處理可以大大提高效率. 也叫JDBC存儲(chǔ)過(guò)程。

    例如,如果要執(zhí)行兩條sql語(yǔ)句

    SELECT colume FROM TABLE WHERE colume=1;
    SELECT colume FROM TABLE WHERE colume=2;

    會(huì)生成兩個(gè)執(zhí)行計(jì)劃

    一千個(gè)查詢就生成一千個(gè)執(zhí)行計(jì)劃!

    PreparedStatement用于使用綁定變量重用執(zhí)行計(jì)劃

    SELECT colume FROM TABLE WHERE colume=:x;

    通過(guò)set不同數(shù)據(jù)只需要生成一次執(zhí)行計(jì)劃,可以重用

    是否使用綁定變量對(duì)系統(tǒng)影響非常大,生成執(zhí)行計(jì)劃極為消耗資源

    兩種實(shí)現(xiàn) 速度差距可能成百上千倍

    后者使用了PreparedStatement對(duì)象,而前者是普通的Statement對(duì)象。PreparedStatement對(duì)象不僅包含了SQL語(yǔ)句,而且大多數(shù)情況下這個(gè)語(yǔ)句已經(jīng)被預(yù)編譯過(guò),因而當(dāng)其執(zhí)行時(shí),只需DBMS運(yùn)行SQL語(yǔ)句,而不必先編譯。當(dāng)你需要執(zhí)行Statement對(duì)象多次的時(shí)候,PreparedStatement對(duì)象將會(huì)大大降低運(yùn)行時(shí)間,當(dāng)然也加快了訪問(wèn)數(shù)據(jù)庫(kù)的速度

    這種轉(zhuǎn)換也給你帶來(lái)很大的便利,不必重復(fù)SQL語(yǔ)句的句法,而只需更改其中變量的值,便可重新執(zhí)行SQL語(yǔ)句。選擇PreparedStatement對(duì)象與否,在于相同句法的SQL語(yǔ)句是否執(zhí)行了多次,而且兩次之間的差別僅僅是變量的不同。如果僅僅執(zhí)行了一次的話,在對(duì)數(shù)據(jù)庫(kù)只執(zhí)行一次性存取的時(shí)侯,用 Statement 對(duì)象進(jìn)行處理,PreparedStatement 對(duì)象的開(kāi)銷比Statement大,對(duì)于一次性操作并不會(huì)帶來(lái)額外的好處。

    2. PrepareStatement中執(zhí)行的SQL語(yǔ)句中是可以帶參數(shù)的,也就是說(shuō)可以替換變量,盡量采用使用?號(hào)的方式傳遞參數(shù),增加代碼的可讀性又可以預(yù)編譯加速;而Statement則不可以。

    3. 防止SQL注入。在SQL中包含特殊字符或SQL的關(guān)鍵字(如:’ or 1 or ‘)時(shí),Statement將出現(xiàn)不可預(yù)料的結(jié)果(出現(xiàn)異常或查詢的結(jié)果不正確),可用PreparedStatement來(lái)解決。

    SQL注入或者說(shuō)SQL注入攻擊就是利用Statement的漏洞完成的,例如用個(gè)用戶登錄,那么form表單有用戶名和密碼
    那么我提交時(shí),在用戶名輸入框內(nèi) 輸入 “aaa’ or ’a’=’a” 密碼框隨便輸入,那么這樣意味著 sql的
    查詢語(yǔ)言就是 “select * from 表 where 用戶名=’aaa’ or ’a’=’a’ and 密碼=’123’  ”,這樣查詢出來(lái)所有的數(shù)據(jù)或者是混亂。那么不被授權(quán)的用戶照樣可以登錄,豈不是被黑了?!實(shí)際中現(xiàn)在java程序員早都不用這種方式寫(xiě)查詢了,一般都用PreparedStatement來(lái)查詢,或干脆就用hibernate之類的持久層框架,這樣通過(guò)sql注入就無(wú)從談起了。
    posted @ 2012-07-20 11:14 redcoatjk 閱讀(4420) | 評(píng)論 (2)編輯 收藏
     
    摘自:http://ryxxlong.iteye.com/blog/552884

    如何修改mysql root密碼
      忘記MySQL ROOT密碼是在MySQ使用中很常見(jiàn)的問(wèn)題,可是有很多朋友并不會(huì)重置ROOT密碼,那叫苦啊,特寫(xiě)此文章與大家交流:

    1、編輯MySQL的配置文件:my.ini
    一般在MySQL安裝目錄下有my.ini即MySQL的配置文件。
    在此配置文件的最后添加如下一行:
    skip-grant-tables
    保存退出編輯。

    2、然后重啟MySQL服務(wù)
    在命令行下執(zhí)行:
    net stop MySQL
    net start MySQL

    3、設(shè)置新的ROOT密碼
    然后用命令提示符cd到對(duì)應(yīng)安裝目錄的bin下執(zhí)行:
    MySQL -u root -p MySQL或mysql -u root -p
    直接回車無(wú)需密碼即可進(jìn)入數(shù)據(jù)庫(kù)了。
    此時(shí),在命令行下執(zhí)行 use mysql;
    現(xiàn)在我們執(zhí)行如下語(yǔ)句把root密碼更新為:
    update user set password=PASSWORD("root") where user='root';
    (注意:此時(shí)不用使用mysqladmin -u root -p password '你的新密碼'這條命令修改密碼,因?yàn)?skip-grant-tables'配置,
    不信的話,你可以試用一下,它肯定會(huì)報(bào)如下所示的錯(cuò)誤:
    F:\Documents and Settings\long>mysqladmin -u root -p password 'root'
    Enter password:
    Warning: single quotes were not trimmed from the password by your command
    line client, as you might have expected.
    mysqladmin:
    You cannot use 'password' command as mysqld runs
     with grant tables disabled (was started with --skip-grant-tables).
    Use: "mysqladmin flush-privileges password '*'" instead)
    exit 退出MySQL。

    4、還原配置文件并重啟服務(wù)

    然后修改MySQL配置文件把剛才添加的那一行'skip-grant-tables'刪除。
    再次重起MySQL服務(wù),密碼修改完畢。
    用新密碼root試一下吧,又能登入重新進(jìn)入mysql了?



    附mysql修改密碼的一些方法:
    1. 用MYSQL的grant語(yǔ)句,例如
    mysql -h hostname –u root 命令登錄到mysqld server 用grant 命令改變口令:
    mysql -h 192.168.1.101 -u root
    上邊的192.168.1.101 是偶的mysqld 運(yùn)行機(jī)器,你換成自己的,這樣登錄上去,就可以修改密碼了,
    其實(shí)沒(méi)必要這么麻煩,直接mysql -u root就可以了。
    GRANT ALL ON *.* TO 'root'@'localhost' IDENTIFIED BY 'root' WITH GRANT OPTION

    2. mysqladmin -u 用戶名 -p 舊密碼 password 新密碼
    例1:給root 加個(gè)密碼root。首先進(jìn)入cmd中,然后鍵入
    以下命令,至于在CMD下能否使用mysqladmin,
    就要看你的Windows環(huán)境變量PATH中是否添加“E:\Program Files\MySQL\MySQL Server 5.1\bin;”(請(qǐng)改為你自己的安裝路徑)了。)
    mysqladmin -u root password root
    注:因?yàn)殚_(kāi)始時(shí)root 沒(méi)有密碼,所以-p 舊密碼一項(xiàng)就可以省略了。
    例2:再將root 的密碼改為admin。
    mysqladmin –u root -proot password admin(注意-p 不要和后面的密碼分
    開(kāi)寫(xiě),要寫(xiě)在一起,不然會(huì)出錯(cuò),錯(cuò)誤如下所示:
    F:\Documents and Settings\long>mysqladmin -u root -p root password admin
    Enter password: ****
    mysqladmin: Unknown command: 'root')
    當(dāng)然你也可以這樣寫(xiě):mysqladmin –u root -p password admin回車,
    然后再輸入你的舊密碼,這樣也是完全也可以的,看你的愛(ài)好了.
    例3:再將root用戶的密碼去掉.
    F:\Documents and Settings\long>mysqladmin -u root -p password  ;
    Enter password: root
    此時(shí),root用戶又沒(méi)有密碼了.可以通過(guò)下面的方法設(shè)置:
    F:\Documents and Settings\long>mysql -u root
    mysql>set password for 'root'@'localhost'=password('root');(語(yǔ)法:SET PASSWORD FOR '用戶名'@'主機(jī)' = PASSWORD('密碼'))
    mysql>set password for 'root'@'%'=password('root');
    //本條可選,這是在配置mysql數(shù)據(jù)庫(kù),如果你選擇了允許root通過(guò)遠(yuǎn)程登錄進(jìn)來(lái)時(shí),你在mysql數(shù)據(jù)庫(kù)下的user表中,
    use mysql;
    select * from user;可以看到有兩條記錄,如果你沒(méi)有配置這一項(xiàng)的話,只會(huì)第一條記錄!
    Host                    User     Password
    'localhost', 'root', '*9C9F4927129ECC3209D8550DC8B67156FDBF9418', ...
    '%', 'root', '*81F5E21E35407D884A6CD4A731AEBFB6AF209E1B', ...
    通過(guò)以上設(shè)置,root的密碼將變?yōu)閞oot這樣就完成了根用戶root密碼的設(shè)置工作。

    3. use mysql;
     update user set password =password('yourpass') where user='root'

    (注:下面的這些方法我本人沒(méi)有試過(guò),不知對(duì)不對(duì),我只是轉(zhuǎn)載了一下:)
    下面的方法都在mysql提示符下使用,且必須有mysql的root權(quán)限:
    方法4
    mysql> INSERT INTO mysql.user (Host,User,Password)
    VALUES('%','jeffrey',PASSWORD('biscuit'));
    mysql> FLUSH PRIVILEGES
    確切地說(shuō)這是在增加一個(gè)用戶,用戶名為jeffrey,密碼為biscuit。
    在《mysql中文參考手冊(cè)》里有這個(gè)例子,所以我也就寫(xiě)出來(lái)了。
    注意要使用PASSWORD函數(shù),然后還要使用FLUSH PRIVILEGES。

    方法5
    和方法三一樣,只是使用了REPLACE語(yǔ)句
    mysql> REPLACE INTO mysql.user (Host,User,Password)
    VALUES('%','jeffrey',PASSWORD('biscuit'));
    mysql> FLUSH PRIVILEGES

    方法6
    使用SET PASSWORD語(yǔ)句,
    mysql> SET PASSWORD FOR jeffrey@"%" = PASSWORD('biscuit');
    你也必須使用PASSWORD()函數(shù),
    但是不需要使用FLUSH PRIVILEGES。


    方法7
    使用GRANT ... IDENTIFIED BY語(yǔ)句
    mysql> GRANT USAGE ON *.* TO jeffrey@"%" IDENTIFIED BY 'biscuit';
    這里PASSWORD()函數(shù)是不必要的,也不需要使用FLUSH PRIVILEGES。

    注:mysql 新設(shè)置用戶或更改密碼后需用flush privileges刷新MySQL的系統(tǒng)權(quán)限相關(guān)表,
    否則會(huì)出現(xiàn)拒絕訪問(wèn),還有一種方法,就是重新啟動(dòng)mysql服務(wù)器,來(lái)使新設(shè)置生效。

    posted @ 2012-07-19 10:54 redcoatjk 閱讀(328) | 評(píng)論 (0)編輯 收藏
     

    怎么查看端口占用情況?

           開(kāi)始--運(yùn)行--cmd 進(jìn)入命令提示符 輸入netstat -ano 即可看到所有連接的PID 之后在任務(wù)管理器中找到這個(gè)PID所對(duì)應(yīng)的程序如果任務(wù)管理器中沒(méi)有PID這一項(xiàng),可以在任務(wù)管理器中選"查看"-"選擇列"

            經(jīng)常,我們?cè)趩?dòng)應(yīng)用的時(shí)候發(fā)現(xiàn)系統(tǒng)需要的端口被別的程序占用,如何知道誰(shuí)占有了我們需要的端口,很多人都比較頭疼,下面就介紹一種非常簡(jiǎn)單的方法,希望對(duì)大家有用

    假如我們需要確定誰(shuí)占用了我們的9050端口

    1、Windows平臺(tái)
    在windows命令行窗口下執(zhí)行:

    C:\>netstat -aon|findstr "9050"

    TCP 127.0.0.1:9050 0.0.0.0:0 LISTENING 2016


    看到了嗎,端口被進(jìn)程號(hào)為2016的進(jìn)程占用,繼續(xù)執(zhí)行下面命令:

    C:\>tasklist|findstr "2016"

    tor.exe 2016 Console 0 16,064 K

    很清楚吧,tor占用了你的端口。

    posted @ 2012-06-13 13:51 redcoatjk 閱讀(258) | 評(píng)論 (0)編輯 收藏
     
    JSON 即 JavaScript Object Natation,它是一種輕量級(jí)的數(shù)據(jù)交換格式,非常適合于服務(wù)器與 JavaScript 的交互。本文將快速講解 JSON 格式,并通過(guò)代碼示例演示如何分別在客戶端和服務(wù)器端進(jìn)行 JSON 格式數(shù)據(jù)的處理。
    管有許多宣傳關(guān)于 XML 如何擁有跨平臺(tái),跨語(yǔ)言的優(yōu)勢(shì),然而,除非應(yīng)用于 Web Services,否則,在普通的 Web 應(yīng)用中,開(kāi)發(fā)者經(jīng)常為 XML 的解析傷透了腦筋,無(wú)論是服務(wù)器端生成或處理 XML,還是客戶端用 JavaScript 解析 XML,都常常導(dǎo)致復(fù)雜的代碼,極低的開(kāi)發(fā)效率。實(shí)際上,對(duì)于大多數(shù) Web 應(yīng)用來(lái)說(shuō),他們根本不需要復(fù)雜的 XML 來(lái)傳輸數(shù)據(jù),XML 的擴(kuò)展性很少具有優(yōu)勢(shì),許多 AJAX 應(yīng)用甚至直接返回 HTML 片段來(lái)構(gòu)建動(dòng)態(tài) Web 頁(yè)面。和返回 XML 并解析它相比,返回 HTML 片段大大降低了系統(tǒng)的復(fù)雜性,但同時(shí)缺少了一定的靈活性。

    現(xiàn)在, JSON 為 Web 應(yīng)用開(kāi)發(fā)者提供了另一種數(shù)據(jù)交換格式。讓我們來(lái)看看 JSON 到底是什么,同 XML 或 HTML 片段相比,JSON 提供了更好的簡(jiǎn)單性和靈活性。

    JSON 數(shù)據(jù)格式解析

    和 XML 一樣,JSON 也是基于純文本的數(shù)據(jù)格式。由于 JSON 天生是為 JavaScript 準(zhǔn)備的,因此,JSON 的數(shù)據(jù)格式非常簡(jiǎn)單,您可以用 JSON 傳輸一個(gè)簡(jiǎn)單的 String,Number,Boolean,也可以傳輸一個(gè)數(shù)組,或者一個(gè)復(fù)雜的 Object 對(duì)象。

    String,Number 和 Boolean 用 JSON 表示非常簡(jiǎn)單。例如,用 JSON 表示一個(gè)簡(jiǎn)單的 String “ abc ”,其格式為:

    "abc"

    這與絕大多數(shù)編程語(yǔ)言的表示方法一致,例如:

    12345(整數(shù))
    -3.9e10(浮點(diǎn)數(shù))

    Boolean 類型表示為 truefalse 。此外,JavaScript 中的 null 被表示為 null,注意,truefalsenull 都沒(méi)有雙引號(hào),否則將被視為一個(gè) String 。

    JSON 還可以表示一個(gè)數(shù)組對(duì)象,使用 [] 包含所有元素,每個(gè)元素用逗號(hào)分隔,元素可以是任意的 Value,例如,以下數(shù)組包含了一個(gè) String,Number,Boolean 和一個(gè) null:

    ["abc",12345,false,null]

    Object 對(duì)象在 JSON 中是用 {} 包含一系列無(wú)序的 Key-Value 鍵值對(duì)表示的,實(shí)際上此處的 Object 相當(dāng)于 Java 中的 Map<String, Object>,而不是 Java 的 Class 。注意 Key 只能用 String 表示。

    例如,一個(gè) Address 對(duì)象包含如下 Key-Value:

    city:Beijing 
    street:Chaoyang Road
    postcode:100025(整數(shù))

    用 JSON 表示如下:

    {"city":"Beijing","street":" Chaoyang Road ","postcode":100025}

    其中 Value 也可以是另一個(gè) Object 或者數(shù)組,因此,復(fù)雜的 Object 可以嵌套表示,例如,一個(gè) Person 對(duì)象包含 name 和 address 對(duì)象,可以表示如下:

    {"name":"Michael","address":
    {"city":"Beijing","street":" Chaoyang Road ","postcode":100025}
    }

    JavaScript 處理 JSON 數(shù)據(jù)

    上面介紹了如何用 JSON 表示數(shù)據(jù),接下來(lái),我們還要解決如何在服務(wù)器端生成 JSON 格式的數(shù)據(jù)以便發(fā)送到客戶端,以及客戶端如何使用 JavaScript 處理 JSON 格式的數(shù)據(jù)。

    我們先討論如何在 Web 頁(yè)面中用 JavaScript 處理 JSON 數(shù)據(jù)。我們通過(guò)一個(gè)簡(jiǎn)單的 JavaScript 方法就能看到客戶端如何將 JSON 數(shù)據(jù)表示給用戶:

    function handleJson() { 
    var j={"name":"Michael","address":
    {"city":"Beijing","street":" Chaoyang Road ","postcode":100025}
    };
    document.write(j.name);
    document.write(j.address.city);
    }

    假定服務(wù)器返回的 JSON 數(shù)據(jù)是上文的:

    {"name":"Michael","address":
    {"city":"Beijing","street":" Chaoyang Road ","postcode":100025}
    }

    只需將其賦值給一個(gè) JavaScript 變量,就可以立刻使用該變量并更新頁(yè)面中的信息了,相比 XML 需要從 DOM 中讀取各種節(jié)點(diǎn)而言,JSON 的使用非常容易。我們需要做的僅僅是發(fā)送一個(gè) Ajax 請(qǐng)求,然后將服務(wù)器返回的 JSON 數(shù)據(jù)賦值給一個(gè)變量即可。有許多 Ajax 框架早已包含了處理 JSON 數(shù)據(jù)的能力,例如 Prototype(一個(gè)流行的 JavaScript 庫(kù):http://prototypejs.org)提供了 evalJSON() 方法,能直接將服務(wù)器返回的 JSON 文本變成一個(gè) JavaScript 變量:

    new Ajax.Request("http://url", { 
    method: "get",
    onSuccess: function(transport) {
    var json = transport.responseText.evalJSON();
    // TODO: document.write(json.xxx);
    }
    });

    服務(wù)器端輸出 JSON 格式數(shù)據(jù)

    下面我們討論如何在服務(wù)器端輸出 JSON 格式的數(shù)據(jù)。以 Java 為例,我們將演示將一個(gè) Java 對(duì)象編碼為 JSON 格式的文本。

    將 String 對(duì)象編碼為 JSON 格式時(shí),只需處理好特殊字符即可。另外,必須用 (") 而非 (') 表示字符串:


    static String string2Json(String s) {
    StringBuilder sb = new StringBuilder(s.length()+20);
    sb.append('\"');
    for (int i=0; i<s.length(); i++) {
    char c = s.charAt(i);
    switch (c) {
    case '\"':
    sb.append("\\\"");
    break;
    case '\\':
    sb.append("\\\\");
    break;
    case '/':
    sb.append("\\/");
    break;
    case '\b':
    sb.append("\\b");
    break;
    case '\f':
    sb.append("\\f");
    break;
    case '\n':
    sb.append("\\n");
    break;
    case '\r':
    sb.append("\\r");
    break;
    case '\t':
    sb.append("\\t");
    break;
    default:
    sb.append(c);
    }
    }
    sb.append('\"');
    return sb.toString();
    }

    將 Number 表示為 JSON 就容易得多,利用 Java 的多態(tài),我們可以處理 Integer,Long,F(xiàn)loat 等多種 Number 格式:


    static String number2Json(Number number) {
    return number.toString();
    }

    Boolean 類型也可以直接通過(guò) toString() 方法得到 JSON 的表示:


    static String boolean2Json(Boolean bool) {
    return bool.toString();
    }

    要將數(shù)組編碼為 JSON 格式,可以通過(guò)循環(huán)將每一個(gè)元素編碼出來(lái):


    static String array2Json(Object[] array) {
    if (array.length==0)
    return "[]";
    StringBuilder sb = new StringBuilder(array.length << 4);
    sb.append('[');
    for (Object o : array) {
    sb.append(toJson(o));
    sb.append(',');
    }
    // 將最后添加的 ',' 變?yōu)?']':
    sb.setCharAt(sb.length()-1, ']');
    return sb.toString();
    }

    最后,我們需要將 Map<String, Object> 編碼為 JSON 格式,因?yàn)?JavaScript 的 Object 實(shí)際上對(duì)應(yīng)的是 Java 的 Map<String, Object> 。該方法如下:


    static String map2Json(Map<String, Object> map) {
    if (map.isEmpty())
    return "{}";
    StringBuilder sb = new StringBuilder(map.size() << 4);
    sb.append('{');
    Set<String> keys = map.keySet();
    for (String key : keys) {
    Object value = map.get(key);
    sb.append('\"');
    sb.append(key);
    sb.append('\"');
    sb.append(':');
    sb.append(toJson(value));
    sb.append(',');
    }
    // 將最后的 ',' 變?yōu)?'}':
    sb.setCharAt(sb.length()-1, '}');
    return sb.toString();
    }

    為了統(tǒng)一處理任意的 Java 對(duì)象,我們編寫(xiě)一個(gè)入口方法 toJson(Object),能夠?qū)⑷我獾?Java 對(duì)象編碼為 JSON 格式:


    public static String toJson(Object o) {
    if (o==null)
    return "null";
    if (o instanceof String)
    return string2Json((String)o);
    if (o instanceof Boolean)
    return boolean2Json((Boolean)o);
    if (o instanceof Number)
    return number2Json((Number)o);
    if (o instanceof Map)
    return map2Json((Map<String, Object>)o);
    if (o instanceof Object[])
    return array2Json((Object[])o);
    throw new RuntimeException("Unsupported type: " + o.getClass().getName());
    }

    我們并未對(duì) Java 對(duì)象作嚴(yán)格的檢查。不被支持的對(duì)象(例如 List)將直接拋出 RuntimeException 。此外,為了保證輸出的 JSON 是有效的,Map<String, Object> 對(duì)象的 Key 也不能包含特殊字符。細(xì)心的讀者可能還會(huì)發(fā)現(xiàn)循環(huán)引用的對(duì)象會(huì)引發(fā)無(wú)限遞歸,例如,精心構(gòu)造一個(gè)循環(huán)引用的 Map,就可以檢測(cè)到 StackOverflowException


    @Test(expected=StackOverflowError.class)
    public void testRecurrsiveMap2Json() {
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("key", map);
    JsonUtil.map2Json(map);
    }

    好在服務(wù)器處理的 JSON 數(shù)據(jù)最終都應(yīng)該轉(zhuǎn)化為簡(jiǎn)單的 JavaScript 對(duì)象,因此,遞歸引用的可能性很小。

    最后,通過(guò) Servlet 或 MVC 框架輸出 JSON 時(shí),需要設(shè)置正確的 MIME 類型(application/json)和字符編碼。假定服務(wù)器使用 UTF-8 編碼,則可以使用以下代碼輸出編碼后的 JSON 文本:


    response.setContentType("application/json;charset=UTF-8");
    response.setCharacterEncoding("UTF-8");
    PrintWriter pw = response.getWriter();
    pw.write(JsonUtil.toJson(obj));
    pw.flush();

    小結(jié)

    JSON 已經(jīng)是 JavaScript 標(biāo)準(zhǔn)的一部分。目前,主流的瀏覽器對(duì) JSON 支持都非常完善。應(yīng)用 JSON,我們可以從 XML 的解析中擺脫出來(lái),對(duì)那些應(yīng)用 Ajax 的 Web 2.0 網(wǎng)站來(lái)說(shuō),JSON 確實(shí)是目前最靈活的輕量級(jí)方案。

    posted @ 2012-02-27 11:00 redcoatjk 閱讀(339) | 評(píng)論 (0)編輯 收藏
     
    JNDI是 Java 命名與目錄接口(Java Naming and Directory Interface),在J2EE規(guī)范中是重要的規(guī)范之一,不少專家認(rèn)為,沒(méi)有透徹理解JNDI的意義和作用,就沒(méi)有真正掌握J(rèn)2EE特別是EJB的知識(shí)。
    那么,JNDI到底起什么作用?

    要了解JNDI的作用,我們可以從“如果不用JNDI我們?cè)鯓幼觯坑昧薐NDI后我們又將怎樣做?”這個(gè)問(wèn)題來(lái)探討。

    沒(méi)有JNDI的做法:
    程序員開(kāi)發(fā)時(shí),知道要開(kāi)發(fā)訪問(wèn)MySQL數(shù)據(jù)庫(kù)的應(yīng)用,于是將一個(gè)對(duì) MySQL JDBC 驅(qū)動(dòng)程序類的引用進(jìn)行了編碼,并通過(guò)使用適當(dāng)?shù)?JDBC URL 連接到數(shù)據(jù)庫(kù)。
    就像以下代碼這樣:

    Connection conn=null;
    try {Class.forName("com.mysql.jdbc.Driver",true, Thread.currentThread().getContextClassLoader());
    conn=DriverManager.getConnection("jdbc:mysql://MyDBServer?user=qingfeng&password=mingyue");
    /* 使用conn并進(jìn)行SQL操作 */......
    conn.close();
    }
    catch(Exception e)
    {e.printStackTrace();}
    finally {if(conn!=null)
    {try {conn.close();}
    catch(SQLException e) {
    }}}

    這是傳統(tǒng)的做法,也是以前非Java程序員(如Delphi、VB等)常見(jiàn)的做法。這種做法一般在小規(guī)模的開(kāi)發(fā)過(guò)程中不會(huì)產(chǎn)生問(wèn)題,只要程序員熟悉Java語(yǔ)言、了解JDBC技術(shù)和MySQL,可以很快開(kāi)發(fā)出相應(yīng)的應(yīng)用程序。

    沒(méi)有JNDI的做法存在的問(wèn)題:
    1、數(shù)據(jù)庫(kù)服務(wù)器名稱MyDBServer 、用戶名和口令都可能需要改變,由此引發(fā)JDBC URL需要修改;
    2、數(shù)據(jù)庫(kù)可能改用別的產(chǎn)品,如改用DB2或者Oracle,引發(fā)JDBC驅(qū)動(dòng)程序包和類名需要修改;
    3、隨著實(shí)際使用終端的增加,原配置的連接池參數(shù)可能需要調(diào)整;
    4、......

    解決辦法:
    程序員應(yīng)該不需要關(guān)心“具體的數(shù)據(jù)庫(kù)后臺(tái)是什么?JDBC驅(qū)動(dòng)程序是什么?JDBC URL格式是什么?訪問(wèn)數(shù)據(jù)庫(kù)的用戶名和口令是什么?”等等這些問(wèn)題,程序員編寫(xiě)的程序應(yīng)該沒(méi)有對(duì) JDBC 驅(qū)動(dòng)程序的引用,沒(méi)有服務(wù)器名稱,沒(méi)有用戶名稱或口令 —— 甚至沒(méi)有數(shù)據(jù)庫(kù)池或連接管理。而是把這些問(wèn)題交給J2EE容器來(lái)配置和管理,程序員只需要對(duì)這些配置和管理進(jìn)行引用即可。

    由此,就有了JNDI。

    用了JNDI之后的做法:
    首先,在在J2EE容器中配置JNDI參數(shù),定義一個(gè)數(shù)據(jù)源,也就是JDBC引用參數(shù),給這個(gè)數(shù)據(jù)源設(shè)置一個(gè)名稱;然后,在程序中,通過(guò)數(shù)據(jù)源名稱引用數(shù)據(jù)源從而訪問(wèn)后臺(tái)數(shù)據(jù)庫(kù)。
    具體操作如下(以JBoss為例):
    1、配置數(shù)據(jù)源
    在JBoss的 D:\jboss420GA\docs\examples\jca 文件夾下面,有很多不同數(shù)據(jù)庫(kù)引用的數(shù)據(jù)源定義模板。將其中的 mysql-ds.xml 文件Copy到你使用的服務(wù)器下,如 D:\jboss420GA\server\default\deploy。
    修改 mysql-ds.xml 文件的內(nèi)容,使之能通過(guò)JDBC正確訪問(wèn)你的MySQL數(shù)據(jù)庫(kù),如下:
    <?xml version="1.0" encoding="UTF-8"?>
    <datasources>
    <local-tx-datasource>
        <jndi-name>MySqlDS</jndi-name>
        <connection-url>jdbc:mysql://localhost:3306/lw</connection-url>
        <driver-class>com.mysql.jdbc.Driver</driver-class>
        <user-name>root</user-name>
        <password>rootpassword</password>
    <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>
        <metadata>
           <type-mapping>mySQL</type-mapping>
        </metadata>
    </local-tx-datasource>
    </datasources>

    這里,定義了一個(gè)名為MySqlDS的數(shù)據(jù)源,其參數(shù)包括JDBC的URL,驅(qū)動(dòng)類名,用戶名及密碼等。

    2、在程序中引用數(shù)據(jù)源:

    Connection conn=null;
    try
    {
    Context ctx=new InitialContext();
    Object datasourceRef=ctx.lookup("java:MySqlDS");
    //引用數(shù)據(jù)源
    DataSource ds=(Datasource)datasourceRef;
    conn=ds.getConnection();
    /* 使用conn進(jìn)行數(shù)據(jù)庫(kù)SQL操作 */......
    c.close();
    }
    catch(Exception e)
    {e.printStackTrace();}
    finally {if(conn!=null)
    {
    try
    {
    conn.close();
    }
    catch(SQLException e)
    {
    }}}
    直接使用JDBC或者通過(guò)JNDI引用數(shù)據(jù)源的編程代碼量相差無(wú)幾,但是現(xiàn)在的程序可以不用關(guān)心具體JDBC參數(shù)了。
    在系統(tǒng)部署后,如果數(shù)據(jù)庫(kù)的相關(guān)參數(shù)變更,只需要重新配置 mysql-ds.xml 修改其中的JDBC參數(shù),只要保證數(shù)據(jù)源的名稱不變,那么程序源代碼就無(wú)需修改。

    由此可見(jiàn),JNDI避免了程序與數(shù)據(jù)庫(kù)之間的緊耦合,使應(yīng)用更加易于配置、易于部署。

    JNDI的擴(kuò)展:
    JNDI在滿足了數(shù)據(jù)源配置的要求的基礎(chǔ)上,還進(jìn)一步擴(kuò)充了作用:所有與系統(tǒng)外部的資源的引用,都可以通過(guò)JNDI定義和引用。

    所以,在J2EE規(guī)范中,J2EE 中的資源并不局限于 JDBC 數(shù)據(jù)源。引用的類型有很多,其中包括資源引用(已經(jīng)討論過(guò))、環(huán)境實(shí)體和 EJB 引用。特別是 EJB 引用,它暴露了 JNDI 在 J2EE 中的另外一項(xiàng)關(guān)鍵角色:查找其他應(yīng)用程序組件。

    EJB 的 JNDI 引用非常類似于 JDBC 資源的引用。在服務(wù)趨于轉(zhuǎn)換的環(huán)境中,這是一種很有效的方法。可以對(duì)應(yīng)用程序架構(gòu)中所得到的所有組件進(jìn)行這類配置管理,從 EJB 組件到 JMS 隊(duì)列和主題,再到簡(jiǎn)單配置字符串或其他對(duì)象,這可以降低隨時(shí)間的推移服務(wù)變更所產(chǎn)生的維護(hù)成本,同時(shí)還可以簡(jiǎn)化部署,減少集成工作。 外部資源”。


    總結(jié):
    J2EE 規(guī)范要求所有 J2EE 容器都要提供 JNDI 規(guī)范的實(shí)現(xiàn)。JNDI 在 J2EE 中的角色就是“交換機(jī)” —— J2EE 組件在運(yùn)行時(shí)間接地查找其他組件、資源或服務(wù)的通用機(jī)制。在多數(shù)情況下,提供 JNDI 供應(yīng)者的容器可以充當(dāng)有限的數(shù)據(jù)存儲(chǔ),這樣管理員就可以設(shè)置應(yīng)用程序的執(zhí)行屬性,并讓其他應(yīng)用程序引用這些屬性(Java 管理擴(kuò)展(Java Management Extensions,JMX)也可以用作這個(gè)目的)。JNDI 在 J2EE 應(yīng)用程序中的主要角色就是提供間接層,這樣組件就可以發(fā)現(xiàn)所需要的資源,而不用了解這些間接性。

    在 J2EE 中,JNDI 是把 J2EE 應(yīng)用程序合在一起的粘合劑,JNDI 提供的間接尋址允許跨企業(yè)交付可伸縮的、功能強(qiáng)大且很靈活的應(yīng)用程序。這是 J2EE 的承諾,而且經(jīng)過(guò)一些計(jì)劃和預(yù)先考慮,這個(gè)承諾是完全可以實(shí)現(xiàn)的。
    posted @ 2012-02-14 10:24 redcoatjk 閱讀(347) | 評(píng)論 (0)編輯 收藏
     

    在Oracle中,要按特定條件查詢前N條記錄,用個(gè)rownum就搞定了。
    select * from emp where rownum <= 5
    結(jié)果只查詢5條記錄, oracle會(huì)自動(dòng)展現(xiàn)一個(gè)rownum的屬性表示記錄排序號(hào)

    而select * from emp where rownum > 5 ;則是失敗的。
    因?yàn)?rownum是oracle預(yù)處理字段,默認(rèn)標(biāo)序是1,只有記錄集已經(jīng)滿足條件后才會(huì)進(jìn)行后續(xù)編號(hào)。由于第一條記錄rownum默認(rèn)是1,而你的條件是rownum>=6 對(duì)第一條記錄比較它的rownum肯定不大于6 所以不滿足條件 oracle舍棄第一條記錄將數(shù)據(jù)庫(kù)第二條記錄標(biāo)序?yàn)?再進(jìn)行比較  肯定都不滿足rownum>=6  這樣循環(huán)也就是說(shuō)由于沒(méi)有記錄滿足rownum>=6所以記錄一直被舍棄,rownum一直是1 。

    解決方案: 利用查詢時(shí),自動(dòng)生成的rownum屬性.
    排序方法:
      select * from (
           select a1.*, rownum rwn  from emp a1   where rownum <=10
        ) where rwn >= 6;
      或者
      select * from (
        select qx.*,row_number() over(order by qx.empno) rwn from emp qx
      ) where rwn between 6 and 10
    -------------------------------------------------------------------------
    使用注意:

    1排序?qū)е聰?shù)據(jù)重復(fù):


    table1中表有字段(其余字段省)
    ID  主鍵
    DATA_UPDATE_TIME 數(shù)據(jù)更新時(shí)間(只存儲(chǔ)了年月日)

    分頁(yè)查詢的語(yǔ)句如下
    select *
       from (
            select row_.*, rownum rownum_
               from ( select  p.id from table1 p
                 order by  p.DATA_UPDATE_TIME desc )
       row_ where rownum <= )
    where rownum_ >

    以每頁(yè)顯示10條為例
    第一次  rownum <= 10)   where rownum_ > 0
    第二次  rownum <= 20)   where rownum_ > 10

    發(fā)現(xiàn)有一條記錄在兩次查詢結(jié)果中重復(fù)出現(xiàn),不知道問(wèn)題出在哪里,請(qǐng)忙幫看看。

    另:
    DATA_UPDATE_TIME 的值有重復(fù),不知道跟它有沒(méi)有關(guān)系。
    如果按ID排的話就不會(huì)出現(xiàn)這個(gè)問(wèn)題


    解答:
    如果order by 不能唯一確定記錄的順序就會(huì)出現(xiàn)這個(gè)問(wèn)題。
    解決的方法是把分頁(yè)部分全部拿到最外層進(jìn)行。

    Java代碼 復(fù)制代碼 收藏代碼
    1. select * from (    
    2.   select row_.*, rownum rownum_    
    3.   from (   
    4.     select p.id from table1 p    
    5.     order by p.DATA_UPDATE_TIME desc    
    6.   ) row_   
    7. )    
    8. where rownum_ > ? and rownum_ <= ?   

    2 排序的id順序:
    Oracle中的rownum的是在取數(shù)據(jù)的時(shí)候產(chǎn)生的序號(hào),所以想對(duì)指定排序的數(shù)據(jù)去指定的rowmun行數(shù)據(jù)就必須注意了。
    SQL> select rownum ,id,name from student order by name;
        ROWNUM ID     NAME
    ---------- ------ ---------------------------------------------------
             3 200003 李三
             2 200002 王二
             1 200001 張一
             4 200004 趙四
    可以看出,rownum并不是按照name列來(lái)生成的序號(hào)。系統(tǒng)是按照記錄插入時(shí)的順序給記錄排的號(hào),rowid也是順序分配的。為了解決這個(gè)問(wèn)題,必須使用子查詢
    SQL> select rownum ,id,name from (select * from student order by name);
        ROWNUM ID     NAME
    ---------- ------ ---------------------------------------------------
             1 200003 李三
             2 200002 王二
             3 200001 張一
             4 200004 趙四
    這樣就成了按name排序,并且用rownum標(biāo)出正確序號(hào)(有小到大)


    ------------
    參考Oracle的rownum原理和使用  http://tenn.iteye.com/blog/99339

    在Oracle中,要按特定條件查詢前N條記錄,用個(gè)rownum就搞定了。
    select * from emp where rownum <= 5
    而且書(shū)上也告誡,不能對(duì)rownum用">",這也就意味著,如果你想用
    select * from emp where rownum > 5
    則是失敗的。要知道為什么會(huì)失敗,則需要了解rownum背后的機(jī)制:
    1 Oracle executes your query.

    2 Oracle fetches the first row and calls it row number 1.

    3 Have we gotten past row number meets the criteria? If no, then Oracle discards the row, If yes, then Oracle return the row.

    4 Oracle fetches the next row and advances the row number (to 2, and then to 3, and then to 4, and so forth).

    5 Go to step 3.

    了解了原理,就知道rownum>不會(huì)成功,因?yàn)樵诘谌降臅r(shí)候查詢出的行已經(jīng)被丟棄,第四步查出來(lái)的rownum仍然是1,這樣永遠(yuǎn)也不會(huì)成功。

    同樣道理,rownum如果單獨(dú)用=,也只有在rownum=1時(shí)才有用。

     

    對(duì)于rownum來(lái)說(shuō)它是oracle系統(tǒng)順序分配為從查詢返回的行的編號(hào),返回的第一行分配的是1,第二行是2,依此類推,這個(gè)偽字段可以用于限制查詢返回的總行數(shù),而且rownum不能以任何表的名稱作為前綴。
     舉例說(shuō)明:
    例如表:student(學(xué)生)表,表結(jié)構(gòu)為:
    ID       char(6)      --學(xué)號(hào)
    name    VARCHAR2(10)   --姓名
    create table student (ID char(6), name VARCHAR2(100));
    insert into sale values('200001',‘張一’);
    insert into sale values('200002',‘王二’);
    insert into sale values('200003',‘李三’);
    insert into sale values('200004',‘趙四’);
    commit;
    (1) rownum 對(duì)于等于某值的查詢條件
    如果希望找到學(xué)生表中第一條學(xué)生的信息,可以使用rownum=1作為條件。但是想找到學(xué)生表中第二條學(xué)生的信息,使用rownum=2結(jié)果查不到數(shù)據(jù)。因?yàn)閞ownum都是從1開(kāi)始,但是1以上的自然數(shù)在rownum做等于判斷是時(shí)認(rèn)為都是false條件,所以無(wú)法查到rownum = n(n>1的自然數(shù))。
    SQL> select rownum,id,name from student where rownum=1;(可以用在限制返回記錄條數(shù)的地方,保證不出錯(cuò),如:隱式游標(biāo))
    SQL> select rownum,id,name from student where rownum=1;
        ROWNUM ID     NAME
    ---------- ------ ---------------------------------------------------
             1 200001 張一
    SQL> select rownum,id,name from student where rownum =2;
        ROWNUM ID     NAME
    ---------- ------ ---------------------------------------------------
    (2)rownum對(duì)于大于某值的查詢條件
       如果想找到從第二行記錄以后的記錄,當(dāng)使用rownum>2是查不出記錄的,原因是由于rownum是一個(gè)總是從1開(kāi)始的偽列,Oracle 認(rèn)為rownum> n(n>1的自然數(shù))這種條件依舊不成立,所以查不到記錄
    SQL> select rownum,id,name from student where rownum >2;
    ROWNUM ID     NAME
    ---------- ------ ---------------------------------------------------
    那如何才能找到第二行以后的記錄呀。可以使用以下的子查詢方法來(lái)解決。注意子查詢中的rownum必須要有別名,否則還是不會(huì)查出記錄來(lái),這是因?yàn)閞ownum不是某個(gè)表的列,如果不起別名的話,無(wú)法知道rownum是子查詢的列還是主查詢的列。
    SQL>select * from(select rownum no ,id,name from student) where no>2;
            NO ID     NAME
    ---------- ------ ---------------------------------------------------
             3 200003 李三
             4 200004 趙四
    SQL> select * from(select rownum,id,name from student)where rownum>2;
        ROWNUM ID     NAME
    ---------- ------ ---------------------------------------------------
    (3)rownum對(duì)于小于某值的查詢條件
    如果想找到第三條記錄以前的記錄,當(dāng)使用rownum<3是能得到兩條記錄的。顯然rownum對(duì)于rownum<n((n>1的自然數(shù))的條件認(rèn)為是成立的,所以可以找到記錄。
    SQL> select rownum,id,name from student where rownum <3;
        ROWNUM ID     NAME
    ---------- ------ ---------------------------------------------------
    1 200001 張一
            2 200002 王二
    綜上幾種情況,可能有時(shí)候需要查詢r(jià)ownum在某區(qū)間的數(shù)據(jù),那怎么辦呀從上可以看出rownum對(duì)小于某值的查詢條件是人為true的,rownum對(duì)于大于某值的查詢條件直接認(rèn)為是false的,但是可以間接的讓它轉(zhuǎn)為認(rèn)為是true的。那就必須使用子查詢。例如要查詢r(jià)ownum在第二行到第三行之間的數(shù)據(jù),包括第二行和第三行數(shù)據(jù),那么我們只能寫(xiě)以下語(yǔ)句,先讓它返回小于等于三的記錄行,然后在主查詢中判斷新的rownum的別名列大于等于二的記錄行。但是這樣的操作會(huì)在大數(shù)據(jù)集中影響速度。
    SQL> select * from (select rownum no,id,name from student where rownum<=3 ) where no >=2;
            NO ID     NAME
    ---------- ------ ---------------------------------------------------
             2 200002 王二
             3 200003 李三
    (4)rownum和排序
    Oracle中的rownum的是在取數(shù)據(jù)的時(shí)候產(chǎn)生的序號(hào),所以想對(duì)指定排序的數(shù)據(jù)去指定的rowmun行數(shù)據(jù)就必須注意了。
    SQL> select rownum ,id,name from student order by name;
        ROWNUM ID     NAME
    ---------- ------ ---------------------------------------------------
             3 200003 李三
             2 200002 王二
             1 200001 張一
             4 200004 趙四
    可以看出,rownum并不是按照name列來(lái)生成的序號(hào)。系統(tǒng)是按照記錄插入時(shí)的順序給記錄排的號(hào),rowid也是順序分配的。為了解決這個(gè)問(wèn)題,必須使用子查詢
    SQL> select rownum ,id,name from (select * from student order by name);
        ROWNUM ID     NAME
    ---------- ------ ---------------------------------------------------
             1 200003 李三
             2 200002 王二
             3 200001 張一
             4 200004 趙四
    這樣就成了按name排序,并且用rownum標(biāo)出正確序號(hào)(有小到大)

    posted @ 2011-11-17 16:46 redcoatjk 閱讀(322) | 評(píng)論 (0)編輯 收藏
     
    僅為個(gè)人理解.請(qǐng)指正
    Hibernate Session, 其作用無(wú)需多言.
    運(yùn)用中為避免資源消耗,一般都會(huì)手動(dòng)封裝一個(gè)HibernateUtil類(未使用Spring管理的前提下).
    該類的作用使Hibernate加載配置文件config, 創(chuàng)建sessionFactory等只運(yùn)行一次.
    實(shí)際運(yùn)用中,經(jīng)常需要將當(dāng)前線程和session綁定.一般的用法為使用ThreadLocal: 在HibernateUtil類中封裝hibernate的管理.通過(guò)openSession取得
    session,并將其放入ThreadLocal變量中. 這樣業(yè)務(wù)邏輯中僅需通過(guò)工具類取得當(dāng)前線程對(duì)應(yīng)的session.使用完畢后,調(diào)用工具類closeSession方法將
    session關(guān)閉,當(dāng)前線程的ThreadLocal變量置為NULL. 保證線程歸還線程池復(fù)用后,ThreadLocal為空,以免出現(xiàn)導(dǎo)致其他線程訪問(wèn)到本線程變量.
    后,Hibernate的SessionFactory提供獲取session的新方法getCurrentSession (獲得與當(dāng)前線程綁定的session). 內(nèi)部通過(guò)代理封裝,此方式得到的session
    不僅和當(dāng)前線程綁定,也無(wú)需手動(dòng)開(kāi)關(guān). 默認(rèn)在事務(wù)提交之后,session自動(dòng)關(guān)閉. 需注意的是,必須在事務(wù)開(kāi)啟的前提之下才可使用此種方式獲得的session.
    此外hibernate.cfg.xml配置文件中也許配置
    <property name="current_session_context_class">thread</property> 基于線程
    了,引入Spring之后.sessionfactory的創(chuàng)建等都交給spring管理.Spring也提供了HibernateTemplate,HibernateDaoSupport這樣的封裝方法.
    用戶可以不再考慮session的管理,事務(wù)的開(kāi)啟關(guān)閉.只需配置事務(wù)即可.
    而所謂session關(guān)閉后,因延遲加載導(dǎo)致前臺(tái)無(wú)法顯示的問(wèn)題以往解決方式為強(qiáng)制全部加載,現(xiàn)在也可通過(guò)在web.xml中配置
    org.springframework.orm.hibernate3.support.OpenSessionInViewFilter來(lái)解決.



    ------------------------------以下內(nèi)容為工地資料-------------------------------------------------------------------------------
    OpenSession : 手動(dòng)打開(kāi),需手動(dòng)關(guān)閉.[所以代碼中充斥著try catch --sf.openSession --打開(kāi)事務(wù),提交-回滾 finall關(guān)閉session的代碼]
    threadlocal : hibernate給出的提示. 在HibernateUtil工具類中,new出threadlocal ,放入opensession.這樣可以使當(dāng)前線程綁定session.
    使用后需關(guān)閉session,將threadlocal中session變量置為null .
    3  getCurrentSession: hibernate3的新特性. 無(wú)需手動(dòng)關(guān)閉session,自動(dòng)獲取當(dāng)前線程的session,若無(wú)則新建之. 需在配置文件中配置thread屬性.表明和當(dāng)前線程綁定.
        參考網(wǎng)友資料,getCurrentSession模式,內(nèi)部開(kāi)啟了session自動(dòng)提交的功能且使用getCurrentSession的session,及時(shí)做load操作,也需要打開(kāi)事務(wù).
    Title

    1 getCurrentSession創(chuàng)建的session會(huì)和綁定到當(dāng)前線程,而openSession不會(huì)。

    2 getCurrentSession創(chuàng)建的線程會(huì)在事務(wù)回滾或事物提交后自動(dòng)關(guān)閉,而openSession必須手動(dòng)關(guān)閉

    這里getCurrentSession本地事務(wù)(本地事務(wù):jdbc)時(shí) 要在配置文件里進(jìn)行如下設(shè)置

     * 如果使用的是本地事務(wù)(jdbc事務(wù))
     <property name="hibernate.current_session_context_class">thread</property>
     * 如果使用的是全局事務(wù)(jta事務(wù))
     <property name="hibernate.current_session_context_class">jta</property>

    getCurrentSession () 使用當(dāng)前的session
    openSession()         重新建立一個(gè)新的session

    在一個(gè)應(yīng)用程序中,如果DAO 層使用Spring 的hibernate 模板,通過(guò)Spring 來(lái)控制session 的生命周期,則首選getCurrentSession ()。

    使用Hibernate的大多數(shù)應(yīng)用程序需要某種形式的“上下文相關(guān)的” session,特定的session在整個(gè)特定的上下文范圍內(nèi)始終有效。然而,對(duì)不同類型的應(yīng)用程序而言,要為什么是組成這種“上下文”下一個(gè)定義通常 是困難的;不同的上下文對(duì)“當(dāng)前”這個(gè)概念定義了不同的范圍。在3.0版本 之前,使用Hibernate的程序要么采用自行編寫(xiě)的基于 ThreadLocal的上下文session,要么采用HibernateUtil這樣的輔助類,要么采用第三方框架(比如Spring或Pico), 它們提供了基于代理(proxy)或者基于攔截器(interception)的上下文相關(guān)session。從3.0.1版本開(kāi)始,Hibernate增加了SessionFactory.getCurrentSession()方法。一 開(kāi)始,它假定了采用JTA事務(wù),JTA事務(wù)定義了當(dāng)前session的范圍和上下文(scope and context)。Hibernate開(kāi)發(fā)團(tuán)隊(duì)堅(jiān)信,因?yàn)橛泻脦讉€(gè)獨(dú)立的JTA TransactionManager實(shí)現(xiàn)穩(wěn)定可用,不論是否被部署到一個(gè)J2EE容器中,大多數(shù)(假若不是所有的)應(yīng)用程序都應(yīng)該采用JTA事務(wù)管理。 基于這一點(diǎn),采用JTA的上下文相關(guān)session可以滿足你一切需要。

    更好的是,從3.1開(kāi)始,SessionFactory.getCurrentSession()的后臺(tái)實(shí)現(xiàn)是可拔插的。因此,我們引入了新的擴(kuò)展 接口 (org.hibernate.context.CurrentSessionContext)和新的配置參數(shù) (hibernate.current_session_context_class),以便對(duì)什么是“當(dāng)前session”的范圍和上下文(scope and context)的定義進(jìn)行拔插。

    請(qǐng)參閱 org.hibernate.context.CurrentSessionContext接口的Javadoc,那里有關(guān)于它的契約的詳細(xì)討論。它定義 了單一的方法,currentSession(),特定的實(shí)現(xiàn)用它來(lái)負(fù)責(zé)跟蹤當(dāng)前的上下文session。Hibernate內(nèi)置了此接口的兩種實(shí)現(xiàn)。

    org.hibernate.context.JTASessionContext - 當(dāng)前session根據(jù)JTA來(lái)跟蹤和界定。這和以前的僅支持JTA的方法是完全一樣的。詳情請(qǐng)參閱Javadoc。

    org.hibernate.context.ThreadLocalSessionContext - 當(dāng)前session通過(guò)當(dāng)前執(zhí)行的線程來(lái)跟蹤和界定。詳情也請(qǐng)參閱Javadoc。

    這兩種實(shí)現(xiàn)都提供了“每數(shù)據(jù)庫(kù)事務(wù)對(duì)應(yīng)一個(gè)session”的編程模型,也稱作每次請(qǐng)求一個(gè)session。Hibernate session的起始和終結(jié)由數(shù)據(jù)庫(kù)事務(wù)的生存來(lái)控制。假若你采用自行編寫(xiě)代碼來(lái)管理事務(wù)(比如,在純粹的J2SE,或者 JTA/UserTransaction/BMT),建議你使用Hibernate Transaction API來(lái)把底層事務(wù)實(shí)現(xiàn)從你的代碼中隱藏掉。如果你在支持CMT的EJB容器中執(zhí)行,事務(wù)邊界是聲明式定義的,你不需要在代碼中進(jìn)行任何事務(wù)或 session管理操作。請(qǐng)參閱第 11 章 事務(wù)和并發(fā)一節(jié)來(lái)閱讀更多的內(nèi)容和示例代碼。

    hibernate.current_session_context_class 配置參數(shù)定義了應(yīng)該采用哪個(gè)org.hibernate.context.CurrentSessionContext實(shí)現(xiàn)。注意,為了向下兼容,如果未 配置此參數(shù),但是存在org.hibernate.transaction.TransactionManagerLookup的配 置,Hibernate會(huì)采用org.hibernate.context.JTASessionContext。一般而言,此參數(shù)的值指明了要使用的實(shí) 現(xiàn)類的全名,但那兩個(gè)內(nèi)置的實(shí)現(xiàn)可以使用簡(jiǎn)寫(xiě),即"jta"和"thread"。

    1、getCurrentSession()與openSession()的區(qū)別?

    * 采用getCurrentSession()創(chuàng)建的session會(huì)綁定到當(dāng)前線程中,而采用openSession()
    創(chuàng)建的session則不會(huì)
    * 采用getCurrentSession()創(chuàng)建的session在commit或rollback時(shí)會(huì)自動(dòng)關(guān)閉,而采用openSession()
    創(chuàng)建的session必須手動(dòng)關(guān)閉
    2、使用getCurrentSession()需要在hibernate.cfg.xml文件中加入如下配置:
    * 如果使用的是本地事務(wù)(jdbc事務(wù))
    <property name="hibernate.current_session_context_class">thread</property>
    * 如果使用的是全局事務(wù)(jta事務(wù))
    <property name="hibernate.current_session_context_class">jta</property>

    利于ThreadLocal模式管理Session
       早在Java1.2推出之時(shí),Java平臺(tái)中就引入了一個(gè)新的支持:java.lang.ThreadLocal,給我們?cè)诰帉?xiě)多線程程序
       時(shí)提供了一種新的選擇。ThreadLocal是什么呢?其實(shí)ThreadLocal并非是一個(gè)線程的本地實(shí)現(xiàn)版本,它并不是一個(gè)Thread,
       而是thread local variable(線程局部變量)。也許把它命名為T(mén)hreadLocalVar更加合適。線程局部變量(ThreadLocal)
       其實(shí)的功用非常簡(jiǎn)單,就是為每一個(gè)使用某變量的線程都提供一個(gè)該變量值的副本,是每一個(gè)線程都可以獨(dú)立地改變自己的副本,
       而不會(huì)和其它線程的副本沖突。從線程的角度看,就好像每一個(gè)線程都完全擁有一個(gè)該變量。
       ThreadLocal是如何做到為每一個(gè)線程維護(hù)變量的副本的呢?其實(shí)實(shí)現(xiàn)的思路很簡(jiǎn)單,在ThreadLocal類中有一個(gè)Map,
       用于存儲(chǔ)每一個(gè)線程的變量的副本。比如下面的示例實(shí)現(xiàn)(為了簡(jiǎn)單,沒(méi)有考慮集合的泛型):
    public class HibernateUtil {

    public static final ThreadLocal session =new ThreadLocal();

    public static final SessionFactory sessionFactory;
       static {
          try {
            sessionFactory = new Configuration().configure().buildSessionFactory();
          } catch (Throwable ex) {
               throw new ExceptionInInitializerError(ex);
          }   
    }

         public static Session currentSession() throws HibernateException {
            Session s = session.get();
            if(s == null) {
              s = sessionFactory.openSession();
              session.set(s);
               }
             return s;
           }

        public static void closeSession() throws HibernateException {
               Session s = session.get();
            if(s != null) {
                s.close();
            }
            session.set(null);
        }
    }

    以下為T(mén)hreadLocal的參考資料
    Title

     最近由于需要用到ThreadLocal,在網(wǎng)上搜索了一些相關(guān)資料,發(fā)現(xiàn)對(duì)ThreadLocal經(jīng)常會(huì)有下面幾種誤解

     一、ThreadLocal是java線程的一個(gè)實(shí)現(xiàn)
          ThreadLocal的確是和java線程有關(guān),不過(guò)它并不是java線程的一個(gè)實(shí)現(xiàn),它只是用來(lái)維護(hù)本地變量。針對(duì)每個(gè)線程,提供自己的變量版本,主要是為了避免線程沖突,每個(gè)線程維護(hù)自己的版本。彼此獨(dú)立,修改不會(huì)影響到對(duì)方。

     二、ThreadLocal是相對(duì)于每個(gè)session的

            ThreadLocal顧名思義,是針對(duì)線程。在java web編程上,每個(gè)用戶從開(kāi)始到會(huì)話結(jié)束,都有自己的一個(gè)session標(biāo)識(shí)。但是ThreadLocal并不是在會(huì)話層上。其 實(shí),Threadlocal是獨(dú)立于用戶session的。它是一種服務(wù)器端行為,當(dāng)服務(wù)器每生成一個(gè)新的線程時(shí),就會(huì)維護(hù)自己的 ThreadLocal。對(duì)于這個(gè)誤解,個(gè)人認(rèn)為應(yīng)該是開(kāi)發(fā)人員在本地基于一些應(yīng)用服務(wù)器測(cè)試的結(jié)果。眾所周知,一般的應(yīng)用服務(wù)器都會(huì)維護(hù)一套線程池,也 就是說(shuō),對(duì)于每次訪問(wèn),并不一定就新生成一個(gè)線程。而是自己有一個(gè)線程緩存池。對(duì)于訪問(wèn),先從緩存池里面找到已有的線程,如果已經(jīng)用光,才去新生成新的線 程。所以,由于開(kāi)發(fā)人員自己在測(cè)試時(shí),一般只有他自己在測(cè),這樣服務(wù)器的負(fù)擔(dān)很小,這樣導(dǎo)致每次訪問(wèn)可能是共用同樣一個(gè)線程,導(dǎo)致會(huì)有這樣的誤解:每個(gè) session有一個(gè)ThreadLocal

     三、ThreadLocal是相對(duì)于每個(gè)線程的,用戶每次訪問(wèn)會(huì)有新的ThreadLocal

      理論上來(lái)說(shuō),ThreadLocal是的確是相對(duì)于每個(gè)線程,每個(gè)線程會(huì)有自己的ThreadLocal。但是上面已經(jīng)講到,一般的應(yīng)用服 務(wù)器都會(huì)維護(hù)一套線程池。因此,不同用戶訪問(wèn),可能會(huì)接受到同樣的線程。因此,在做基于TheadLocal時(shí),需要謹(jǐn)慎,避免出現(xiàn) ThreadLocal變量的緩存,導(dǎo)致其他線程訪問(wèn)到本線程變量 .[senngr:HibernateUtil工具類中,一般都是通過(guò)closesession的方法,里面將opensession對(duì)應(yīng)的session關(guān)閉.并將ThreadLocal變量置為NULL.這樣線程池中如果再將這個(gè)線程分配給別人,對(duì)應(yīng)的ThreadLocal是干凈的.]

     四、對(duì)每個(gè)用戶訪問(wèn),ThreadLocal可以多用
            可以說(shuō),ThreadLocal是一把雙刃劍,用得來(lái)的話可以起到非常好的效果。但是,ThreadLocal如果用得不好,就會(huì)跟全局變量一樣。代碼不 能重用,不能獨(dú)立測(cè)試。因?yàn)椋恍┍緛?lái)可以重用的類,現(xiàn)在依賴于ThreadLocal變量。如果在其他沒(méi)有ThreadLocal場(chǎng)合,這些類就變得不 可用了。個(gè)人覺(jué)得ThreadLocal用得很好的幾個(gè)應(yīng)用場(chǎng)合,值得參考

      1、存放當(dāng)前session用戶:quake want的jert

      2、存放一些context變量,比如webwork的ActionContext

      3、存放session,比如Spring hibernate orm的session

    posted @ 2011-11-02 01:37 redcoatjk 閱讀(17700) | 評(píng)論 (3)編輯 收藏
     
    http://space.itpub.net/9252210/viewspace-594453
    今天在做數(shù)據(jù)導(dǎo)出的時(shí)候,由于用戶名的密碼使用的是特殊字符,所以遇到了錯(cuò)誤代碼:“EXP-00056: 遇到 ORACLE 錯(cuò)誤 12154”,網(wǎng)上查找原因,需要用引號(hào)擴(kuò)起來(lái),但是os不同,方式也不同:

        windows os: exp username/"""password"""@devdb --3個(gè)雙引號(hào)擴(kuò)密碼

        linux/unix os: exp 'username/"password"@devdb' --1個(gè)雙引號(hào)擴(kuò)密碼,1個(gè)單引號(hào)擴(kuò)全部

        實(shí)驗(yàn)結(jié)果如下:
    1.創(chuàng)建帶有特殊字符密碼的用戶
    C:\Documents and Settings\Home>sqlplus /nolog
    SQL*Plus: Release 10.2.0.1.0 - Production on 星期四 5月 7 17:37:36 2009
    Copyright (c) 1982, 2005, Oracle.  All rights reserved.
    SQL> connsys/oracle@devdbas sysdba
    已連接。
    SQL> create user exp identified by "12345!@#$%";
    用戶已創(chuàng)建。
    SQL> grant connect, resource to exp;
    授權(quán)成功。
    SQL> conn exp/"12345!@#$%"@devdb2
    已連接。
    SQL> create table table1 as select * from dual;
    表已創(chuàng)建。
    SQL> exit
    2.windows os導(dǎo)出測(cè)試
    C:\Documents and Settings\Home>expexp/12345!@#$%@devdbfile=c:\exp.dmp wner=exp
    Export: Release 9.2.0.1.0 - Production on 星期四 5月 7 17:39:42 2009
    Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.
    EXP-00056: 遇到 ORACLE 錯(cuò)誤 12154
    ORA-12154: TNS: 無(wú)法處理服務(wù)名
    EXP-00000: 導(dǎo)出終止失敗
    C:\Documents and Settings\Home>exp exp/"12345!@#$%"@devdb2file=c:\exp.dmp wner=exp
    Export: Release 9.2.0.1.0 - Production on 星期四 5月 7 17:39:57 2009
    Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.
    EXP-00056: 遇到 ORACLE 錯(cuò)誤 12154
    ORA-12154: TNS: 無(wú)法處理服務(wù)名
    EXP-00000: 導(dǎo)出終止失敗
    C:\Documents and Settings\Home>exp exp/"""12345!@#$%"""@devdb2file=c:\exp.dmp wner=exp
    Export: Release 9.2.0.1.0 - Production on 星期四 5月 7 17:41:54 2009
    Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.
    連接到: Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Production
    With the Partitioning, Real Application Clusters, OLAP, Data Mining
    and Real Application Testing options
    已導(dǎo)出 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集
    . 正在導(dǎo)出 pre-schema 過(guò)程對(duì)象和操作
    . 正在導(dǎo)出用戶 EXP 的外部函數(shù)庫(kù)名稱
    . 導(dǎo)出 PUBLIC 類型同義詞
    . 導(dǎo)出私有類型同義詞
    . 正在導(dǎo)出用戶 EXP 的對(duì)象類型定義
    即將導(dǎo)出 EXP 的對(duì)象 ...
    . 正在導(dǎo)出數(shù)據(jù)庫(kù)鏈接
    . 正在導(dǎo)出序號(hào)
    . 正在導(dǎo)出群集定義
    . 即將導(dǎo)出 EXP 的表通過(guò)常規(guī)路徑 ...
    . . 正在導(dǎo)出表                          TABLE1          1 行被導(dǎo)出
    . 正在導(dǎo)出同義詞
    . 正在導(dǎo)出視圖
    . 正在導(dǎo)出存儲(chǔ)的過(guò)程
    . 正在導(dǎo)出運(yùn)算符
    . 正在導(dǎo)出引用完整性約束條件
    . 正在導(dǎo)出觸發(fā)器
    . 正在導(dǎo)出索引類型
    . 正在導(dǎo)出位圖, 功能性索引和可擴(kuò)展索引
    . 正在導(dǎo)出后期表活動(dòng)
    . 正在導(dǎo)出實(shí)體化視圖
    . 正在導(dǎo)出快照日志
    . 正在導(dǎo)出作業(yè)隊(duì)列
    . 正在導(dǎo)出刷新組和子組
    . 正在導(dǎo)出維
    . 正在導(dǎo)出 post-schema 過(guò)程對(duì)象和操作
    . 正在導(dǎo)出統(tǒng)計(jì)
    在沒(méi)有警告的情況下成功終止導(dǎo)出。

    3.linux/unix os導(dǎo)出測(cè)試
    [oracle@rac2 ~]$ expexp/12345!@#$%@devdbfile=./exp.dmp wner=exp
    -bash:!@#$%@devdb: event not found
    [oracle@rac2 ~]$ exp exp/"""12345!@#$%"""@devdbfile=./exp.dmp wner=exp
    -bash:!@#$%"""@devdb: event not found
    [oracle@rac2 ~]$exp 'exp/"12345!@#$%"@devdb'file=./exp.dmp wner=exp 
    Export: Release 10.2.0.4.0 - Production on Thu May 7 19:21:32 2009 
    Copyright (c) 1982, 2007, Oracle.  All rights reserved. 
    Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Production
    With the Partitioning, Real Application Clusters, OLAP, Data Mining
    and Real Application Testing options
    Export done in US7ASCII character set and AL16UTF16 NCHAR character set
    server uses ZHS16GBK character set (possible charset conversion)
    . exporting pre-schema procedural objects and actions
    . exporting foreign function library names for user EXP
    . exporting PUBLIC type synonyms
    . exporting private type synonyms
    . exporting object type definitions for user EXP
    About to export EXP's objects ...
    . exporting database links
    . exporting sequence numbers
    . exporting cluster definitions
    . about to export EXP's tables via Conventional Path ...
    . . exporting table                         TABLE1          1 rows exported
    . exporting synonyms
    . exporting views
    . exporting stored procedures
    . exporting operators
    . exporting referential integrity constraints
    . exporting triggers
    . exporting indextypes
    . exporting bitmap, functional and extensible indexes
    . exporting posttables actions
    . exporting materialized views
    . exporting snapshot logs
    . exporting job queues
    . exporting refresh groups and children
    . exporting dimensions
    . exporting post-schema procedural objects and actions
    . exporting statistics
    Export terminated successfully without warnings.

    posted @ 2011-10-19 17:03 redcoatjk 閱讀(692) | 評(píng)論 (0)編輯 收藏
     

    關(guān)于group by 的應(yīng)用問(wèn)題  

    數(shù)據(jù)庫(kù)內(nèi)容為下面


     

    寫(xiě)一SQL得出下面內(nèi)容:


     

    貼出SQL結(jié)果如下:(MySQL版本)

    create table gosin_temp(rq varchar(10),shengfu nchar(1));

    insert into gosin_temp values('2009-05-09','勝');
    insert into gosin_temp values('2009-05-09','勝');
    insert into gosin_temp values('2009-05-09','負(fù)');
    insert into gosin_temp values('2009-05-09','負(fù)');
    insert into gosin_temp values('2009-05-10','勝');
    insert into gosin_temp values('2009-05-10','負(fù)');
    insert into gosin_temp values('2009-05-10','負(fù)');

    select * from gosin_temp;

    得到結(jié)果的SQL:
    select a1.rq,a1.勝,b1.負(fù) from
    (select a.rq, count(a.shengfu) 勝 from gosin_temp a where a.shengfu='勝' group by a.rq) a1,
    (select b.rq, count(b.shengfu) 負(fù) from gosin_temp b where b.shengfu='負(fù)' group by b.rq) b1
    where a1.rq = b1.rq

    類似的題目還有很多,如:

       勝 負(fù)
    1 a b
    2 b a
    3 b a

    要求寫(xiě)一SQL語(yǔ)句,輸出如下結(jié)果:
       勝 負(fù)
    a 1 2
    b 2 1

    其實(shí)都一樣 只要熟悉使用group by 就不覺(jué)得難了。

    posted @ 2011-08-25 17:12 redcoatjk 閱讀(225) | 評(píng)論 (0)編輯 收藏
     
    摘自:   http://www.iteye.com/topic/766418

    -----------------------------------------
    1,什么是Servlet
    2,Servlet有什么作用
    3,Servlet的生命周期
    4,Servlet怎么處理一個(gè)請(qǐng)求
    5,Servlet與JSP有什么區(qū)別
    6,Servlet里的cookie技術(shù)
    7,Servlet里的過(guò)濾器
    8,Servlet里的監(jiān)聽(tīng)器

     


    一,什么是Servlet?


    Servlet是一個(gè)Java編寫(xiě)的程序,此程序是基于Http協(xié)議的,在服務(wù)器端運(yùn)行的(如tomcat),

     

    是按照Servlet規(guī)范編寫(xiě)的一個(gè)Java類。



    二,Servlet有什么作用?


    主要是處理客戶端的請(qǐng)求并將其結(jié)果發(fā)送到客戶端。



    三,Servlet的生命周期?


    Servlet的生命周期是由Servlet的容器來(lái)控制的,它可以分為3個(gè)階段;初始化,運(yùn)行,銷毀。

    初始化階段:


    1,Servlet容器加載servlet類,把servlet類的.class文件中的數(shù)據(jù)讀到內(nèi)存中。


    2,然后Servlet容器創(chuàng)建一個(gè)ServletConfig對(duì)象。ServletConfig對(duì)象包含了Servlet的初始化配置信息。


    3,Servlet容器創(chuàng)建一個(gè)servlet對(duì)象。


    4,Servlet容器調(diào)用servlet對(duì)象的init方法進(jìn)行初始化。



    運(yùn)行階段:


    當(dāng)servlet容器接收到一個(gè)請(qǐng)求時(shí),servlet容器會(huì)針對(duì)這個(gè)請(qǐng)求創(chuàng)建servletRequest和servletResponse對(duì)象。

     

    然后調(diào)用service方法。并把這兩個(gè)參數(shù)傳遞給service方法。Service方法通過(guò)servletRequest對(duì)象獲得請(qǐng)求的

     

    信息。并處理該請(qǐng)求。再通過(guò)servletResponse對(duì)象生成這個(gè)請(qǐng)求的響應(yīng)結(jié)果。然后銷毀servletRequest和

     

    servletResponse對(duì)象。我們不管這個(gè)請(qǐng)求是post提交的還是get提交的,最終這個(gè)請(qǐng)求都會(huì)由service方法來(lái)處理。


    web服務(wù)器接受到一個(gè)http請(qǐng)求后,web服務(wù)器會(huì)將請(qǐng)求移交給 servlet容器,servlet容器首先對(duì)所請(qǐng)求的URL進(jìn)行解析并根據(jù)
    web.xml 配置文件找到相應(yīng)的處理servlet,同時(shí)將request、response對(duì)象傳遞給它,servlet通過(guò)request對(duì)象可知道客戶端
    的請(qǐng)求 者、請(qǐng)求信息以及其他的信息等,servlet在處理完請(qǐng)求后會(huì)把所有需要返回的信息放入response對(duì)象中并返回到客戶端,
    servlet一旦處理 完請(qǐng)求,servlet容器就會(huì)刷新response對(duì)象,并把控制權(quán)重新返回給web服務(wù)器。

     


    銷毀階段:


    當(dāng)Web應(yīng)用被終止時(shí),servlet容器會(huì)先調(diào)用servlet對(duì)象的destrory方法,然后再銷毀servlet對(duì)象,

     

    同時(shí)也會(huì)銷毀與servlet對(duì)象相關(guān)聯(lián)的servletConfig對(duì)象。我們可以在destroy方法的實(shí)現(xiàn)中,釋放

     

    servlet所占用的資源,如關(guān)閉數(shù)據(jù)庫(kù)連接,關(guān)閉文件輸入輸出流等。



    在這里該注意的地方:


    在servlet生命周期中,servlet的初始化和和銷毀階段只會(huì)發(fā)生一次,而service方法執(zhí)行的次數(shù)則取決于servlet被客戶

     

    端訪問(wèn)的次數(shù)

     

     


    四,Servlet怎么處理一個(gè)請(qǐng)求?


    當(dāng)用戶發(fā)送一個(gè)請(qǐng)求到某個(gè)Servlet的時(shí)候,Servlet容器會(huì)創(chuàng)建一個(gè)ServletRequst和ServletResponse對(duì)象。

     

    在ServletRequst對(duì)象中封裝了用戶的請(qǐng)求信息,然后Servlet容器把ServletRequst和ServletResponse對(duì)象

     

    傳給用戶所請(qǐng)求的Servlet,Servlet把處理好的結(jié)果寫(xiě)在ServletResponse中,然后Servlet容器把響應(yīng)結(jié)果傳

     

    給用戶。

     


    五,Servlet與JSP有什么區(qū)別?


    1,jsp經(jīng)編譯后就是servlet,也可以說(shuō)jsp等于servlet。


    2,jsp更擅長(zhǎng)頁(yè)面(表現(xiàn))。servlet更擅長(zhǎng)邏輯編輯。 (最核心的區(qū)別)。


    3,在實(shí)際應(yīng)用中采用Servlet來(lái)控制業(yè)務(wù)流程,而采用JSP來(lái)生成動(dòng)態(tài)網(wǎng)頁(yè).在struts框架中,

     

    JSP位于MVC設(shè)計(jì)模式的視圖層,而Servlet位于控制層。

     


    六,Servlet里的cookie技術(shù)?


    cookies是一種WEB服務(wù)器通過(guò)瀏覽器在訪問(wèn)者的硬盤(pán)上存儲(chǔ)信息的手段,是由Netscape公司開(kāi)發(fā)出來(lái)的。


    cookie技術(shù)的好處:


        1,Cookie有效期限未到時(shí),Cookie能使用戶在不鍵入密碼和用戶名的情況下進(jìn)入曾經(jīng)瀏覽過(guò)的一些站點(diǎn)。


        2,Cookie能使站點(diǎn)跟蹤特定訪問(wèn)者的訪問(wèn)次數(shù)、最后訪問(wèn)時(shí)間和訪問(wèn)者進(jìn)入站點(diǎn)的路徑。
       
    創(chuàng)建一個(gè)cookie

    Java代碼  收藏代碼
    1. //里面的兩個(gè)參數(shù)分別是cookie的名和cookie的值  
    2.   
    3. response.addCookie(new Cookie("abc","10000000"));  

     

    使用cookie

    Java代碼  收藏代碼
    1. Cookie[] cook =request.getCookies();//用一個(gè)Cookie數(shù)組來(lái)接收  
    2.   
    3. for(int j=0;j<cook.length;j++){//通過(guò)循環(huán)來(lái)打印Cookie  
    4.   
    5.         cook[j].getName()://取cookie的名    
    6.         cook[j].getValue()://去cookie的值  
    7.   
    8. }  
     


    七,Servlet里的過(guò)濾器?


    過(guò)濾器的主要作用


    1,任何系統(tǒng)或網(wǎng)站都要判斷用戶是否登錄。


    2,網(wǎng)絡(luò)聊天系統(tǒng)或論壇,功能是過(guò)濾非法文字


    3,統(tǒng)一解決編碼


    (2)怎么創(chuàng)建一個(gè)過(guò)濾器:

     

    1,生成一個(gè)普通的class類,實(shí)現(xiàn)Filter接口(javax.servlet.Filter;)。


    2,重寫(xiě)接口里面的三個(gè)方法:init,doFilter,destroy。


    3,然后在web.xml配置過(guò)濾器。



    八,Servlet里的監(jiān)聽(tīng)器?


    監(jiān)聽(tīng)器的作用:自動(dòng)執(zhí)行一些操作。

    三種servlet監(jiān)聽(tīng)器:

     

    對(duì)request的監(jiān)聽(tīng)。對(duì)session的監(jiān)聽(tīng)。對(duì)application的監(jiān)聽(tīng)。

    怎么創(chuàng)建一個(gè)session監(jiān)聽(tīng)器:


    1,生成一個(gè)普通的class類,如果是對(duì)session的監(jiān)聽(tīng),則實(shí)現(xiàn)HttpSessionListener。


    2,然后重寫(xiě)里面的五個(gè)方法:

     

    Java代碼  收藏代碼
    1. public void sessionCreated(HttpSessionEvent arg0) {} // 創(chuàng)建  
    2.   
    3. public void sessionDestroyed(HttpSessionEvent arg0) {} // 銷毀  
    4.   
    5. public void attributeAdded(HttpSessionEvent arg0) {} // 增加  
    6.   
    7. public void attributeRemoved(HttpSessionEvent arg0) {} // 刪除  
    8.   
    9. public void attributeReplaced(HttpSessionEvent arg0) {} // 替換 
    posted @ 2011-08-25 15:41 redcoatjk 閱讀(226) | 評(píng)論 (0)編輯 收藏
     
    這個(gè)寫(xiě)的不錯(cuò).有的沒(méi)看懂.
    目前沒(méi)時(shí)間細(xì)看,暫時(shí)先轉(zhuǎn)載.
    摘自:
    http://www.jdon.com/artichect/state.htm

    ---------------------------------------------------

    板橋里人 http://www.jdon.com 2006/1/2(轉(zhuǎn)載請(qǐng)保留)

      這是一個(gè)實(shí)戰(zhàn)中非常重要但是容易被忽視的概念,說(shuō)它重要,是因?yàn)樗葦?shù)據(jù)庫(kù)重要;說(shuō)它容易被忽視也是同樣的原因,它經(jīng)常被數(shù)據(jù)庫(kù)概念替代。

      如果你經(jīng)驗(yàn)和經(jīng)歷中沒(méi)有狀態(tài)這個(gè)概念,極端地說(shuō):可能你的Java系統(tǒng)經(jīng)驗(yàn)還未積累到一定程度,狀態(tài)是每個(gè)Java程序員深入Java系統(tǒng)后必然碰到的問(wèn)題。

      本文我想試圖表達(dá)的是:狀態(tài)分兩種:活動(dòng)的狀態(tài)對(duì)象和持久化的狀態(tài)。而數(shù)據(jù)庫(kù)中的數(shù)據(jù)只是狀態(tài)的一種持久化結(jié)果,而Java系統(tǒng) 運(yùn)行時(shí),我們更多的可能是和一種活動(dòng)的狀態(tài)打交道,這種活動(dòng)的狀態(tài)存在內(nèi)存中,而不是持久化到硬盤(pán)上,當(dāng)然,需要時(shí)你可以通過(guò)數(shù)據(jù)庫(kù)/文件持久化到硬盤(pán)上。

      但是,如果你以數(shù)據(jù)庫(kù)數(shù)據(jù)替代狀態(tài),那么就可能導(dǎo)致數(shù)據(jù)庫(kù)的頻繁訪問(wèn),而且 你的系統(tǒng)會(huì)變成一個(gè)非對(duì)象化的、緊耦合、到處是分散數(shù)據(jù)塊的糟糕系統(tǒng)。這樣的系統(tǒng)并不比傳統(tǒng)的兩層結(jié)構(gòu)好到哪里!也不會(huì)比Jsp里嵌入Java代碼偽三層系統(tǒng)高明到什么地方。

    什么是狀態(tài)?

      只要有對(duì)象就可能有狀態(tài),任何一個(gè)對(duì)象活動(dòng)時(shí),都有自己的狀態(tài)屬性,類的 字段屬性極有可能成為狀態(tài),我們現(xiàn)在經(jīng)常使用的Domain model其實(shí)就是一種 包含狀態(tài)的對(duì)象,如果你對(duì)狀態(tài)沒(méi)有深入掌握,就不可能真正掌握對(duì)象系統(tǒng)特點(diǎn),或者是Domain Model的執(zhí)行情況。

      對(duì)于初學(xué)者,經(jīng)常會(huì)疑問(wèn):我是將數(shù)據(jù)放在HttpSession中還是Request中,這里 其實(shí)已經(jīng)開(kāi)始接觸狀態(tài),一旦你接觸狀態(tài),你就要開(kāi)始小心,因?yàn)槟憧赡軙?huì)將內(nèi)存泄漏的惡魔導(dǎo)引進(jìn)來(lái)。

      內(nèi)存泄漏的惡魔爆發(fā)時(shí)刻取決于你狀態(tài)的生存周期和系統(tǒng)并發(fā)訪問(wèn)量。

      狀態(tài)的生存周期也就是包含這個(gè)狀態(tài)的對(duì)象的生命周期,在簡(jiǎn)單系統(tǒng)中,我們只 需要通過(guò)new創(chuàng)建對(duì)象,然后它的消亡就會(huì)依靠JVM垃圾回收機(jī)制回收,但是事情會(huì)這么簡(jiǎn)單嗎?

      狀態(tài)的危險(xiǎn)還會(huì)發(fā)生在多線程環(huán)境下,當(dāng)多個(gè)線程對(duì)同一個(gè)內(nèi)存中狀態(tài)寫(xiě)操作時(shí),這時(shí)怎么辦?如果這個(gè)狀 態(tài)持久化在數(shù)據(jù)庫(kù)中,我們會(huì)依賴數(shù)據(jù)庫(kù)提供的強(qiáng)大事務(wù)機(jī)制防止這種并發(fā)死鎖,但是如果是在內(nèi)存中,你就很難辦,因此,我們就盡量避免發(fā)生這種多線程同時(shí)訪 問(wèn)一個(gè)狀態(tài)的現(xiàn)象,而Singleton單例模式極容易發(fā)生這種現(xiàn)象,因此實(shí)踐中,單例模式是J2EE開(kāi)發(fā)中需要避免的,相關(guān)帖子討論見(jiàn):
    http://www.jdon.com/jive/article.jsp?forum=91&thread=17578

      我們接觸的Web容器或Jsp/Servlet本質(zhì)就是一個(gè)多線程,這也是很多初學(xué)者不知道的, 因?yàn)槎嗑€程編程是復(fù)雜或困難的,因此才有jsp/Servlet這樣的上層封裝,但是我們使用他們
    時(shí),實(shí)際在進(jìn)行多線程編程。

      生命周期和多線程并發(fā)使得我們簡(jiǎn)單的面向?qū)ο笙到y(tǒng)變得異常復(fù)雜和難以掌握起來(lái)。下面我從這個(gè)兩個(gè)角度,給出兩種模式思維解決之道。

    生命周期(Scope)

      生命周期(Scope)就是指狀態(tài)的活動(dòng)周期,狀態(tài)對(duì)象是什么時(shí)候被創(chuàng)建;然后什么時(shí)候被銷毀,很顯然,如果狀態(tài)對(duì)象還沒(méi)有被創(chuàng)建或已經(jīng)被銷毀,你再 訪問(wèn)這個(gè)狀態(tài)對(duì)象可能失敗,而狀態(tài)的生命周期控制是可能散落在運(yùn)行程序的各個(gè)地方,如果不象狀態(tài)模式那樣進(jìn)行統(tǒng)一控制,有可能整個(gè)系統(tǒng)是危機(jī)四伏的。

      狀態(tài)的生命周期其實(shí)就是對(duì)象生命周期,更加細(xì)化地說(shuō):是Domain Model這個(gè)對(duì)象的生命周期。這在一個(gè)以領(lǐng)域模型為驅(qū)動(dòng)的設(shè)計(jì)概念中不可回避的課題,而領(lǐng)域模型實(shí)戰(zhàn)的復(fù)雜性就復(fù)雜在此。

      狀態(tài)的生命周期在J2EE中目前有三種:Request/Session和 Application,Request是每個(gè)客戶端發(fā)出的一次請(qǐng)求,這是J2EE系統(tǒng)中最基本的事件激活單元, 當(dāng)服務(wù)器端推出一個(gè)頁(yè)面到客戶端時(shí),意味著這個(gè)Request的結(jié)束。那么如果我們的狀態(tài)保存在Request中,意味著在request結(jié)束之前,這個(gè) 請(qǐng)求經(jīng)歷的任何一個(gè)環(huán)節(jié)都可以對(duì)這個(gè)狀態(tài)(對(duì)象)進(jìn)行操作。(掌握這個(gè)原理,對(duì)于你學(xué)習(xí)Struts和JSF很有幫助)

      如果是Session,則一直和該客戶端有關(guān),只要是該客戶端發(fā)出的每次request的任何環(huán)節(jié)都可以對(duì)這個(gè)狀態(tài)(對(duì)象)進(jìn)行操作。

      如果是Application,則意味著這個(gè)狀態(tài)是當(dāng)前Web項(xiàng)目的全局狀態(tài)。

      這三種狀態(tài)形式都是以將狀態(tài)保存在內(nèi)存中形式存在的,是和持久化狀態(tài)相對(duì)的。是一種內(nèi)存活動(dòng)狀態(tài)。

      生命周期的選取當(dāng)然是越短越好,這樣,這個(gè)狀態(tài)對(duì)象就可以被自動(dòng)銷毀,從而避免了
    大訪問(wèn)量下的內(nèi)存泄漏,但是在大訪問(wèn)量下,對(duì)象頻繁創(chuàng)建和銷毀是耗費(fèi)性能的。

      那么,我們可能經(jīng)常使用HttpSession來(lái)保存狀態(tài),這時(shí)你極有可能造成內(nèi)存泄漏,我經(jīng)常在 Jdon論壇上看到將很多數(shù)據(jù)庫(kù)數(shù)據(jù)暫時(shí)保存在HttpSession中想法,這是相當(dāng)危險(xiǎn)的,因?yàn)橐坏┎l(fā)用戶很多,相當(dāng)多的HttpSession包 含了狀態(tài),而狀態(tài)中有可能有更多其他引用,因此內(nèi)存很快會(huì)爆滿,或者垃圾回收機(jī)制頻繁啟動(dòng),造成應(yīng)用系統(tǒng)運(yùn)行暫停或緩慢。

      當(dāng)你將狀態(tài)放入HttpSession時(shí),難道沒(méi)有考慮將其手工消除嗎?你要知道所有Web容器 (Tomcat/Weblogic等)都不會(huì)自動(dòng)替你清除那些你可能不用的狀態(tài)對(duì)象啊。如果每個(gè)人只管新增元素,不管重整或管理,這個(gè)系統(tǒng)能不變得混亂 嗎?代碼上這種現(xiàn)象我們是通過(guò)Refactoring等結(jié)構(gòu)/行為模式來(lái)解決,那么在運(yùn)行時(shí)的狀態(tài)管理呢?

      狀態(tài)管理模式或者說(shuō)對(duì)象管理模式正是解決這種問(wèn)題的。

       按照該模式,你必須手工自己管理放在HttpSession的狀態(tài),比如你為每個(gè)HttpSession
    設(shè)立一個(gè)狀態(tài)容器最大尺寸,當(dāng)超過(guò)這個(gè)尺寸時(shí),你需要將不用的狀態(tài)從容器去除, 但是如果這個(gè)客戶端在Session失效期內(nèi)又來(lái)訪問(wèn)這個(gè)狀態(tài)怎么辦?那么你可能需要先臨時(shí)將狀態(tài)序列化保存到硬盤(pán)上,等Session失效期到達(dá)后再真正刪除。

      是不是覺(jué)得很麻煩?
      捷徑是有:
      1. 盡量少使用HttpSession保存狀態(tài),這對(duì)集群環(huán)境也是有利的,見(jiàn)該貼討論:
    http://www.jdon.com/jive/article.jsp?forum=121&thread=22282
    那么這些狀態(tài)放在哪里?使用Application的緩存中,

      2. 使用狀態(tài)管理中間件,目前有幾個(gè)選擇:EJB的有態(tài)Bean;NanoContainer之類狀態(tài)相關(guān)的微容器。那么Spring可以嗎?目前沒(méi)有發(fā)現(xiàn)有 該功能,甚至在Spring容器內(nèi)無(wú)法直接使用Session性質(zhì)的狀態(tài),只能通過(guò)線程級(jí)別的ThreadLocal來(lái)實(shí)現(xiàn)(對(duì)不起,你又要開(kāi)始回到遠(yuǎn)古 的匯編線程時(shí)代了);而Jdon框架則可以。

      下面我們談?wù)凙pplication的狀態(tài),在這個(gè)范圍內(nèi),一個(gè)對(duì)象狀態(tài)可以被多個(gè)用戶反復(fù)訪問(wèn),在這個(gè)級(jí)別,狀態(tài)類似數(shù)據(jù)庫(kù)中數(shù)據(jù),因?yàn)榭梢允褂脭?shù)據(jù)庫(kù)來(lái)替代這個(gè)級(jí)別的狀態(tài),所以將狀態(tài)放入緩存這個(gè)深層次技術(shù)被大多數(shù)初學(xué)者忽視了,甚至產(chǎn)生了對(duì)數(shù)據(jù)庫(kù)依賴心理。

    緩存中的狀態(tài)

      雖然我們將狀態(tài)保存在Application中,但是我們不可避免還是遇到Session同樣的狀態(tài)管理問(wèn)題,這個(gè)問(wèn)題所幸的是有專門(mén)緩存中間件解決 了,當(dāng)然,在一個(gè)多服務(wù)器集群系統(tǒng),如果一個(gè)客戶端在一個(gè)服務(wù)器中存放了狀態(tài),那么能否在另外一個(gè)服務(wù)器的內(nèi)存中訪問(wèn)到呢?回答是肯定的,前提是你必須使 用分布式緩存系統(tǒng)。

      目前分布式緩存系統(tǒng)是靠EJB服務(wù)器完成,當(dāng)JBoss 5在2006變成完全解耦、可肢解時(shí),
    我們就可以使用原本只支持EJB的JBoss分布式緩存系統(tǒng)來(lái)支持我們的普通JavaBeans了(POJO)。這其中目前可能會(huì)花費(fèi)一些力氣,因?yàn)檫€沒(méi)有一個(gè)統(tǒng)一的POJO構(gòu)件接口標(biāo)準(zhǔn),我相信以后
    可能會(huì)有。

      如果你不想花費(fèi)力氣,而且可能就只是一臺(tái)服務(wù)器,可以通過(guò)雙核芯片提升性能,那么單態(tài)緩存如果實(shí)現(xiàn)?很簡(jiǎn)單,使用一個(gè)緩存產(chǎn)品如OsCache等,將其設(shè)定保存在 Application中,或者在web.xml中進(jìn)行一下簡(jiǎn)單的配置即可。

      但是,這時(shí)你可能碰到另外一個(gè)問(wèn)題:狀態(tài)的唯一標(biāo)識(shí),如何通過(guò)唯一標(biāo)識(shí)從緩存中那么
    多對(duì)象狀態(tài)中取出你要的那一個(gè)呢?比較瑣碎。

      有沒(méi)有一個(gè)框架幫助你省卻這些麻煩,當(dāng)然推薦Jdon Framework,只要將包含狀態(tài)的類(主要是Domain Model)繼承特定的類或接口(接口在1.4版本實(shí)現(xiàn))即可,這個(gè)類的對(duì)象運(yùn)行時(shí)就會(huì)被緩存或從緩存中讀取,再也無(wú)需你照料緩存了,就這么簡(jiǎn)單。

      當(dāng)然,Jdon Framework的底層緩存器是可以被替代,使用你喜歡的緩存產(chǎn)品,因?yàn)閖don
    Framework是基于Ioc設(shè)計(jì),構(gòu)件之間是完全解耦、可徹底肢解,能夠通過(guò)配置替代和更換的。
    如果你不明白這個(gè)道理,需要好好研究一下Ioc模式帶給我們革命性的新變化。

      從以上也可以看出:java復(fù)雜性還在于我們需要在編碼時(shí),卻要想象其運(yùn)行時(shí)的情形。而這種翻譯聯(lián)想沒(méi)有深厚的實(shí)踐功底,是很難順利完成的。

    狀態(tài)管理中間件

      自從J2EE開(kāi)辟中間件時(shí)代以來(lái),就有相當(dāng)多的高級(jí)中間件提供與具體應(yīng)用無(wú)關(guān)的通用功能,狀態(tài)管理中間件很早就有之,EJB的有態(tài)Session Bean是一個(gè)代表。

      一個(gè)中間件不但要有良好的松耦合設(shè)計(jì),我們暫時(shí)稱為靜態(tài)設(shè)計(jì);更要有優(yōu)秀的動(dòng)態(tài)設(shè)計(jì),例如狀態(tài)管理就屬于一種動(dòng)態(tài)設(shè)計(jì)。

      當(dāng)然,如果你比較謙虛,不但要選擇一些靜態(tài)設(shè)計(jì)很好的框架或中間件;而且還要依賴一些擁有良好的動(dòng)態(tài)運(yùn)行管理的中間件。

      EJB無(wú)論是EJB1.X/EJB2.X/EJB3.X.在狀態(tài)管理上要更加優(yōu)秀,當(dāng)然EJB3.X又吸收了優(yōu)秀的靜態(tài)設(shè)計(jì)概念,但是因?yàn)樾枰幸粋€(gè)具體服務(wù)器實(shí)現(xiàn)過(guò)程,這個(gè)過(guò)程中存在一些陷阱,如In-Box問(wèn)題等。

      Spring無(wú)疑是一個(gè)靜態(tài)設(shè)計(jì)非常優(yōu)秀框架,它一直在AOP上孜孜不倦,力圖探索一條從AOP角度進(jìn)行動(dòng)態(tài)運(yùn)行管理干預(yù)捷徑,相信會(huì)有驚人結(jié)果,當(dāng)然,這種細(xì)粒度的AOP需要實(shí)踐檢驗(yàn),當(dāng)然如果整入JDK 6.0就更好。

      而Jdon Framework則試圖在目前兩者之間尋求了一個(gè)平衡,既有Ioc/AOP優(yōu)秀的靜態(tài)設(shè)計(jì),雖然在AOP上不及Spring前衛(wèi);但提供了切實(shí)Session和Cache狀態(tài)管理;

      如果你不需要EJB的分布式多服務(wù)器集群功能;又不是AOP的超級(jí)粉絲,無(wú)疑使用Jdon Framework之類的框架無(wú)疑是簡(jiǎn)化方便的。

    狀態(tài)設(shè)計(jì)的難點(diǎn)

      最后,我不得不重申,并不是有了良好的狀態(tài)管理框架就可以高枕無(wú)憂了,狀態(tài)的設(shè)計(jì)其實(shí)是我們每個(gè)項(xiàng)目必須面臨的可變課題,如果狀態(tài)復(fù)雜了可以使用狀態(tài)模式對(duì)付,可惜往往狀態(tài)不夠復(fù)雜。

      一個(gè)對(duì)象本身屬性和狀態(tài)是應(yīng)該耦合在一起,還是進(jìn)行分離,屬性和狀態(tài)沒(méi)有明顯的涇渭分明的界限,我們舉一個(gè)例子:

      論壇Forum這個(gè)對(duì)象,它有一些字段屬性,如論壇名稱、論壇描述,還有其他一些相關(guān)屬性:如該論壇 的最新發(fā)帖;該論壇的發(fā)貼量,后兩者好像也是論壇字段,但是他們可能經(jīng)常變化的,應(yīng)該屬于狀態(tài),那么狀態(tài)和Forum這個(gè)主體對(duì)象是什么關(guān)系?是將該論壇 的最新發(fā)帖和該論壇的發(fā)貼量?jī)蓚€(gè)字段并入Forum這個(gè)Domain Model中,還是應(yīng)該單獨(dú)建立一個(gè)狀態(tài)對(duì)象?如果進(jìn)行分離,分離的依據(jù)是什么?

      當(dāng)然,這里分離的依據(jù)是因?yàn)閷?duì)象的生存周期不同。對(duì)于我們熟悉的課題,我們能夠馬上分辨出其中的生存周期,如果是不熟悉領(lǐng)域的建模呢?

      所以,大家已經(jīng)明白:狀態(tài)設(shè)計(jì)的難點(diǎn)是:如何粒度細(xì)化地創(chuàng)建模型對(duì)象;然后分辨出其中動(dòng)態(tài)的狀態(tài)性質(zhì)。這是域建模實(shí)戰(zhàn)中一個(gè)難點(diǎn)。

      很多人問(wèn)我:你提倡的域建模、設(shè)計(jì)模式和框架是什么意思?為什么說(shuō)他們是Java開(kāi)發(fā)設(shè)計(jì)的三件寶呢?或者說(shuō)三個(gè)典型知識(shí)點(diǎn)呢?我想通過(guò)本篇我已經(jīng)通過(guò)狀態(tài)這個(gè)概念稍微解釋了域建模的一些特點(diǎn)。

      當(dāng)前,MDA中的四色原型模式Archetype將幫助我們更好地分辨出類的屬性、狀態(tài)和行為,這是一場(chǎng)帶來(lái)以后十年的軟件革命,
    posted @ 2011-08-25 15:38 redcoatjk 閱讀(179) | 評(píng)論 (0)編輯 收藏
     

    我對(duì)瀏覽器請(qǐng)求流程的理解:

    (1) 訪問(wèn)流程:

    (1.1) 系統(tǒng)運(yùn)行在某web容器,Tomcat(其運(yùn)行和weblogic不同,Tomcat只有一個(gè)進(jìn)程).

          其預(yù)設(shè)有初始的線程數(shù).

    (1.2) 瀏覽器打開(kāi)某網(wǎng)站,網(wǎng)站及給其分配一個(gè)sessionID(頁(yè)面隱式的發(fā)起request, Tomcat

          某個(gè)特定的監(jiān)聽(tīng)線程給予response一個(gè)sessionid). sessionid用以識(shí)別本次訪問(wèn).

    (1.3) 用戶點(diǎn)擊登錄/注冊(cè), 瀏覽器發(fā)起一個(gè)新的request, Tomcat線程池中空閑的線程進(jìn)行

           處理. 反饋結(jié)果于前臺(tái)展現(xiàn).如線程池中線程不足,Tomcat每次按照一定規(guī)則創(chuàng)建出更多的空閑線程(其初始值,增加值,及最大值依據(jù)配置文件/JDK/硬件).

    posted @ 2011-08-25 11:37 redcoatjk 閱讀(223) | 評(píng)論 (0)編輯 收藏
     
    來(lái)源:
    http://www.iteye.com/topic/960652
    http://godsend-jin.iteye.com/blog/1004386
    --------------------------------------------------------------------

    最近在做登錄和權(quán)限控制模塊,用到了session,發(fā)現(xiàn)session的好多方法都不熟悉,而且以前也聽(tīng)說(shuō)過(guò)JsessionId 之類session竊取的事,

    對(duì)這些一直都是一知半解。今天索性google了很多資料,先上sun的官網(wǎng)去看session的文檔了解一些方法,又找了別人關(guān)于session的看法。

    總結(jié)如下:

          1,session是什么?  what

              session經(jīng)常譯為會(huì)話,以打電話為例,從開(kāi)始撥號(hào)到掛斷電話就是你會(huì)話的生存周期。

          2,session 做什么用的  why?

              首先舉個(gè)例子:

                    咖啡店舉行 消費(fèi)滿5杯咖啡贈(zèng)送一杯的活動(dòng),可每個(gè)人一次消費(fèi)5杯的時(shí)候非常少。這時(shí)候有3種辦法:

                    1,店員看到每個(gè)顧客時(shí)都能記住其消費(fèi)了多少杯,從而給其優(yōu)惠,這是協(xié)議本身具有狀態(tài)

                    2,給每個(gè)顧客一個(gè)卡片,上面記錄顧客的每次消費(fèi),這是客戶端保存狀態(tài)

                    3,給每個(gè)顧客一個(gè)卡片,卡片上只有一個(gè)編號(hào),顧客每次的消費(fèi)記錄在店里,這就是 服務(wù)端有狀態(tài)

              而http本身是無(wú)狀態(tài)的,所以我們只能使用2,3中方法,來(lái)保存一些信息。

              實(shí)際采用的是第3種方法,服務(wù)器段保存一次會(huì)話所有的信息,并生成一個(gè)唯一的id,這個(gè)id沒(méi)有規(guī)律而且不會(huì)重復(fù),將這個(gè)id傳回到客戶段,

    保存到cookie中。每次訪問(wèn)服務(wù)器時(shí),客戶端都會(huì)偷偷將這個(gè)id傳到服務(wù)器,服務(wù)器根據(jù)id查到這次會(huì)話保存的內(nèi)容。就能實(shí)現(xiàn)會(huì)話中共享一些數(shù)據(jù)。

         3,session怎樣創(chuàng)建和銷毀 ? how

             session是保存在內(nèi)存中的,所以會(huì)有一些性能上的影響。因此本著這個(gè)原則,session是只有在使用到的時(shí)候才會(huì)被創(chuàng)建,如果始終沒(méi)有用到

    session,這個(gè)session是永遠(yuǎn)不會(huì)被創(chuàng)建的。

            比如: 訪問(wèn)servlet ,只要你代碼中沒(méi)有 request.getSession()或request.getSession(true);這兩行是等價(jià)的,那session是不會(huì)創(chuàng)建。

    又 當(dāng)你訪問(wèn)靜態(tài)頁(yè)面時(shí),根本不會(huì)生成servlet,所以也不會(huì)創(chuàng)建session。

           下面解釋一些疑惑: session是第一次請(qǐng)求時(shí)創(chuàng)建的?

      大家都知道 jsp是被編譯成servlet才執(zhí)行的,問(wèn)題就在jsp編譯的過(guò)程。

     jsp中有個(gè)<%@ page session="true/false"%> 這個(gè)開(kāi)關(guān)表示是否創(chuàng)建session,當(dāng)你不寫(xiě)這行時(shí),它會(huì)默認(rèn)給你加上這句。所以會(huì)造成上面的疑惑。

    當(dāng)然還有一些標(biāo)簽中可能有g(shù)etSession()操作,會(huì)產(chǎn)生一些不必要的session。

           session只能在服務(wù)端銷毀,有三種途徑: 1,到達(dá)session的最大請(qǐng)求間隔時(shí)間時(shí),2,session。invalidate()

     3,服務(wù)器進(jìn)程當(dāng)?shù)簟?/p>

           這里也有一些疑惑: 瀏覽器關(guān)閉時(shí),session就會(huì)注銷。

           首先瀏覽器關(guān)閉時(shí),瀏覽器并沒(méi)有給服務(wù)器發(fā)送任何消息,所以服務(wù)器不會(huì)知道瀏覽器何時(shí)關(guān)閉了。

     上面我們知道取得session 是因?yàn)闉g覽器cookie中有sessionid,而普通cookie通常會(huì)是會(huì)話cookie,也就是說(shuō)瀏覽器關(guān)閉時(shí),這個(gè)cookie會(huì)被注銷,

    所以當(dāng)你再訪問(wèn)服務(wù)器時(shí)就沒(méi)有sessionid了,所以造成session關(guān)閉了的假象,如果昵稱通過(guò)特殊方法將sessionid傳遞給服務(wù)器,你會(huì)發(fā)現(xiàn)session還在。

    如果想讓cookie保存時(shí)間長(zhǎng)一些,就需要手動(dòng)指定cookie的過(guò)期時(shí)間

     

    4,實(shí)際項(xiàng)目中的難點(diǎn):

         1,瀏覽器禁用cookie

          這就沒(méi)辦法保存sessionid了,可以采用url重寫(xiě),轉(zhuǎn)發(fā),加隱藏字段等方法來(lái)將sessionid傳給服務(wù)器。

         如:  baidu.com:jsessionid=adfasdfasdfasdfasdfafdadf?asdfasdf

                 baidu.com?jsessionid=asdfasdfasdfadsfad&&adfdf

     這根據(jù)服務(wù)器的不同實(shí)現(xiàn),第一種可以將普通參數(shù)區(qū)分開(kāi)。

     

         2,多人共用session的問(wèn)題

            例: a 訪問(wèn) baidu.com ,但他沒(méi)有帳號(hào),于是他將連接 baidu.com/login.jsp?jsessionid=adsfasdfad(這個(gè)a的sessionid) 發(fā)給B, B登錄

    后,a就相當(dāng)于用b的帳號(hào)登錄了。你們可以在在本地試試。

            解決方法: 當(dāng)發(fā)現(xiàn)通過(guò)sessionid從url指定時(shí), 創(chuàng)建一個(gè)新的session,將舊session的信息復(fù)制到 新sessoin中,然后將新session注銷。

    就能防止上面那種情況了。

        3,一個(gè)帳號(hào)多地方登錄

           比如: 你用abc帳號(hào)登錄了baidu.com,有打開(kāi)了一個(gè)瀏覽器,又用abc帳號(hào)登錄了一次。當(dāng)不設(shè)計(jì)敏感操作時(shí),這無(wú)所謂,而當(dāng)你做一些敏感操

    作時(shí)就必須禁止這樣情況,防止同時(shí)操作,造成重復(fù)操作,或者數(shù)據(jù)損壞。

         解決方法: 監(jiān)聽(tīng)session,將username和sessionid對(duì)應(yīng)起來(lái),當(dāng)username再次登錄時(shí),注銷掉以前的session,保存現(xiàn)在的session,這也是

    一種比較不錯(cuò)的方案。

     

    這是 sghcel 畫(huà)的圖,挺不錯(cuò)的:

     



    其他:
     1session在何時(shí)被創(chuàng)建 
        一個(gè)常見(jiàn)的誤解是以為session在有客戶端訪問(wèn)時(shí)就被創(chuàng)建,然而事實(shí)是直到某server端程序調(diào)用 HttpServletRequest.getSession(true)這樣的語(yǔ)句時(shí)
    才被創(chuàng)建,注意如果
    JSP沒(méi)有顯示的使用 <%@page session="false"%> 關(guān)閉session,則JSP文件在編譯成Servlet時(shí)將會(huì)自動(dòng)加上這樣一條語(yǔ)句
    HttpSession session = HttpServletRequest.getSession(true);這也是JSP中隱含的session對(duì)象的來(lái)歷。 

       
    由于session會(huì)消耗內(nèi)存資源,因此,如果不打算使用session,應(yīng)該在所有的JSP中關(guān)閉它。


        2
    session何時(shí)被刪除
      綜合前面的討論,session在下列情況下被刪除a.程序調(diào)用HttpSession.invalidate();b.距離上一次收到客戶端發(fā)送的session id時(shí)間間隔超過(guò)了session
    超時(shí)設(shè)置
    ;c.服務(wù)器進(jìn)程被停止(非持久session


        3
    、如何做到在瀏覽器關(guān)閉時(shí)刪除session
    Title
      嚴(yán)格的講,做不到這一點(diǎn)。可以做一點(diǎn)努力的辦法是在所有的客戶端頁(yè)面里使用javascript代碼window.oncolose來(lái)監(jiān)視瀏覽器的關(guān)閉動(dòng)作,然后向服務(wù)器發(fā)送
    一個(gè)請(qǐng)求來(lái)刪除
    session。但是對(duì)于瀏覽器崩潰或者強(qiáng)行殺死進(jìn)程這些非常規(guī)手段仍然無(wú)能為力。


        4
    、有個(gè)HttpSessionListener是怎么回事 

       
    你可以創(chuàng)建這樣的listener去監(jiān)控session的創(chuàng)建和銷毀事件,使得在發(fā)生這樣的事件時(shí)你可以做一些相應(yīng)的工作。注意是session的創(chuàng)建和銷毀動(dòng)作觸發(fā)listener
    而不是相反。類似的與
    HttpSession有關(guān)的listener還有 HttpSessionBindingListenerHttpSessionActivationListener HttpSessionAttributeListener 

        5
    、存放在session中的對(duì)象必須是可序列化的嗎 


     
    不是必需的。要求對(duì)象可序列化只是為了session能夠在集群中被復(fù)制或者能夠持久保存或者在必要時(shí)server能夠暫時(shí)把session交換出內(nèi)存。
    Weblogic Serversession中放置一個(gè)不可序列化的對(duì)象在控制臺(tái)上會(huì)收到一個(gè)警告。我所用過(guò)的某個(gè)iPlanet版本如果session中有不可序列化的對(duì)象,
    session銷毀時(shí)會(huì)有一個(gè)Exception,很奇怪。


        6
    、如何才能正確的應(yīng)付客戶端禁止cookie的可能性
     
        對(duì)所有的URL使用URL重寫(xiě),包括超鏈接,formaction,和重定向的URL,具體做法參見(jiàn)[6]
    http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770


        7
    、開(kāi)兩個(gè)瀏覽器窗口訪問(wèn)應(yīng)用程序會(huì)使用同一個(gè)session還是不同的session 

       
    參見(jiàn)第三小節(jié)對(duì)cookie的討論,對(duì)session來(lái)說(shuō)是只認(rèn)id不認(rèn)人,因此不同的瀏覽器,不同的窗口打開(kāi)方式以及不同的cookie存儲(chǔ)方式都會(huì)對(duì)這個(gè)問(wèn)題
    的答案有影響。
     

        8
    、如何防止用戶打開(kāi)兩個(gè)瀏覽器窗口操作導(dǎo)致的session混亂 
    這個(gè)問(wèn)題與防止表單多次提交是類似的,可以通過(guò)設(shè)置客戶端的令牌來(lái)解決。就是在服務(wù)器每次生成一個(gè)不同的id返回給客戶端,同時(shí)保存在session里,
    客戶端提交表單時(shí)必須把這個(gè)
    id也返回服務(wù)器,程序首先比較返回的id與保存在session里的值是否一致,如果不一致則說(shuō)明本次操作已經(jīng)被提交過(guò)了。
    可以參看《
    J2EE核心模式》關(guān)于表示層模式的部分。需要注意的是對(duì)于使用javascript window.open打開(kāi)的窗口,一般不設(shè)置這個(gè)id,或者使用單獨(dú)的id
    以防主窗口無(wú)法操作,建議不要再
    window.open打開(kāi)的窗口里做修改操作,這樣就可以不用設(shè)置。


        9
    、為什么在Weblogic Server中改變session的值后要重新調(diào)用一次session.setValue 


    做這個(gè)動(dòng)作主要是為了在集群環(huán)境中提示Weblogic Server session中的值發(fā)生了改變,需要向其他服務(wù)器進(jìn)程復(fù)制新的session值。


       10HttpSession 和 hibernate session 有什么區(qū)別?
    httpSession :

    它的產(chǎn)生:J2EE的Web程序在運(yùn)行的時(shí)候,會(huì)給每一個(gè)新的訪問(wèn)者建立一個(gè)HttpSession,這個(gè)Session是用戶身份的唯一表示。注意,是容器

    (Tomcat,Resin)自動(dòng)創(chuàng)建的。

    用途:存放這個(gè)用戶的一些經(jīng)常被用到的信息,例如:用戶名,權(quán)限。例如在購(gòu)物車程序里,存放用戶買的商品。

    銷毀:一定時(shí)間(跟容器有關(guān))內(nèi),用戶無(wú)任何動(dòng)作,session自動(dòng)銷毀。

    得到的方法:
    HttpSession session = request.getSession();
    常用方法setAttribute
    session.setAttribute(key,value);
    這樣在另一個(gè)jsp或者Servlet里,可以用
    session.getAttribute(key);得到value
    類似一個(gè)Map


    hibernate session

    它是hibernate操作數(shù)據(jù)庫(kù)的一個(gè)句柄對(duì)象。它跟上面那個(gè)Session唯一的相似處就是名字有點(diǎn)像,其他沒(méi)任何一樣的地方。
    它是hibernate表示操作數(shù)據(jù)庫(kù)的一個(gè)會(huì)話

     

    posted @ 2011-08-25 11:22 redcoatjk 閱讀(1244) | 評(píng)論 (0)編輯 收藏
     

    AOP術(shù)語(yǔ)介紹

    1. 正常的編程為從上到下的調(diào)用,執(zhí)行



    2. 加入了安全性檢查,日志這樣的代碼. 這是一個(gè)橫切的問(wèn)題,其于正常的業(yè)務(wù)毫無(wú)關(guān)系.

    橫切的問(wèn)題會(huì)散布在代碼的各個(gè)角落
    .


    3.這個(gè)橫切就是橫切性的關(guān)注點(diǎn): Cross cutting concern





    4.
    將橫切的關(guān)注點(diǎn)都放在一個(gè)類中(如動(dòng)態(tài)代理項(xiàng)目中的SecurityHandler.java).這個(gè)類就叫做切面.

       對(duì)橫切關(guān)注點(diǎn)進(jìn)行模塊化,這個(gè)模塊化的類就叫做切面類(Aspect對(duì)應(yīng)的類) ,


     

     

    5. 在切面類中對(duì)某個(gè)問(wèn)題如日志或安全性檢查的具體實(shí)現(xiàn)方法,叫做橫切關(guān)注點(diǎn)的具體實(shí)現(xiàn)(稱為Advice).






     

     

    6. 這個(gè)Advice可以進(jìn)行分類. :在業(yè)務(wù)方法執(zhí)行之前,之后.異常時(shí)候……


     

    7. Advice應(yīng)用的目標(biāo)方法范圍(那些方法之前,之后,異常….)這個(gè)過(guò)濾范圍叫做切入點(diǎn)Pointcut()


     

    8 .植入

    Advice應(yīng)用的目標(biāo)方法的過(guò)程叫做植入(Weave)

    Spring只支持針對(duì)業(yè)務(wù)方法執(zhí)行前,執(zhí)行后進(jìn)行植入. 即只支持方法級(jí)別的植入

    植入的地方就叫做連接點(diǎn).

    SpringAop是使用代理模式.

     

    橫切問(wèn)題的處理思路:

    發(fā)現(xiàn)橫切性的問(wèn)題,將其模塊化(切片).然后形成切片類,在其中實(shí)現(xiàn)這些橫切性的功能.

    posted @ 2011-06-26 21:58 redcoatjk 閱讀(204) | 評(píng)論 (0)編輯 收藏
     
    對(duì)象: pickTicket 出庫(kù)  1 : N  pickTicketDetail 出庫(kù)明細(xì)
    數(shù)據(jù)庫(kù): pickTicket的id作為pickTicketDetail 的外鍵(pickTicket.id)
    ---------
    在對(duì)pickTicketDetail 某行數(shù)據(jù)進(jìn)行insert/update/delete的事務(wù)提交給數(shù)據(jù)庫(kù)進(jìn)行持久化處理時(shí),數(shù)據(jù)庫(kù)會(huì)將
    pickTicket整個(gè)表給予只讀鎖. 此為避免修改pickTicketDetail 時(shí),pickTicket的數(shù)據(jù)進(jìn)行修改而出現(xiàn)
    pickTicketDetail中的pickTicket.id對(duì)應(yīng)在pickTicket中不存在.(即確保數(shù)據(jù)庫(kù)的數(shù)據(jù)完整性)

    發(fā)生場(chǎng)景: 事件A增刪改某表A時(shí),會(huì)對(duì)該表的所有外鍵對(duì)應(yīng)的表給予只讀鎖.如此時(shí)其他事務(wù)B正提交數(shù)據(jù)庫(kù),類似的需要鎖定事件A中已鎖定的表.
    此時(shí)2個(gè)事務(wù)都在等待對(duì)方表解鎖.產(chǎn)生死鎖.


    可以處理方案:
    1盡量縮短事務(wù)處理的時(shí)間.
    2對(duì)pickTicketDetail 增加pickTicket.id的索引.
    ------------
    相關(guān)參考:
    http://it.china-b.com/sjk/oracle/20090826/177376_1.html
    測(cè)試:

    session 1:

    SQL> delete from emp where emp.deptno=10;

    session 2:

    SQL> delete from dept where deptno=40;

    現(xiàn)象:在emp的字段deptno沒(méi)有索引時(shí)session 2等待, 有索引則不等待.

    結(jié)論:如果沒(méi)有索引時(shí),對(duì)父表的操作,會(huì)級(jí)聯(lián)加一個(gè)TM S鎖(level 4)到子表上;

    如果有索引時(shí),對(duì)父表的操作,會(huì)級(jí)聯(lián)加一個(gè)TM RS鎖(level 2)到子表上;

    這時(shí)如果子表上本身就有個(gè)TM RX鎖(這種鎖很容易產(chǎn)生,insert update delete都會(huì)產(chǎn)生這種鎖),

    TM S鎖和TM RX鎖是互斥的, TM RS鎖和TM RX鎖是相容的.


    -------

    最后:其實(shí)想記錄的是"外鍵未加索引的問(wèn)題" .此問(wèn)題可以google下了解.

    本文寫(xiě)的較亂,只為存疑記錄.有待進(jìn)一步了解學(xué)習(xí).



    posted @ 2011-05-31 19:09 redcoatjk 閱讀(161) | 評(píng)論 (0)編輯 收藏
    CALENDER
    <2011年5月>
    24252627282930
    1234567
    891011121314
    15161718192021
    22232425262728
    2930311234

    常用鏈接

    留言簿(3)

    隨筆分類(22)

    隨筆檔案(76)

    文章分類(12)

    文章檔案(17)

    搜索

    •  

    積分與排名

    • 積分 - 250573
    • 排名 - 227

    最新評(píng)論

    評(píng)論排行榜


    Powered By: 博客園
    模板提供滬江博客

    主站蜘蛛池模板: 美女无遮挡拍拍拍免费视频| 日韩一卡2卡3卡4卡新区亚洲| 亚洲 日韩 色 图网站| 亚洲成年人免费网站| 亚洲综合激情六月婷婷在线观看| 99久久国产免费中文无字幕| 久久亚洲私人国产精品vA | 性做久久久久久久免费看| 亚洲国产视频久久| 成年女人毛片免费视频| 亚洲精品V天堂中文字幕| 四虎成人精品一区二区免费网站| 国产AV无码专区亚洲AV蜜芽| 国产成人在线免费观看| 香港经典a毛片免费观看看| 亚洲精品无码专区2| 久久一区二区免费播放| 亚洲妇熟XXXX妇色黄| 亚洲免费视频在线观看| 亚洲国产精品线观看不卡| 美女裸身网站免费看免费网站 | 永久免费视频v片www| 国产精品亚洲va在线观看| 亚洲精品国产成人影院| 丝袜足液精子免费视频| 亚洲国产精品一区| 97国产免费全部免费观看| 亚洲午夜成人精品无码色欲| 免费jjzz在在线播放国产| 一个人免费观看视频在线中文| 国产亚洲日韩一区二区三区| 男人都懂www深夜免费网站| 亚洲综合激情视频| 黄网址在线永久免费观看 | 国产AV无码专区亚洲AV漫画 | 日本在线免费观看| 亚洲AV无码国产精品色| 在线免费观看国产视频| jizz日本免费| 亚洲高清在线mv| 狼友av永久网站免费观看|