??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲国产成人久久77,亚洲国产成人无码AV在线,精品国产亚洲一区二区三区http://www.tkk7.com/crabboy/zh-cnFri, 09 May 2025 18:34:41 GMTFri, 09 May 2025 18:34:41 GMT60?window.showModalDialog()"实现DIV模式弹出H口 http://www.tkk7.com/crabboy/archive/2008/05/05/198359.html虎啸龙吟虎啸龙吟Mon, 05 May 2008 02:43:00 GMThttp://www.tkk7.com/crabboy/archive/2008/05/05/198359.htmlhttp://www.tkk7.com/crabboy/comments/198359.htmlhttp://www.tkk7.com/crabboy/archive/2008/05/05/198359.html#Feedback0http://www.tkk7.com/crabboy/comments/commentRss/198359.htmlhttp://www.tkk7.com/crabboy/services/trackbacks/198359.html 
1、test.html  试?/strong>
 <html>
 <head>
   <title>试面</title>
   <style>
     .list {
       border-top:1 solid #8A2BE2;
       border-left:1 solid #8A2BE2;
       border-right:1 solid #8A2BE2;
     }
     .list td {
       border-bottom: 1 solid #8A2BE2;
     }
   </style>
   <script>
      function $(el) {
        return document.getElementById(el);
      }
      function showWin(param) {
        window.showModalDialog("dailog.htm", param, "dialogWidth:" +param.width +"px;dialogHeight:"+param.height+"px;center:yes;help:no;scroll:no;status:no;resizable:no");
      }
     
      function TB(tbid) {
        this.tb = typeof(tbid) == "string"? $(tbid): tbid;
        this.getValue = function(rowIndex, cellIndex){
          var trs = this.tb.rows[rowIndex];
          var _td = trs.cells[cellIndex];
          return _td.innerText;
        }
        this.setValue = function(rowIndex, cellIndex, value) {
          var _tr = this.tb.rows[rowIndex];
          var _td = _tr.cells[cellIndex];
          _td.innerText = value;
        }
       
        /********获取行烦?*******/
        this.findRowIndex = function(eventSrc) {
          var _tr = eventSrc; //eventSrc事g?必须在TD里获事g源是TD或TR本n
          while(_tr.tagName != "TR") {
            _tr =  _tr.parentNode;
          }
          var trs = this.tb.rows;
          for(var i = 0; i < trs.length; i++){
            if(_tr == trs[i]) return i;
          }
        }
      }
          
      function edit() {
        var tb = new TB("data");
        rIndex = tb.findRowIndex(event.srcElement);
        $("updateRowIndex").value = rIndex;
        $("userName").value = tb.getValue(rIndex, 1); //获得姓名
        $("sex").value = tb.getValue(rIndex, 2); //获得性别
        $("age").value = tb.getValue(rIndex, 3); //获得q龄
         showWin({title:"修改用户信息", width:390, height:230, _div:"openWin",parent:window});
      }
     
      function saveAndUpdateView(){
        var updateRowIndex = $("updateRowIndex").value;
        var tb = new TB($f("data")); //$f()在dailog.html定义,获到的table是父H口中的table
        tb.setValue(updateRowIndex, 1, $("userName").value);
        tb.setValue(updateRowIndex, 2, $("sex").value);
        tb.setValue(updateRowIndex, 3, $("age").value);
        close();
      }
   </script>
  
 </head>
 <body>
  <p style="margin-top:60px">
   <center>
     <table id="data" class="list" width="460px">
       <tr>
         <td>~号</td>
         <td>用户?lt;/td>
         <td>性别</td>
         <td>q龄</td>
         <td>操作</td>
       </tr>
       <tr>
         <td>1</td>
         <td>李永?lt;/td>
         <td>?lt;/td>
         <td>27</td>
         <td><span style="background:#FAEBD7;cursor:hand" onclick="edit();">&nbsp;修改&nbsp;</span></td>
       </tr>
        <tr>
         <td>2</td>
         <td>林兄</td>
         <td>?lt;/td>
         <td>27</td>
         <td><span style="background:#FAEBD7;cursor:hand" onclick="edit();">&nbsp;修改&nbsp;</span></td>
       </tr>
        <tr>
         <td>3</td>
         <td>叶兄</td>
         <td>?lt;/td>
         <td>23</td>
         <td><span style="background:#FAEBD7;cursor:hand" onclick="edit();">&nbsp;修改&nbsp;</span></td>
       </tr>
     </table>
   </center>
  </p>
 
  <!---弹出H口昄的内?--->
  <div id="openWin" style="display:none;">
    <form>
      <fieldSet>
        <legend>修改用户</legend>
        <table>
          <tr>
            <td>用户?lt;/td><td><input type="text" id="userName"/></td>
          </tr>
          <tr>
            <td>性别</td><td><input type="text" id="sex"/></td>
          </tr>
          <tr>
            <td>q龄</td><td><input type="text" id="age"/></td>
          </tr>
        </table>
      </fieldSet>
      <input type="hidden" id="updateRowIndex"/>
    </form>
    <span style="background:#FAEBD7;cursor:hand" onclick="saveAndUpdateView();">&nbsp;修改&nbsp;</span>
  </div>
 </body>
</html>

2、dailog.html H口原型

<html>
 <head>
   <script>
     var param = window.dialogArguments; //传过来的模式对话框窗口参?br />      document.title = param.title; //H口标题,必须在窗口创建前实现s
    
   /********父H口的js加蝲q来********/
     var scripts = param.parent.document.scripts;
     var _head = document.getElementsByTagName("head")[0];
     for(var n = 0; n < scripts.length; n++) {
       if(scripts[n].src) {
         var _script = newEl("script");
         _script.src = scripts[n].src;
         bind(_head, _script);
       }else{//加蝲直接在html文档中写的script
         var _script = newEl("script");
         _script.text = scripts[n].text;
          bind(_head, _script);
       }
     }
    
     /*******ҎID获得父窗口的元素*********/
     function $f(el) {
       return param.parent.document.getElementById(el);
     }
   
    /***********创徏一个HTML元素*******/
     function newEl(tagName) {
       return document.createElement(tagName);
     }
     /***********q加元素***************/
     function bind(ower, child) {
       ower.appendChild(child);
     }
     /*******在浏览器完成对象的装载后立即触发*********/
     window.onload = function() {
       var winDiv;
       if(typeof(param._div) == "string") {
         winDiv = param.parent.document.getElementById(param._div); //父窗口window对象,因ؓparam._div对象在父H口
       }else{//直接传对象过?br />          winDiv = param._div;
       }
       $("mainDiv").innerHTML = winDiv.innerHTML; //DIV内容在弹出窗口中渲染
    }
   </script>
 </head>
 <body>
 <center>
  <div id="mainDiv" style="margin-top:20px;width:90%"></div>
 </center>
 </body>
</html>


虎啸龙吟 2008-05-05 10:43 发表评论
]]>
得到准确的在Uh数统计-减少搜烦引擎的干?/title><link>http://www.tkk7.com/crabboy/archive/2008/04/21/194471.html</link><dc:creator>虎啸龙吟</dc:creator><author>虎啸龙吟</author><pubDate>Mon, 21 Apr 2008 03:37:00 GMT</pubDate><guid>http://www.tkk7.com/crabboy/archive/2008/04/21/194471.html</guid><wfw:comment>http://www.tkk7.com/crabboy/comments/194471.html</wfw:comment><comments>http://www.tkk7.com/crabboy/archive/2008/04/21/194471.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/crabboy/comments/commentRss/194471.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/crabboy/services/trackbacks/194471.html</trackback:ping><description><![CDATA[<span style="font-family: Verdana"><span style="font-size: 8pt">转自http://www.tkk7.com/flyffa/archive/2006/12/14/87722.html<br /> <br /> </span></span> <div> <h2 style="margin: 13pt 0cm"><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="font-family: 黑体">基本ҎQ?/span> </span></span></h2> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="font-family: 宋体">基本的方法,|上到处都是Q在</span> <span>java</span> <span style="font-family: 宋体">中就是在</span> <span>web.xml</span> <span style="font-family: 宋体">注册一?/span> <span>Listener</span> <span style="font-family: 宋体">Q如下:</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><listener></span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>    </span><listener-class>xp.web.SessionCounter</listener-class></span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"></listener></span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span>SessionCounter.java</span> <span style="font-family: 宋体">实现</span> <span>javax.servlet.http.HttpSessionListener</span> <span style="font-family: 宋体">接口Q分别在</span> <span>sessionCreated</span> <span style="font-family: 宋体">Ҏ?/span> <span>sessionDestroyed</span> <span style="font-family: 宋体">Ҏ中处?/span> <span>session</span> <span style="font-family: 宋体">数目?/span> </span></span></p> <p><span><span style="font-family: Verdana"><span style="font-size: 8pt">  </span></span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="font-family: 宋体">q样的方法有一定的问题Q?/span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span>1</span> <span style="font-family: 宋体">、对于真正从|页讉K的和搜烦引擎?/span> <span>spider</span> <span style="font-family: 宋体">无法区分?/span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span>2</span> <span style="font-family: 宋体">、当</span> <span>Tomcat</span> <span style="font-family: 宋体">重启Ӟ加蝲了上ơ持久化?/span> <span>session</span> <span style="font-family: 宋体">Ӟ无法准确计算在线数?/span> </span></span></p> <p><span><span style="font-family: Verdana"><span style="font-size: 8pt">  </span></span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="font-family: 宋体">W二个问题我们可以不予考虑Q这?/span> <span>tomcat</span> <span style="font-family: 宋体">容器实现不标准的问题Q我们要解决的是的第一个问题,如何知道你的讉K的是真实的?/span> </span></span></p> <p><span><span style="font-family: Verdana"><span style="font-size: 8pt">  </span></span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><strong><span><span style="font-size: 16pt; font-family: 黑体">?/span> </span><span><span style="font-size: 16pt">js </span></span><span><span style="font-size: 16pt; font-family: 黑体">l过搜烦引擎</span> </span></strong><span style="font-family: 宋体">Q?/span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="font-family: 宋体">做过</span> <span>pv</span> <span style="font-family: 宋体">l计的都知道Q可以用</span> <span>script</span> <span style="font-family: 宋体">的方式得C真实?/span> <span>pageView</span> <span style="font-family: 宋体">数目Q我们现在要做的是q样的一件事情,我们在所有的面都加入一D话Q?/span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><script type="text/javascript"></span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial">document.write ("<iframe src='/sessionCountServlet' width=0 height=0 frameborder=no border=0 MARGINWIDTH=0 MARGINHEIGHT=0 SCROLLING=no></iframe>");</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"></script></span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="font-family: 宋体">然后我们写上一?/span> <span>servlet</span> <span style="font-family: 宋体">来记录这些真正的讉K者?/span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial">import java.io.*;</span> </span></span></p> <p><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span style="font-family: Verdana"><span style="font-size: 8pt">  </span></span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial">import javax.servlet.*;</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial">import javax.servlet.http.*;</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial">public class SessionCounterServlet extends HttpServlet {</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>    </span>public SessionCounterServlet() {</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>        </span>super();</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>    </span>}</span> </span></span></p> <p><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span style="font-family: Verdana"><span style="font-size: 8pt">  </span></span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>    </span>public void doGet(HttpServletRequest request,</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>                      </span>HttpServletResponse response) throws IOException,</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>            </span>ServletException {</span> </span></span></p> <p><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span style="font-family: Verdana"><span style="font-size: 8pt">  </span></span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>        </span>process(request, response);</span> </span></span></p> <p><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span style="font-family: Verdana"><span style="font-size: 8pt">  </span></span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>    </span>}</span> </span></span></p> <p><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span style="font-family: Verdana"><span style="font-size: 8pt">  </span></span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>    </span>public void doPost(HttpServletRequest request,</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>                       </span>HttpServletResponse response) throws IOException,</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>            </span>ServletException {</span> </span></span></p> <p><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span style="font-family: Verdana"><span style="font-size: 8pt">  </span></span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>        </span>process(request, response);</span> </span></span></p> <p><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span style="font-family: Verdana"><span style="font-size: 8pt">  </span></span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>    </span>}</span> </span></span></p> <p><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span style="font-family: Verdana"><span style="font-size: 8pt">  </span></span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>    </span>public void process(HttpServletRequest request,</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>                        </span>HttpServletResponse response) throws IOException,</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>            </span>ServletException {</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>        </span>SessionCounter.put(request.getSession().getId());</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial">}</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial">}</span> </span></span></p> <p><span><span style="font-family: Verdana"><span style="font-size: 8pt">  </span></span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="font-family: 宋体">我们可以看到q个</span> <span>servlet</span> <span style="font-family: 宋体">只是做了一件事情,?/span> <span>process</span> <span style="font-family: 宋体">里面做了</span> <span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial">SessionCounter.put(request.getSession().getId());</span> <span style="font-family: 宋体">q个动作?/span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="font-family: 宋体">我们来看看我们的</span> <span>SessionCounter</span> <span style="font-family: 宋体">做了些什么:</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial">import javax.servlet.http.*;</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial">import java.util.Hashtable;</span> </span></span></p> <p><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span style="font-family: Verdana"><span style="font-size: 8pt">  </span></span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial">public class SessionCounter implements HttpSessionListener {</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>    </span>public SessionCounter() {</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>    </span>}</span> </span></span></p> <p><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span style="font-family: Verdana"><span style="font-size: 8pt">  </span></span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>    </span>public static Hashtable m_real = new Hashtable();</span> </span></span></p> <p><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span style="font-family: Verdana"><span style="font-size: 8pt">  </span></span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>    </span>private static long count = 0;</span> </span></span></p> <p><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span style="font-family: Verdana"><span style="font-size: 8pt">  </span></span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>    </span>public void sessionCreated(HttpSessionEvent e) {</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>        </span>count++;</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>    </span>}</span> </span></span></p> <p><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span style="font-family: Verdana"><span style="font-size: 8pt">  </span></span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>    </span>public void sessionDestroyed(HttpSessionEvent e) {</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>        </span>if (count > 0) {</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>            </span>count--;</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>        </span>}</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>        </span>m_real.remove(e.getSession().getId());</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>    </span>}</span> </span></span></p> <p><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span style="font-family: Verdana"><span style="font-size: 8pt">  </span></span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>    </span>public static long getSessionCount() {</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>        </span>return count;</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>    </span>}</span> </span></span></p> <p><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span style="font-family: Verdana"><span style="font-size: 8pt">  </span></span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>    </span>public static void put(String sessionId){</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>        </span>m_real.put(sessionId,"1");</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>    </span>}</span> </span></span></p> <p><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span style="font-family: Verdana"><span style="font-size: 8pt">  </span></span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>    </span>public static int getRealCount(){</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>        </span>return m_real.size();</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial"><span>    </span>}</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="background: silver 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial">}</span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="font-family: 宋体">我们记录了一个静态的</span> <span>hash</span> <span style="font-family: 宋体">表来记录Ȁzȝ态的</span> <span>sessionid</span> <span style="font-family: 宋体">Qƈ?/span> <span>session</span> <span style="font-family: 宋体">销毁的时候将q个</span> <span>sessionid</span> <span style="font-family: 宋体">|ؓI?/span> </span></span></p> <p><span style="font-family: Verdana"><span style="font-size: 8pt"><span style="font-family: 宋体">怎么?/span> <span>servlet</span> <span style="font-family: 宋体">配置?/span> <span>web</span> <span style="font-family: 宋体">应用中我׃|唆了?/span> </span></span></p> </div> <img src ="http://www.tkk7.com/crabboy/aggbug/194471.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/crabboy/" target="_blank">虎啸龙吟</a> 2008-04-21 11:37 <a href="http://www.tkk7.com/crabboy/archive/2008/04/21/194471.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JPA中的实体层次设计http://www.tkk7.com/crabboy/archive/2008/04/21/194464.html虎啸龙吟虎啸龙吟Mon, 21 Apr 2008 03:20:00 GMThttp://www.tkk7.com/crabboy/archive/2008/04/21/194464.htmlhttp://www.tkk7.com/crabboy/comments/194464.htmlhttp://www.tkk7.com/crabboy/archive/2008/04/21/194464.html#Feedback0http://www.tkk7.com/crabboy/comments/commentRss/194464.htmlhttp://www.tkk7.com/crabboy/services/trackbacks/194464.htmlq部分的内容基本与Hibernate一?JPA同样支持3U类型的l承形式:

1.Single Table Strategy ,单表{略,一张表包含基类与子cȝ所有数?很多情况下都是采用这L冗余设计,通过一个discriminator来区?/span>

2.Table Per Class Strategy ,每个子类对应一张表,每张表都拥有基类的属?/span>

3.Join Strategy ,仍然是每个子cd应一张表Q但此表中不包含基类的属?仅仅是此子类的扩展属?׃n基类的属?/span>

以一个例子来说明3U情?

一.单表{略

比如Pet作ؓ基类,Cat和Dogl承此类q拥有自q扩展属??

package com.denny_blue.ejb3.inheritance;

import java.io.Serializable;

import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "animal_type", discriminatorType = DiscriminatorType.STRING)
public class Pet implements Serializable {
 private int id;

 private String name;

 private double weight;

 public Pet() {
 }

 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 public int getId() {
  return id;
 }

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

 public String getName() {
  return name;
 }

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

 public double getWeight() {
  return weight;
 }

 public void setWeight(double weight) {
  this.weight = weight;
 }

}

Petcd的注意的就是通过@Inheritance(strategy = InheritanceType.SINGLE_TABLE)定采用单表{略,通过@DiscriminatorColumn定了标志值的字段和类型,我想熟悉hibernate的朋友对q些都应该很熟悉.然后是两个子c?

//Cat.java

package com.denny_blue.ejb3.inheritance;

import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(discriminatorType = DiscriminatorType.STRING)
@DiscriminatorValue("cat")
public class Cat extends Pet {
 private String HairBall;

 public String getHairBall() {
  return HairBall;
 }

 public void setHairBall(String hairBall) {
  HairBall = hairBall;
 }

}

//Dog.java

package com.denny_blue.ejb3.inheritance;

import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;

@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(discriminatorType=DiscriminatorType.STRING)
@DiscriminatorValue("dog")
public class Dog extends Pet {
 private String trick;

 public String getTrick() {
  return trick;
 }

 public void setTrick(String trick) {
  this.trick = trick;
 }

}

两个子类最值的x的就是@DiscriminatorValue注释,比如Cat的此gؓcat,意味着当Catcd的Entity存入数据库时,JPA自动把cat的Dlanimal_type字段,Dog的值则为dog,由此可以在同一张表中区分开两个不同的子c?

?Table per Class

采用Table Per Class{略的话Q每个子c都单独徏表,q且都独立拥有基cM的所有属?互相之间不共?在我们的例子中所要进行的修改很小,像这?

//基类

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Pet implements Serializable {
 private int id;

 private String name;

 private double weight;

........

//子类:不需要Q何设|?/span>

@Entity
public class Dog extends Pet {
 private String trick;

  .......

  .......

?Join{略

每个子类同样独立,基类也独立徏表,只不q所有的子类的表中只有扩展属?他们׃n基类的表,在我们的例子中修改下卛_:

//基类

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Pet implements Serializable {
 private int id;

 private String name;

 private double weight;

  ........

//子类

@Entity

@Inheritance(strategy = InheritanceType.JOINED)
public class Dog extends Pet {
 private String trick;

  .......

  .......

q部分的内容实在没什么新?与hibernate完全一?JAVA EE5向spring和hibernate借鉴了太多东?
{}



虎啸龙吟 2008-04-21 11:20 发表评论
]]>
oracle语句优化大全http://www.tkk7.com/crabboy/archive/2008/04/20/194289.html虎啸龙吟虎啸龙吟Sun, 20 Apr 2008 03:33:00 GMThttp://www.tkk7.com/crabboy/archive/2008/04/20/194289.htmlhttp://www.tkk7.com/crabboy/comments/194289.htmlhttp://www.tkk7.com/crabboy/archive/2008/04/20/194289.html#Feedback0http://www.tkk7.com/crabboy/comments/commentRss/194289.htmlhttp://www.tkk7.com/crabboy/services/trackbacks/194289.htmlOracle sql 性能优化调整
  1. 选用适合的ORACLE优化?br style="font-family: " />   ORACLE的优化器共有3U:
  a. RULE (Z规则)
  b. COST (Z成本)
  c. CHOOSE (选择?
  讄~省的优化器Q可以通过对init.ora文g中OPTIMIZER_MODE参数的各U声明,如RULEQCOSTQCHOOSEQALL_ROWSQFIRST_ROWS . 你当然也在SQL句或是会话(session)U对其进行覆盖?br style="font-family: " />   Z使用Z成本的优化器(CBOQ?Cost-Based Optimizer) Q?你必ȝ常运行analyze 命oQ以增加数据库中的对象统计信?object statistics)的准性?br style="font-family: " />   如果数据库的优化器模式设|ؓ选择?CHOOSE)Q那么实际的优化器模式将和是否运行过analyze命o有关?如果table已经被analyzeq, 优化器模式将自动成ؓCBO Q?反之Q数据库采用RULE形式的优化器?br style="font-family: " />   在缺省情况下QORACLE采用CHOOSE优化器,Z避免那些不必要的全表扫描(full table scan) Q?你必d量避免用CHOOSE优化器,而直接采用基于规则或者基于成本的优化器?br style="font-family: " />   2. 讉KTable的方式ORACLE 采用两种讉K表中记录的方?br style="font-family: " />   a. 全表扫描
  全表扫描是序地访问表中每条记录?ORACLE采用一ơ读入多个数据块(database block)的方式优化全表扫描?br style="font-family: " />   b. 通过ROWID讉K?br style="font-family: " />   你可以采用基于ROWID的访问方式情况,提高讉K表的效率Q?ROWID包含了表中记录的物理位置信息……ORACLE采用索引(INDEX)实现了数据和存放数据的物理位|?ROWID)之间的联pR?通常索引提供了快速访问ROWID的方法,因此那些Z索引列的查询可以得到性能上的提高?br style="font-family: " />   3. ׃nSQL语句
  Z不重复解析相同的SQL语句Q在W一ơ解析之后, ORACLESQL语句存放在内存中。这块位于系l全局区域SGA(system global area)的共享池(shared buffer pool)中的内存可以被所有的数据库用户共享?因此Q当你执行一个SQL语句(有时被称Z个游?Ӟ如果它和之前的执行过的语句完全相同, ORACLEp很快获得已经被解析的语句以及最好的执行路径?ORACLE的这个功能大大地提高了SQL的执行性能q节省了内存的用?br /> 可惜的是ORACLE只对单的表提供高速缓?cache buffering) Q这个功能ƈ不适用于多表连接查询。数据库理员必dinit.ora中ؓq个区域讄合适的参数Q当q个内存区域大Q就可以保留更多的语句,当然被共享的可能性也p大了。当你向ORACLE 提交一个SQL语句QORACLE会首先在q块内存中查扄同的语句?br />   q里需要注明的是,ORACLE对两者采取的是一U严格匹配,要达成共享,SQL语句必须完全相同(包括I格Q换行等)?br />   ׃n的语句必L三个条Ӟ
  A. 字符U的比较Q?br />   当前被执行的语句和共享池中的语句必须完全相同?br />   例如Q?br />   SELECT * FROM EMP;
  和下列每一个都不同
  SELECT * from EMP;
  Select * From Emp;
  SELECT * FROM EMP;
  B. 两个语句所指的对象必须完全相同Q?br />   例如Q?br />   用户  对象名      如何讉K
  Jack    sal_limit   private synonym
  Work_city   public synonym
  Plant_detail  public synonym
  Jill     sal_limit  private synonym
  Work_city   public synonym
  Plant_detail  table owner
  考虑一下下列SQL语句能否在这两个用户之间׃n?br />   C. 两个SQL语句中必M用相同的名字的绑定变?bind variables)
  例如Q第一l的两个SQL语句是相同的(可以׃n)Q而第二组中的两个语句是不同的(即在运行时Q赋于不同的l定变量相同的?
  a.
  selectpinQnamefrompeoplewherepin=Qblk1.pin;
  selectpinQnamefrompeoplewherepin=Qblk1.pin;
b.
  selectpinQnamefrompeoplewherepin=Qblk1.ot_ind;
  selectpinQnamefrompeoplewherepin=Qblk1.ov_ind;
  4. 选择最有效率的表名序(只在Z规则的优化器中有?
  ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名Q因此FROM子句中写在最后的?基础?driving table)被最先处理?在FROM子句中包含多个表的情况下Q你必须选择记录条数最的表作为基表。当ORACLE处理多个表时Q?会运用排序及合ƈ的方式连接它们。首先,扫描W一个表(FROM子句中最后的那个?q对记录q行zֺQ然后扫描第二个?FROM子句中最后第二个?Q最后将所有从W二个表中检索出的记录与W一个表中合适记录进行合q?br />   例如Q?br />   ?TAB1 16Q?84 条记?br />   ?TAB2 1 条记?br />   选择TAB2作ؓ基础?(最好的Ҏ)
  select count(*) from tab1Qtab2 执行旉0.96U?br />   选择TAB2作ؓ基础?(不佳的方?
  select count(*) from tab2Qtab1 执行旉26.09U?br />   如果?个以上的表连接查询, 那就需要选择交叉?intersection table)作ؓ基础表, 交叉表是指那个被其他表所引用的表?br />   例如Q?EMP表描qCLOCATION表和CATEGORY表的交集?br /> SELECT *
FROM LOCATION L ,
   CATEGORY C,
   EMP E
WHERE E.EMP_NO BETWEEN 1000 AND 2000
AND E.CAT_NO = C.CAT_NO
AND E.LOCN = L.LOCN
  比下列SQL更有效率
SELECT *
FROM EMP E ,
LOCATION L ,
   CATEGORY C
WHERE E.CAT_NO = C.CAT_NO
AND E.LOCN = L.LOCN
AND E.EMP_NO BETWEEN 1000 AND 2000
1. WHERE子句中的q接序?
  ORACLE采用自下而上的顺序解析WHERE子句Q根据这个原理,表之间的q接必须写在其他WHERE条g之前Q?那些可以qo掉最大数量记录的条g必须写在WHERE子句的末?br />   例如Q?br />   (低效Q执行时?56.3U?
  SELECT…
  FROMEMPE
  WHERESAL>50000
  ANDJOB=‘MANAGER’
  AND25<(SELECTCOUNT(*)FROMEMP
  WHEREMGR=E.EMPNO);
  (高效,执行旉10.6U?
  SELECT…
  FROMEMPE
  WHERE25<(SELECTCOUNT(*)FROMEMP
  WHEREMGR=E.EMPNO)
  ANDSAL>50000
  ANDJOB=‘MANAGER’;
  2. SELECT子句中避免?‘ * ’
  当你惛_SELECT子句中列出所有的COLUMNӞ使用动态SQL列引?‘*’ 是一个方便的Ҏ。不q的是,q是一个非怽效的Ҏ?实际上,ORACLE在解析的q程中, 会将‘*’ 依次转换成所有的列名Q?q个工作是通过查询数据字典完成的, q意味着耗费更多的时间?br />   3. 减少讉K数据库的ơ数
  当执行每条SQL语句Ӟ ORACLE在内部执行了许多工作Q?解析SQL语句Q?估算索引的利用率Q?l定变量 Q?L据块{等?由此可见Q?减少讉K数据库的ơ数 Q?p实际上减ORACLE的工作量?br />   例如Q以下有三种Ҏ可以索出雇员L?342?291的职员?br />   Ҏ1 (最低效)
  SELECTEMP_NAME,SALARY,GRADE
  FROMEMP
  WHEREEMP_NO=342;
  SELECTEMP_NAME,SALARY,GRADE
  FROMEMP
  WHEREEMP_NO=291;
  Ҏ2 (ơ低?
  DECLARE
  CURSORC1(E_NONUMBER)IS
  SELECTEMP_NAME,SALARY,GRADE
  FROMEMP
  WHEREEMP_NO=E_NO;
  BEGIN
  OPENC1(342);
  FETCHC1INTO…,..,..;
  OPENC1(291);
  FETCHC1INTO…,..,..;
  CLOSEC1;
  END;
  Ҏ3 (高效)
以下是引用片D:
  SELECTA.EMP_NAME,A.SALARY,A.GRADE,
  B.EMP_NAME,B.SALARY,B.GRADE
  FROMEMPA,EMPB
  WHEREA.EMP_NO=342
  ANDB.EMP_NO=291;
  注意Q?br />   在SQL*Plus Q?SQL*Forms和Pro*C中重新设|ARRAYSIZE参数Q?可以增加每次数据库访问的索数据量 Q徏议gؓ200.
  4. 使用DECODE函数来减处理时?br />   使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表?br />   例如Q?br />   SELECTCOUNT(*)QSUM(SAL)
  FROM EMP
  WHEREDEPT_NO=0020
  ANDENAMELIKE ‘SMITH%’;
  SELECTCOUNT(*)QSUM(SAL)
  FROM EMP
  WHEREDEPT_NO=0030
  ANDENAMELIKE ‘SMITH%’;
  你可以用DECODE函数高效地得到相同结?br />   SELECTCOUNT(DECODE(DEPT_NO,0020,’X’,NULL))D0020_COUNT,
  COUNT(DECODE(DEPT_NO,0030,’X’,NULL))D0030_COUNT,
  SUM(DECODE(DEPT_NO,0020,SAL,NULL))D0020_SAL,
  SUM(DECODE(DEPT_NO,0030,SAL,NULL))D0030_SAL
  FROMEMPWHEREENAMELIKE‘SMITH%’;
  cM的,DECODE函数也可以运用于GROUP BY 和ORDER BY子句中?br />   5. 整合单,无关联的数据库访?br />   如果你有几个单的数据库查询语句,你可以把它们整合C个查询中(即它们之间没有关系)
  例如Q?br />   SELECTNAME
  FROMEMP
  WHEREEMP_NO=1234;
  SELECTNAME
  FROMDPT
  WHEREDPT_NO=10;
  SELECTNAME
  FROMCAT
  WHERECAT_TYPE=‘RD’;
  上面?个查询可以被合ƈ成一个:
  SELECTE.NAME,D.NAME,C.NAME
  FROMCATC,DPTD,EMPE,DUALX
  WHERENVL(‘X’,X.DUMMY)=NVL(‘X’,E.ROWID(+))
  ANDNVL(‘X’,X.DUMMY)=NVL(‘X’,D.ROWID(+))
  ANDNVL(‘X’,X.DUMMY)=NVL(‘X’,C.ROWID(+))
  ANDE.EMP_NO(+)=1234
  ANDD.DEPT_NO(+)=10
  ANDC.CAT_TYPE(+)=‘RD’;

1. 删除重复记录
  最高效的删除重复记录方?( 因ؓ使用了ROWID)
DELETE FROM EMP E
WHERE E.ROWID > (SELECT MIN(X.ROWID)
            FROM EMP X
            WHERE X.EMP_NO = E.EMP_NO);
  2. 用TRUNCATE替代DELETE
  当删除表中的记录Ӟ在通常情况下, 回滚D?rollback segments ) 用来存放可以被恢复的信息?如果你没有COMMIT事务QORACLE会将数据恢复到删除之前的状?准确地说是恢复到执行删除命o之前的状?
  而当q用TRUNCATEӞ 回滚D不再存放Q何可被恢复的信息。当命oq行后,数据不能被恢复。因此很的资源被调用,执行旉也会很短?br />   (译者按Q?TRUNCATE只在删除全表适用QTRUNCATE是DDL不是DML)
  Q? 量多用COMMIT
  只要有可能,在程序中量多用COMMITQ?q样E序的性能得到提高Q需求也会因为COMMIT所释放的资源而减:COMMIT所释放的资源:
  a. 回滚D上用于恢复数据的信息?br />   b. 被程序语句获得的?br />   c. redo log buffer 中的I间
  d. ORACLE为管理上q?U资源中的内部花?br />   (译者按Q?在用COMMIT时必要注意C务的完整性,现实中效率和事务完整性往往是鱼和熊掌不可得?
  Q? 计算记录条数
  和一般的观点相反Q?count(*) 比count(1)E快 Q?当然如果可以通过索引索,对烦引列的计C旧是最快的?例如 COUNT(EMPNO)
  (译者按Q?在CSDN论坛中,曄Ҏ有过相当热烈的讨论, 作者的观点q不十分准确Q通过实际的测试,上述三种Ҏq没有显著的性能差别)
  Q? 用Where子句替换HAVING子句
  避免使用HAVING子句Q?HAVING 只会在检索出所有记录之后才对结果集q行qo?q个处理需要排序,总计{操作?如果能通过WHERE子句限制记录的数目,那就能减这斚w的开销?br />   例如Q?br />   低效
  SELECTREGIONQAVG(LOG_SIZE)
  FROMLOCATION
  GROUPBYREGION
  HAVINGREGIONREGION!=‘SYDNEY’
  ANDREGION!=‘PERTH’
  高效
  SELECTREGIONQAVG(LOG_SIZE)
  FROMLOCATION
  WHEREREGIONREGION!=‘SYDNEY’
  ANDREGION!=‘PERTH’
  GROUPBYREGION
  (译者按Q?HAVING 中的条g一般用于对一些集合函数的比较Q如COUNT() {等?除此而外Q一般的条g应该写在WHERE子句?
  6. 减少对表的查?br />   在含有子查询的SQL语句中,要特别注意减对表的查询?br />   例如Q?br />   低效
  SELECTTAB_NAME
  FROMTABLES
  WHERETAB_NAME=(SELECTTAB_NAME
  FROMTAB_COLUMNS
  WHEREVERSION=604)
  AND DB_VER=(SELECTDB_VER
  FROMTAB_COLUMNS
  WHEREVERSION=604)
  高效
  SELECTTAB_NAME
  FROMTABLES
  WHERE(TAB_NAME,DB_VER)
  =(SELECTTAB_NAME,DB_VER)
  FROMTAB_COLUMNS
  WHEREVERSION=604)
  Update 多个Column 例子Q?br />   低效Q?br />   UPDATEEMP
  SETEMP_CAT=(SELECTMAX(CATEGORY)FROMEMP_CATEGORIES)

1. 使用表的别名(Alias)
  当在SQL语句中连接多个表Ӟ 请用表的别名ƈ把别名前~于每个Column上。这样一来,可以减解析的旉q减那些由Column歧义引v的语法错误?br />   (Column歧义指的是由于SQL中不同的表具有相同的Column名,当SQL语句中出现这个ColumnӞSQL解析器无法判断这个Column的归?
  2. 用EXISTS替代IN
  在许多基于基表的查询中,Z满一个条Ӟ往往需要对另一个表q行联接。在q种情况下, 使用EXISTS(或NOT EXISTS)通常提高查询的效率?br />   低效Q?br />   SELECT*
  FROMEMP(基础?
  WHEREEMPNO>0
  ANDDEPTNOIN(SELECTDEPTNO
  FROMDEPT
  WHERELOC=‘MELB’)
  高效Q?br />   SELECT*
  FROMEMP(基础?
  WHEREEMPNO>0
  ANDEXISTS(SELECT‘X’
  FROMDEPT
  WHEREDEPT.DEPTNO=EMP.DEPTNO
  ANDLOC=‘MELB’)
  (相对来说Q用NOT EXISTS替换NOT IN 更显著地提高效率,下面指?
  3. 用NOT EXISTS替代NOT IN
  在子查询中,NOT IN子句执行一个内部的排序和合q?无论在哪U情况下QNOT IN都是最低效?(因ؓ它对子查询中的表执行了一个全表遍??Z避免使用NOT IN Q我们可以把它改写成外连?Outer Joins)或NOT EXISTS.
  例如Q?br />   SELECT…
  FROMEMP
  WHEREDEPT_NONOTIN(SELECTDEPT_NO
  FROMDEPT
  WHEREDEPT_CAT=’A’);
  Z提高效率。改写ؓQ?br />   (Ҏ一Q?高效)
  SELECT….
  FROMEMPA,DEPTB
  WHEREA.DEPT_NO=B.DEPT(+)
  ANDB.DEPT_NOISNULL
  ANDB.DEPT_CAT(+)=‘A’

1. 用EXPLAIN PLAN 分析SQL语句

  EXPLAIN PLAN 是一个很好的分析SQL语句的工P它甚臛_以在不执行SQL的情况下分析语句?通过分析Q我们就可以知道ORACLE是怎么栯接表Q用什么方式扫描表(索引扫描或全表扫?以及使用到的索引名称?/p>

  你需要按照从里到外,从上C的次序解d析的l果?EXPLAIN PLAN分析的结果是用羃q的格式排列的, 最内部的操作将被最先解读, 如果两个操作处于同一层中Q带有最操作号的将被首先执行?/p>

  NESTED LOOP是少C按照上述规则处理的操作, 正确的执行\径是查对NESTED LOOP提供数据的操作,其中操作h的被最先处理?/p>

  通过实践Q?感到q是用SQLPLUS中的SET TRACE 功能比较方便?/p>

  举例Q?/p>

SQL> list
1 SELECT *
2 FROM dept, emp
 3* WHERE emp.deptno = dept.deptno
SQL> set autotrace traceonly /*traceonly 可以不显C执行结?/
SQL> /
14 rows selected.
Execution Plan
----------------------------------------------------------
 0   SELECT STATEMENT Optimizer=CHOOSE
 1  0 NESTED LOOPS
 2  1  TABLE ACCESS (FULL) OF 'EMP'
 3  1  TABLE ACCESS (BY INDEX ROWID) OF 'DEPT'
 4  3    INDEX (UNIQUE SCAN) OF 'PK_DEPT' (UNIQUE)
Statistics
----------------------------------------------------------
      0 recursive calls
      2 db block gets
     30 consistent gets
      0 physical reads
      0 redo size
    2598 bytes sent via SQL*Net to client
    503 bytes received via SQL*Net from client
      2 SQL*Net roundtrips to/from client
      0 sorts (memory)
      0 sorts (disk)
     14 rows processed

通过以上分析Q可以得出实际的执行步骤是:

  1. TABLE ACCESS (FULL) OF 'EMP'

  2. INDEX (UNIQUE SCAN) OF 'PK_DEPT' (UNIQUE)

  3. TABLE ACCESS (BY INDEX ROWID) OF 'DEPT'

  4. NESTED LOOPS (JOINING 1 AND 3)

  注: 目前许多W三方的工具如TOAD和ORACLE本n提供的工具如OMS的SQL Analyze都提供了极其方便的EXPLAIN PLAN工具。也许喜Ƣ图形化界面的朋友们可以选用它们?/p>

  2. 用烦引提高效?/p>

  索引是表的一个概念部分,用来提高索数据的效率?实际上,ORACLE使用了一个复杂的自^衡B-treel构?通常Q通过索引查询数据比全表扫描要快?当ORACLE扑և执行查询和Update语句的最佌\径时Q?ORACLE优化器将使用索引?同样在联l多个表时用烦引也可以提高效率?另一个用烦引的好处是,它提供了主键(primary key)的唯一性验证?/p>

  除了那些LONG或LONG RAW数据cdQ?你可以烦引几乎所有的列?通常Q?在大型表中用烦引特别有效?当然Q你也会发现Q?在扫描小表时Q用烦引同栯提高效率?/p>

  虽然使用索引能得到查询效率的提高Q但是我们也必须注意到它的代仗?索引需要空间来存储Q也需要定期维护, 每当有记录在表中增减或烦引列被修ҎQ?索引本n也会被修攏V?q意味着每条记录的INSERT Q?DELETE Q?UPDATEؓ此多付出4 Q?5 ơ的盘I/O . 因ؓ索引需要额外的存储I间和处理,那些不必要的索引反而会使查询反应时间变慢?/p>

  定期的重构烦引是有必要的?/p>

  ALTER INDEX REBUILD

  3. 索引的操?/p>

  ORACLE对烦引有两种讉K模式?/p>

  索引唯一扫描 ( INDEX UNIQUE SCAN)

  大多数情况下Q?优化器通过WHERE子句讉KINDEX.

表LODGING有两个烦?Q?建立在LODGING列上的唯一性烦引LODGING_PK和徏立在MANAGER列上的非唯一性烦引LODGING$MANAGER.

  SELECT*
  FROMLODGING
  WHERELODGING=‘ROSEHILL’;

  在内?Q?上述SQL被分成两步执行Q?首先 Q?LODGING_PK 索引通过索引唯一扫描的方式被讉K Q?获得相对应的ROWIDQ?通过ROWID讉K表的方式执行下一步检索?/p>

  如果被检索返回的列包括在INDEX列中QORACLE不执行W二步的处理(通过ROWID讉K??因ؓ索数据保存在索引中, 单单讉K索引可以完全满x询结果?/p>

  下面SQL只需要INDEX UNIQUE SCAN 操作?/p>

  SELECTLODGING
  FROMLODGING
  WHERELODGING=‘ROSEHILL’;

  索引范围查询(INDEX RANGE SCAN)

  适用于两U情况:

  1. Z一个范围的?/p>

  2. Z非唯一性烦引的?/p>

  ?Q?/p>

  SELECT LODGING FROM LODGING WHERE LODGING LIKE ‘M%’;

  WHERE子句条g包括一pd| ORACLE通过索引范围查询的方式查询LODGING_PK . ׃索引范围查询返回一l| 它的效率p比烦引唯一扫描低一些?/p>

  ?Q?/p>

  SELECTLODGING
  FROMLODGING
  WHEREMANAGER=‘BILLGATES’;

  q个SQL的执行分两步Q?LODGING$MANAGER的烦引范围查?得到所有符合条件记录的ROWID) 和下一步同qROWID讉K表得到LODGING列的倹{?׃LODGING$MANAGER是一个非唯一性的索引Q数据库不能对它执行索引唯一扫描?/p>

  ׃SQLq回LODGING列,而它q不存在于LODGING$MANAGER索引中, 所以在索引范围查询后会执行一个通过ROWID讉K表的操作?/p>


  WHERE子句中, 如果索引列所对应的值的W一个字W由通配W?WILDCARD)开始, 索引不被采用。在q种情况下,ORACLE用全表扫描?/p>

  SELECTLODGING
  FROMLODGING
  WHEREMANAGERLIKE‘%HANMAN’;

1. 基础表的选择

  基础?Driving Table)是指被最先访问的?通常以全表扫描的方式被访??Ҏ优化器的不同Q?SQL语句中基表的选择是不一L?/p>

  如果你用的是CBO (COST BASED OPTIMIZER)Q优化器会检查SQL语句中的每个表的物理大小Q烦引的状态,然后选用p最低的执行路径?/p>

  如果你用RBO (RULE BASED OPTIMIZER) Q?q且所有的q接条g都有索引对应Q?在这U情况下Q?基础表就是FROM 子句中列在最后的那个表?/p>

  举例Q?/p>

  SELECTA.NAMEQB.MANAGER
  FROM WORKERAQ?br />   LODGINGB
  WHERE A.LODGING=B.LODING;

  ׃LODGING表的LODING列上有一个烦引, 而且WORKER表中没有相比较的索引Q?WORKER表将被作为查询中的基表?/p>

  2. 多个q等的烦?/p>

  当SQL语句的执行\径可以用分布在多个表上的多个烦引时Q?ORACLE会同时用多个烦引ƈ在运行时对它们的记录q行合ƈQ?索出仅对全部索引有效的记录?/p>

  在ORACLE选择执行路径Ӟ唯一性烦引的{高于非唯一性烦引?然而这个规则只有当WHERE子句中烦引列和常量比较才有效。如果烦引列和其他表的烦引类相比较?q种子句在优化器中的{是非怽的?/p>

  如果不同表中两个惛_{的烦引将被引用, FROM子句中表的顺序将军_哪个会被率先使用?FROM子句中最后的表的索引有最高的优先U?/p>

  如果相同表中两个惛_{的烦引将被引用, WHERE子句中最先被引用的烦引将有最高的优先U?/p>

  举例Q?/p>

  DEPTNO上有一个非唯一性烦引,EMP_CAT也有一个非唯一性烦引?/p>

  SELECTENAMEQ?br />   FROMEMP
  WHEREDEPT_NO=20
  ANDEMP_CAT=‘A’;
q里QDEPTNO索引被最先检索,然后同EMP_CAT索引索出的记录进行合q?执行路径如下Q?br />   TABLEACCESSBYROWIDONEMP
  AND-EQUAL
  INDEXRANGESCANONDEPT_IDX
  INDEXRANGESCANONCAT_IDX
  3. {式比较和范围比?br />   当WHERE子句中有索引列, ORACLE不能合ƈ它们QORACLE用范围比较?br />   举例Q?br />   DEPTNO上有一个非唯一性烦引,EMP_CAT也有一个非唯一性烦引?br />   SELECTENAME
  FROMEMP
  WHEREDEPTNO>20
  ANDEMP_CAT=‘A’;
  q里只有EMP_CAT索引被用刎ͼ然后所有的记录逐条与DEPTNO条gq行比较?执行路径如下Q?br />   TABLEACCESSBYROWIDONEMP
  INDEXRANGESCANONCAT_IDX
  4. 不明的索引{
  当ORACLE无法判断索引的等U高低差别,优化器将只用一个烦引,它就是在WHERE子句中被列在最前面的?br />   举例Q?br />   DEPTNO上有一个非唯一性烦引,EMP_CAT也有一个非唯一性烦引?br />   SELECTENAME
  FROMEMP
  WHEREDEPTNO>20
  ANDEMP_CAT>‘A’;
  q里Q?ORACLE只用CDEPT_NO索引?执行路径如下Q?br />   TABLEACCESSBYROWIDONEMP
  INDEXRANGESCANONDEPT_IDX
  译者按Q我们来试一下以下这U情况:
 SQL> select index_nameQ?uniqueness from user_indexes where table_name = 'EMP'Q?br />   INDEX_NAME           UNIQUENES
  ------------------------------ ---------
  EMPNO             UNIQUE
  EMPTYPE            NONUNIQUE
  SQL> select * from emp where empno >= 2 and emp_type = 'A' Q?br />   no rows selected
  Execution Plan
  ----------------------------------------------------------
  0   SELECT STATEMENT Optimizer=CHOOSE
  1  0  TABLE ACCESS QBY INDEX ROWIDQ?OF 'EMP'
  2  1   INDEX QRANGE SCANQ?OF 'EMPTYPE' QNON-UNIQUE
  虽然EMPNO是唯一性烦引,但是׃它所做的是范围比较, {要比非唯一性烦引的{式比较?
  5. 强制索引失效
  如果两个或以上烦引具有相同的{Q你可以强制命oORACLE优化器用其中的一?通过它,索出的记录数量少) .
  举例Q?br />   SELECTENAME
  FROMEMP
  WHEREEMPNO=7935
  ANDDEPTNO+0=10/*DEPTNO上的索引失?/
  ANDEMP_TYPE||‘’=‘A’/*EMP_TYPE上的索引失?/
  q是一U相当直接的提高查询效率的办法?但是你必}慎考虑q种{略Q一般来_只有在你希望单独优化几个SQL时才能采用它?br />   q里有一个例子关于何旉用这U策略,
  假设在EMP表的EMP_TYPE列上有一个非唯一性的索引而EMP_CLASS上没有烦引?br />   SELECTENAME
  FROMEMP
  WHEREEMP_TYPE=‘A’
  ANDEMP_CLASS=‘X’;
  优化器会注意到EMP_TYPE上的索引q用它?q是目前唯一的选择?如果Q一D|间以后, 另一个非唯一性徏立在EMP_CLASS上,优化器必d两个索引q行选择Q在通常情况下,优化器将使用两个索引q在他们的结果集合上执行排序及合q?然而,如果其中一个烦?EMP_TYPE)接近于唯一性而另一个烦?EMP_CLASS)上有几千个重复的倹{?排序及合q就会成ZU不必要的负担?在这U情况下Q你希望使优化器屏蔽掉EMP_CLASS索引?br />   用下面的Ҏ可以解决问题?br />   SELECTENAME
  FROMEMP
  WHEREEMP_TYPE=‘A’
  ANDEMP_CLASS||‘’=‘X’;

1. 避免在烦引列上用计?

  WHERE子句中,如果索引列是函数的一部分。优化器不使用索引而用全表扫描?/p>

  举例Q?/p>

  低效Q?/p>

  SELECT…
  FROMDEPT
  WHERESAL*12>25000;

  高效Q?/p>

  SELECT…
  FROMDEPT
  WHERESAL>25000/12;

  Q这是一个非常实用的规则Q请务必牢记

  2. 自动选择索引

  如果表中有两个以?包括两个)索引Q其中有一个唯一性烦引,而其他是非唯一性?/p>

  在这U情况下QORACLE用唯一性烦引而完全忽略非唯一性烦引?/p>

  举例Q?/p>

  SELECTENAME
  FROMEMP
  WHEREEMPNO=2326
  ANDDEPTNO=20;

  q里Q只有EMPNO上的索引是唯一性的Q所以EMPNO索引用来检索记录?/p>

  TABLEACCESSBYROWIDONEMP
  INDEXUNIQUESCANONEMP_NO_IDX

  3. 避免在烦引列上用NOT

  通常Q我们要避免在烦引列上用NOTQ?NOT会生在和在索引列上使用函数相同的媄响?当ORACLE“遇到”NOTQ他׃停止使用索引转而执行全表扫描?/p>

  举例Q?/p>

  低效Q?(q里Q不使用索引)

  SELECT…
  FROMDEPT
  WHEREDEPT_CODENOT=0;

  高效Q?(q里Q用了索引)

  SELECT…
  FROMDEPT
  WHEREDEPT_CODE>0;

  需要注意的是,在某些时候, ORACLE优化器会自动NOT转化成相对应的关pL作符?/p>

  NOT > to <=

  NOT >= to <

  NOT < to >=

  NOT <= to >

  Q在q个例子中,作者犯了一些错误?例子中的低效率SQL是不能被执行的?/p>

  我做了一些测试:

SQL> select * from emp where NOT empno > 1Q?br />  no rows selected
 Execution Plan
 ----------------------------------------------------------
  0   SELECT STATEMENT Optimizer=CHOOSE
 1  0  TABLE ACCESS QBY INDEX ROWIDQ?OF 'EMP'
 2  1   INDEX QRANGE SCANQ?OF 'EMPNO' QUNIQUEQ?br />   SQL> select * from emp where empno <= 1Q?br />  no rows selected
 Execution Plan
 ----------------------------------------------------------
  0   SELECT STATEMENT Optimizer=CHOOSE
 1  0  TABLE ACCESS QBY INDEX ROWIDQ?OF 'EMP'
 2  1   INDEX QRANGE SCANQ?OF 'EMPNO' QUNIQUEQ?/p>

  两者的效率完全一P也许q符合作者关?#8220; 在某些时候, ORACLE优化器会自动NOT转化成相对应的关pL作符” 的观炏V?/p>

  4. ?gt;=替代>

  如果DEPTNO上有一个烦引,

  高效Q?/p>

  SELECT*
  FROMEMP
  WHEREDEPTNO>=4

  低效Q?/p>

  SELECT*
  FROMEMP
  WHEREDEPTNO>3

  两者的区别在于Q?前者DBMS直接蟩到第一个DEPT{于4的记录而后者将首先定位到DEPTNO=3的记录ƈ且向前扫描到W一个DEPT大于3的记录?br />

1. 避免在烦引列上用计?

  WHERE子句中,如果索引列是函数的一部分。优化器不使用索引而用全表扫描?/p>

  举例Q?/p>

  低效Q?/p>

  SELECT…
  FROMDEPT
  WHERESAL*12>25000;

  高效Q?/p>

  SELECT…
  FROMDEPT
  WHERESAL>25000/12;

  Q这是一个非常实用的规则Q请务必牢记

  2. 自动选择索引

  如果表中有两个以?包括两个)索引Q其中有一个唯一性烦引,而其他是非唯一性?/p>

  在这U情况下QORACLE用唯一性烦引而完全忽略非唯一性烦引?/p>

  举例Q?/p>

  SELECTENAME
  FROMEMP
  WHEREEMPNO=2326
  ANDDEPTNO=20;

  q里Q只有EMPNO上的索引是唯一性的Q所以EMPNO索引用来检索记录?/p>

  TABLEACCESSBYROWIDONEMP
  INDEXUNIQUESCANONEMP_NO_IDX

  3. 避免在烦引列上用NOT

  通常Q我们要避免在烦引列上用NOTQ?NOT会生在和在索引列上使用函数相同的媄响?当ORACLE“遇到”NOTQ他׃停止使用索引转而执行全表扫描?/p>

  举例Q?/p>

  低效Q?(q里Q不使用索引)

  SELECT…
  FROMDEPT
  WHEREDEPT_CODENOT=0;

  高效Q?(q里Q用了索引)

  SELECT…
  FROMDEPT
  WHEREDEPT_CODE>0;

  需要注意的是,在某些时候, ORACLE优化器会自动NOT转化成相对应的关pL作符?/p>

  NOT > to <=

  NOT >= to <

  NOT < to >=

  NOT <= to >

  Q在q个例子中,作者犯了一些错误?例子中的低效率SQL是不能被执行的?/p>

  我做了一些测试:

SQL> select * from emp where NOT empno > 1Q?br />  no rows selected
 Execution Plan
 ----------------------------------------------------------
  0   SELECT STATEMENT Optimizer=CHOOSE
 1  0  TABLE ACCESS QBY INDEX ROWIDQ?OF 'EMP'
 2  1   INDEX QRANGE SCANQ?OF 'EMPNO' QUNIQUEQ?br />   SQL> select * from emp where empno <= 1Q?br />  no rows selected
 Execution Plan
 ----------------------------------------------------------
  0   SELECT STATEMENT Optimizer=CHOOSE
 1  0  TABLE ACCESS QBY INDEX ROWIDQ?OF 'EMP'
 2  1   INDEX QRANGE SCANQ?OF 'EMPNO' QUNIQUEQ?/p>

  两者的效率完全一P也许q符合作者关?#8220; 在某些时候, ORACLE优化器会自动NOT转化成相对应的关pL作符” 的观炏V?/p>

  4. ?gt;=替代>

  如果DEPTNO上有一个烦引,

  高效Q?/p>

  SELECT*
  FROMEMP
  WHEREDEPTNO>=4

  低效Q?/p>

  SELECT*
  FROMEMP
  WHEREDEPTNO>3

  两者的区别在于Q?前者DBMS直接蟩到第一个DEPT{于4的记录而后者将首先定位到DEPTNO=3的记录ƈ且向前扫描到W一个DEPT大于3的记录?br />

 {http://blog.chinaunix.net/u/20483/showart_546882.html}



虎啸龙吟 2008-04-20 11:33 发表评论
]]>
用JavaScript实现本地~存http://www.tkk7.com/crabboy/archive/2008/04/20/194285.html虎啸龙吟虎啸龙吟Sun, 20 Apr 2008 03:10:00 GMThttp://www.tkk7.com/crabboy/archive/2008/04/20/194285.htmlhttp://www.tkk7.com/crabboy/comments/194285.htmlhttp://www.tkk7.com/crabboy/archive/2008/04/20/194285.html#Feedback0http://www.tkk7.com/crabboy/comments/commentRss/194285.htmlhttp://www.tkk7.com/crabboy/services/trackbacks/194285.html

虎啸龙吟 2008-04-20 11:10 发表评论
]]>
ext中namespace命名规则http://www.tkk7.com/crabboy/archive/2008/03/20/187396.html虎啸龙吟虎啸龙吟Thu, 20 Mar 2008 01:11:00 GMThttp://www.tkk7.com/crabboy/archive/2008/03/20/187396.htmlhttp://www.tkk7.com/crabboy/comments/187396.htmlhttp://www.tkk7.com/crabboy/archive/2008/03/20/187396.html#Feedback0http://www.tkk7.com/crabboy/comments/commentRss/187396.htmlhttp://www.tkk7.com/crabboy/services/trackbacks/187396.html

虎啸龙吟 2008-03-20 09:11 发表评论
]]>
带checkBox下拉?/title><link>http://www.tkk7.com/crabboy/archive/2008/03/20/187393.html</link><dc:creator>虎啸龙吟</dc:creator><author>虎啸龙吟</author><pubDate>Thu, 20 Mar 2008 01:08:00 GMT</pubDate><guid>http://www.tkk7.com/crabboy/archive/2008/03/20/187393.html</guid><wfw:comment>http://www.tkk7.com/crabboy/comments/187393.html</wfw:comment><comments>http://www.tkk7.com/crabboy/archive/2008/03/20/187393.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/crabboy/comments/commentRss/187393.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/crabboy/services/trackbacks/187393.html</trackback:ping><description><![CDATA[http://www.smellcode.cn/index.php/javascript/jiyuext20dehanyoucheckboxdetree/ <img src ="http://www.tkk7.com/crabboy/aggbug/187393.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/crabboy/" target="_blank">虎啸龙吟</a> 2008-03-20 09:08 <a href="http://www.tkk7.com/crabboy/archive/2008/03/20/187393.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JFreeChart?/title><link>http://www.tkk7.com/crabboy/archive/2008/03/17/186844.html</link><dc:creator>虎啸龙吟</dc:creator><author>虎啸龙吟</author><pubDate>Mon, 17 Mar 2008 12:14:00 GMT</pubDate><guid>http://www.tkk7.com/crabboy/archive/2008/03/17/186844.html</guid><wfw:comment>http://www.tkk7.com/crabboy/comments/186844.html</wfw:comment><comments>http://www.tkk7.com/crabboy/archive/2008/03/17/186844.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/crabboy/comments/commentRss/186844.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/crabboy/services/trackbacks/186844.html</trackback:ping><description><![CDATA[http://www.tkk7.com/amigoxie/archive/2008/02/20/180779.html <img src ="http://www.tkk7.com/crabboy/aggbug/186844.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/crabboy/" target="_blank">虎啸龙吟</a> 2008-03-17 20:14 <a href="http://www.tkk7.com/crabboy/archive/2008/03/17/186844.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一片关于JMS的文?/title><link>http://www.tkk7.com/crabboy/archive/2008/03/09/184838.html</link><dc:creator>虎啸龙吟</dc:creator><author>虎啸龙吟</author><pubDate>Sun, 09 Mar 2008 07:15:00 GMT</pubDate><guid>http://www.tkk7.com/crabboy/archive/2008/03/09/184838.html</guid><wfw:comment>http://www.tkk7.com/crabboy/comments/184838.html</wfw:comment><comments>http://www.tkk7.com/crabboy/archive/2008/03/09/184838.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/crabboy/comments/commentRss/184838.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/crabboy/services/trackbacks/184838.html</trackback:ping><description><![CDATA[http://www.tkk7.com/pdw2009/archive/2006/05/10/45461.html <img src ="http://www.tkk7.com/crabboy/aggbug/184838.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/crabboy/" target="_blank">虎啸龙吟</a> 2008-03-09 15:15 <a href="http://www.tkk7.com/crabboy/archive/2008/03/09/184838.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>源码分析:HashMap http://www.tkk7.com/crabboy/archive/2006/07/09/57326.html虎啸龙吟虎啸龙吟Sun, 09 Jul 2006 03:38:00 GMThttp://www.tkk7.com/crabboy/archive/2006/07/09/57326.htmlhttp://www.tkk7.com/crabboy/comments/57326.htmlhttp://www.tkk7.com/crabboy/archive/2006/07/09/57326.html#Feedback3http://www.tkk7.com/crabboy/comments/commentRss/57326.htmlhttp://www.tkk7.com/crabboy/services/trackbacks/57326.html 

HashMap是Java新Collection Framework中用来代替HashTable的一个实玎ͼHashMap和HashTable的区别是Q?HashMap是未l同步的Q而且允许null倹{HashTablel承DictionaryQ而且使用了EnumerationQ所以被不要使用?br />HashMap的声明如下:
public class HashMap extends AbstractMap implements Map, Cloneable,Serializable
有关AbstractMapQ?a >http://blog.csdn.net/treeroot/archive/2004/09/20/110343.aspx
有关MapQ?a >http://blog.csdn.net/treeroot/archive/2004/09/20/110331.aspx
有关CloneableQ?a >http://blog.csdn.net/treeroot/archive/2004/09/07/96936.aspx
q个cL较复杂,q里只是重点分析了几个方法,特别是后面涉及到很多内部c都没有解释
不过都比较简单?/p>

static final int DEFAULT_INITIAL_CAPACITY = 16; 默认初始化大?/p>

static final int MAXIMUM_CAPACITY = 1 << 30; 最大初始化大小

static final float DEFAULT_LOAD_FACTOR = 0.75f; 默认加蝲因子

transient Entry[] table; 一个Entrycd的数l,数组的长度ؓ2的指数?/p>

transient int size; 映射的个?/p>

int threshold; 下一ơ扩Ҏ的?/p>

final float loadFactor; 加蝲因子

transient volatile int modCount; 修改ơ数

public HashMap(int initialCapacity, float loadFactor) {
   if (initialCapacity < 0)
     throw new IllegalArgumentException("Illegal initial capacity: " +initialCapacity);
   if (initialCapacity > MAXIMUM_CAPACITY)
     initialCapacity = MAXIMUM_CAPACITY;
   if (loadFactor <= 0 || Float.isNaN(loadFactor))
     throw new IllegalArgumentException("Illegal load factor: " +loadFactor);
   int capacity = 1;
   while (capacity < initialCapacity)
     capacity <<= 1;
   this.loadFactor = loadFactor;
   threshold = (int)(capacity * loadFactor);
   table = new Entry[capacity];
   init();
}

public HashMap(int initialCapacity) {
   this(initialCapacity, DEFAULT_LOAD_FACTOR);
}

public HashMap() {
   this.loadFactor = DEFAULT_LOAD_FACTOR;
   threshold = (int)(DEFAULT_INITIAL_CAPACITY);
      注意Q这里应该是一个失误! 应该是:threshold =(int)(DEFAULT_INITIAL_CAPACITY * loadFactor);
   table = new Entry[DEFAULT_INITIAL_CAPACITY];
   init();
}

public HashMap(Map m) {
   this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, DEFAULT_INITIAL_CAPACITY),                                   DEFAULT_LOAD_FACTOR);
   putAllForCreate(m);
}

void init() {}

static final Object NULL_KEY = new Object();

static Object maskNull(Object key){
   return (key == null ? NULL_KEY : key);
}

static Object unmaskNull(Object key) {
   return (key == NULL_KEY ? null : key);
}

static int hash(Object x) {
   int h = x.hashCode();
   h += ~(h << 9);
   h ^= (h >>> 14);
   h += (h << 4);
   h ^= (h >>> 10);
return h;
}
在HashTable中没有这个方法,也就是说HashTable中是直接用对象的hashCode|但是HashMap做了改进 用这个算法来获得哈希倹{?/p>

static boolean eq(Object x, Object y) {
   return x == y || x.equals(y);
}

static int indexFor(int h, int length) {
   return h & (length-1);
}
Ҏ哈希值和数组的长度来q回该hash值在数组中的位置Q只是简单的与关pR?/p>

public int size() {
   return size;
}

public boolean isEmpty() {
  return size == 0;
}

public Object get(Object key) {
   Object k = maskNull(key);
   int hash = hash(k);
   int i = indexFor(hash, table.length);
   Entry e = table[i];
   while (true) {
     if (e == null) return e;
     if (e.hash == hash && eq(k, e.key)) return e.value;
     e = e.next;
   }
}
q个Ҏ是获取数据的ҎQ首先获得哈希|q里把null值掩CQƈ且hash值经q函数hash()修正?然后计算该哈希值在数组中的索引倹{如果该索引处的引用为nullQ表CHashMap中不存在q个映射?否则的话遍历整个链表Q这里找Cp?如果没有扑ֈ遍历到链表末尾Q返回null。这里的比较是这LQe.hash==hash && eq(k,e.key) 也就是说如果hash不同p定认Z相等Qeqp短\了,只有?hash相同的情况下才调用equalsҎ。现在我们该明白Object中说的如果两个对象equalsq回trueQ他们的 hashCode应该相同的道理了吧。假如两个对象调用equalsq回trueQ但是hashCode不一P那么在HashMap 里就认ؓ他们不相{?/span>

public boolean containsKey(Object key) {
   Object k = maskNull(key);
   int hash = hash(k);
   int i = indexFor(hash, table.length);
   Entry e = table[i];
   while (e != null) {
     if (e.hash == hash && eq(k, e.key)) return true;
     e = e.next;
   }
  return false;
}
q个Ҏ比上面的单,先找到哈希位|,再遍历整个链表,如果扑ֈp回true?/p>Entry getEntry(Object key) {
   Object k = maskNull(key);
   int hash = hash(k);
   int i = indexFor(hash, table.length);
   Entry e = table[i];
   while (e != null && !(e.hash == hash && eq(k, e.key)))
     e = e.next;
   return e;
}
q个ҎҎkeyD回Entry节点Q也是先获得索引位置Q再遍历链表Q如果没有找到返回的是null?

public Object put(Object key, Object value) {
   Object k = maskNull(key);
   int hash = hash(k);
   int i = indexFor(hash, table.length);
   for (Entry e = table[i]; e != null; e = e.next) {
     if (e.hash == hash && eq(k, e.key)) {
       Object oldValue = e.value;
       e.value = value;
       e.recordAccess(this);
       return oldValue;
     }
   }
   modCount++;
   addEntry(hash, k, value, i);
   return null;
}
首先获得hash索引位置Q如果该位置的引用ؓnullQ那么直接插入一个映,q回null。如果此处的引用不是nullQ必遍历链表,如果扑ֈ一个相同的keyQ那么就更新该valueQ同时返回原来的value倹{如果遍历完了没有找刎ͼ说明该keyg存在Q还是插入一个映。如果hashD够离散的话,也就是说该烦引没有被使用的话Q那么不不用遍历链表了。相反,如果hashgLQ极端的说如果是常数的话Q所有的映射都会在这一个链表上Q效率会极其低下。这里D一个最单的例子Q写?br />个不同的cM为key插入到HashMap中,效率会远q不同?br />class Good{
  int i;
  public Good(int i){
   this.i=i;
  }
  public boolean equals(Object o){
   return (o instanceof Good) && (this.i==((Good)o).i)
  }
  public int hashCode(){
   return i;
  }
}
class Bad{
  int i;
  public Good(int i){
    this.i=i;
  }
  public boolean equals(Object o){
    return (o instanceof Good) && (this.i==((Good)o).i)
  }
  public int hashCode(){
   return 0;
  }
}
执行代码Q?br />Map m1=new HashMap();
Map m2=new HashMap();
for(int i=0;i<100;i++){
  m1.put(new Good(i),new Integer(i)); //q里效率非常?br />}
for(int i=0;i<100;i++){
  m2.put(new Bad(i),new Integer(i)); //q里几乎要崩?br />}
上面的是两个非常极端的例子,执行一下就知道差别有多大?/span>

private void putForCreate(Object key, Object value) {
   Object k = maskNull(key);
   int hash = hash(k);
   int i = indexFor(hash, table.length);
   for (Entry e = table[i]; e != null; e = e.next) {
     if (e.hash == hash && eq(k, e.key)) {
        e.value = value;
        return;
     }
   }
   createEntry(hash, k, value, i);
}

void putAllForCreate(Map m) {
   for (Iterator i = m.entrySet().iterator(); i.hasNext(); ) {
     Map.Entry e = (Map.Entry) i.next();
     putForCreate(e.getKey(), e.getValue());
   }
}
上面的两个方法是被构造函数和cloneҎ调用的?/p>

void resize(int newCapacity) {
   Entry[] oldTable = table;
   int oldCapacity = oldTable.length;
   if (size < threshold || oldCapacity > newCapacity)
     return;
   Entry[] newTable = new Entry[newCapacity];
   transfer(newTable);
   table = newTable;
   threshold = (int)(newCapacity * loadFactor);
}
q个Ҏ在需要的时候重新分配空_相当于ArrayList的ensureCapacityҎQ不q这个更加复杂?br />

void transfer(Entry[] newTable) {
   Entry[] src = table;
   int newCapacity = newTable.length;
   for (int j = 0; j < src.length; j++) {
     Entry e = src[j];
     if (e != null) {
       src[j] = null;
       do {
          Entry next = e.next;
          int i = indexFor(e.hash, newCapacity);
          e.next = newTable[i];
          newTable[i] = e;
          e = next;
       } while (e != null);
     }
   }
}
遍历原来的数l,如果该Entry不是null的话Q说明有映射Q然后遍历这个链表,把所有的映射插入到新的数l中Q注意这里要从新计算索引位置?/p>

public void putAll(Map t) {
   int n = t.size();
   if (n == 0)
     return;
   if (n >= threshold) {
     n = (int)(n / loadFactor + 1);
     if (n > MAXIMUM_CAPACITY)
       n = MAXIMUM_CAPACITY;
     int capacity = table.length;
     while (capacity < n) capacity <<= 1;
       resize(capacity);
   }
   for (Iterator i = t.entrySet().iterator(); i.hasNext(); ) {
     Map.Entry e = (Map.Entry) i.next();
     put(e.getKey(), e.getValue());
   }
}
q个Ҏ先确定是否需要扩大空_然后循环调用putҎ?/p>

public Object remove(Object key) {
   Entry e = removeEntryForKey(key);
   return (e == null ? e : e.value);
}

Entry removeEntryForKey(Object key) {
   Object k = maskNull(key);
   int hash = hash(k);
   int i = indexFor(hash, table.length);
   Entry prev = table[i];
   Entry e = prev;
   while (e != null) {  如果e==null表示不存?br />     Entry next = e.next;
     if (e.hash == hash && eq(k, e.key)) {
       modCount++;
       size--;
       if (prev == e)
         table[i] = next; 链表的第一个元素就是要删除的,q里最好加一?e.next=null.
       else
         prev.next = next; 存在担不是链表的W一个元素, q里最好加一?e.next=null.
       e.recordRemoval(this);
       return e;
     }
     prev = e;
     e = next;
   }
  return e;   q里其实是return null;
}
q个Ҏ其实也不复杂Q也是遍历链表,q里加一句e.next=null,可以改ؓ
if(prev==e)
  table[i]=next;
else
  prev.next=next;
e.next=null; q一句是多加的,可以提高效率?br />q里单说明我的看法:
因ؓe是被删除的节点,删除它其实就是指向它的指针指向它的后面一个节炏V所以e可以作ؓGC回收的对象?br />可以eq有一个next指针指向我们的数据,如果e没有被回收。而且此时e.next指向的节点也变ؓ没用的了Q但?br />却有一个它的引?e.next),所以虽然e的下一个节Ҏ用了Q但是却不能作ؓGC回收的对象,除非e先被回收?br />虽然不一定会引v很大的问题,但是臛_会媄响GC的回收效率。就像数据库中的外键引用一P删除h很麻烦呀?

Entry removeMapping(Object o) {
   if (!(o instanceof Map.Entry))
     return null;
   Map.Entry entry = (Map.Entry)o;
   Object k = maskNull(entry.getKey());
   int hash = hash(k);
   int i = indexFor(hash, table.length);
   Entry prev = table[i];
   Entry e = prev;
   while (e != null) {
     Entry next = e.next;
     if (e.hash == hash && e.equals(entry)) {
       modCount++;
       size--;
       if (prev == e)
         table[i] = next;
       else
         prev.next = next;
       e.recordRemoval(this);
       return e;
      }
      prev = e;
      e = next;
   }
   return e;
}
q个Ҏ和上面的一栗?/p>

public void clear() {
   modCount++;
   Entry tab[] = table;
   for (int i = 0; i < tab.length; i++)
     tab[i] = null;
   size = 0;
}
同样可以改进

public boolean containsValue(Object value) {
   if (value == null)
     return containsNullValue();
   Entry tab[] = table;
   for (int i = 0; i < tab.length ; i++)
     for (Entry e = tab[i] ; e != null ; e = e.next)
       if (value.equals(e.value)) return true;
   return false;
}

private boolean containsNullValue() {
   Entry tab[] = table;
   for (int i = 0; i < tab.length ; i++)
     for (Entry e = tab[i] ; e != null ; e = e.next)
       if (e.value == null) return true;
   return false;
}

public Object clone() {
   HashMap result = null;
   try {
     result = (HashMap)super.clone();
   }
   catch (CloneNotSupportedException e) { // assert false; }
   result.table = new Entry[table.length];
   result.entrySet = null;
   result.modCount = 0;
   result.size = 0;
   result.init();
   result.putAllForCreate(this);
   return result;
}

static class Entry implements Map.Entry {
   final Object key;
   Object value;
   final int hash;
   Entry next;
   Entry(int h, Object k, Object v, Entry n) {
     value = v;
     next = n;
     key = k;
     hash = h;
   }
   public Object getKey() {
     return unmaskNull(key);
   }
   public Object getValue() {
     return value;
   }
   public Object setValue(Object newValue) {
      Object oldValue = value;
      value = newValue;
      return oldValue;
   }
   public boolean equals(Object o) {
     if (!(o instanceof Map.Entry)) return false;
     Map.Entry e = (Map.Entry)o;
     Object k1 = getKey();
     Object k2 = e.getKey();
     if (k1 == k2 || (k1 != null && k1.equals(k2))) {
       Object v1 = getValue();
       Object v2 = e.getValue();
       if (v1 == v2 || (v1 != null && v1.equals(v2))) return true;
     }
     return false;
    }
    public int hashCode() {
      return (key==NULL_KEY ? 0 : key.hashCode()) ^ (value==null ? 0 : value.hashCode());
    }
    public String toString() {
      return getKey() + "=" + getValue();
    }
    void recordAccess(HashMap m) { }
    void recordRemoval(HashMap m) { }
}
一个静态内部类

void addEntry(int hash, Object key, Object value, int bucketIndex) {
    table[bucketIndex] = new Entry(hash, key, value, table[bucketIndex]);
    if (size++ >= threshold)
      resize(2 * table.length);
}
注意q个ҎQ插入连表的头?br />可以写成q样更好理解Q?br />Entry oldHead=table[bucketIndex];
Entry newHead = new Entry(hash,key,value,oldHead);
table[bucketIndex]=newHead;

void createEntry(int hash, Object key, Object value, int bucketIndex) {
   table[bucketIndex] = new Entry(hash, key, value, table[bucketIndex]);
   size++;
}

private abstract class HashIterator implements Iterator {
   Entry next;
   int expectedModCount;
   int index;
   Entry current;
   HashIterator() {
     expectedModCount = modCount;
     Entry[] t = table;
     int i = t.length;
     Entry n = null;
     if (size != 0) {
       while (i > 0 && (n = t[--i]) == null) ;
     }
     next = n;
     index = i;
   }
   public boolean hasNext() {
     return next != null;
   }
   Entry nextEntry() {
     if (modCount != expectedModCount)
       throw new ConcurrentModificationException();
     Entry e = next;
    if (e == null)
       throw new NoSuchElementException();
     Entry n = e.next;
     Entry[] t = table;
     int i = index;
     while (n == null && i > 0)
        n = t[--i]; index = i;
     next = n;
     return current = e;
   }
   public void remove() {
     if (current == null)
       throw new IllegalStateException();
     if (modCount != expectedModCount)
       throw new ConcurrentModificationException();
     Object k = current.key;
     current = null;
     HashMap.this.removeEntryForKey(k);
     expectedModCount = modCount;
   }
}

private class ValueIterator extends HashIterator {
   public Object next() {
     return nextEntry().value;
   }
}

private class KeyIterator extends HashIterator {
   public Object next() {
     return nextEntry().getKey();
   }
}

private class EntryIterator extends HashIterator {
   public Object next() {
     return nextEntry();
   }
}

Iterator newKeyIterator() {
   return new KeyIterator();
}

Iterator newValueIterator() {
   return new ValueIterator();
}

Iterator newEntryIterator() {  
   return new EntryIterator();
}

private transient Set entrySet = null;

public Set keySet() {
   Set ks = keySet;
   return (ks != null ? ks : (keySet = new KeySet()));
}

private class KeySet extends AbstractSet {
   public Iterator iterator() {
     return newKeyIterator();
   }
   public int size() {
     return size;
   }
   public boolean contains(Object o) {
     return containsKey(o);
   }
   public boolean remove(Object o) {
     return HashMap.this.removeEntryForKey(o) != null;
   }
   public void clear() {
     HashMap.this.clear();
   }
}

public Collection values() {
   Collection vs = values; return (vs != null ? vs : (values = new Values()));
}

private class Values extends AbstractCollection {
   public Iterator iterator() {
     return newValueIterator();
   }
   public int size() {
     return size;
   }
   public boolean contains(Object o) {
     return containsValue(o);
   }
   public void clear() {
     HashMap.this.clear();
   }
}

public Set entrySet() {
   Set es = entrySet;
   return (es != null ? es : (entrySet = new EntrySet()));
}

private class EntrySet extends AbstractSet {
   public Iterator iterator() {
     return newEntryIterator();
   }
   public boolean contains(Object o) {
     if (!(o instanceof Map.Entry))
       return false;
     Map.Entry e = (Map.Entry)o;
     Entry candidate = getEntry(e.getKey());
     return candidate != null && candidate.equals(e);
   }
   public boolean remove(Object o) {
     return removeMapping(o) != null;
   }
   public int size() {
     return size;
   }
   public void clear() {
     HashMap.this.clear();
   }
}

private void writeObject(java.io.ObjectOutputStream s) throws IOException {
   s.defaultWriteObject();
   s.writeInt(table.length);
   s.writeInt(size);
   for (Iterator i = entrySet().iterator(); i.hasNext(); ) {
     Map.Entry e = (Map.Entry) i.next();
     s.writeObject(e.getKey());
     s.writeObject(e.getValue());
   }
}

private static final long serialVersionUID = 362498820763181265L;

private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {
   s.defaultReadObject();
   int numBuckets = s.readInt();
   table = new Entry[numBuckets];
   init();
   size = s.readInt(); for (int i=0;
   for (int i=0; i<size; i++) {
     Object key = s.readObject();
     Object value = s.readObject(); 
     putForCreate(key, value);
   }
}

int capacity() {
  return table.length;
}
float loadFactor() {
   return loadFactor;
}


作者BlogQ?/strong> http://blog.csdn.net/treeroot/


虎啸龙吟 2006-07-09 11:38 发表评论
]]>
վ֩ģ壺 ۲Ƶwwwѹۿ| ձ | ۺƷ˿| 㻨Ƶۿ| 鶹ۺ뾫Ʒ| ŮǿƨͰˬ| ڵƵվ| ޾ƷƷۺ| avۺavһ| ɫ˿ѹۿվ| ɫ͵͵ɫݺ99| ŮſȸͰƵ | þ99ڹ| þùƷѿ| Ʒ޳aƬ߹ۿ| ձxxxxɫƵ| ձþһva| ƷþƵ| ŮjƵڵ| ۺϼר| ƷƵ| 91þ޹˾Ʒɫ| ŮƵ| ɫۺϾþþƷ޹| þ޾Ʒۿ| þûɫվ| ޺ݺݳۺ| yy6080һ| avվ| ¹Ʒ| Ʒxxxxˮ޹Ʒþһ | ձvaĻþ| þ99ྫƷѹۿ| ձһ| ɫֻڵ| 91վ߹ۿ| Ʒ˿һ| һëƬ߲| ҹѸСӰ| ޾ƷƬ| һ|