`
michealBean
  • 浏览: 8508 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

匿名内部类与jdbc例子

    博客分类:
  • java
阅读更多

 

package com.qingyuan.server;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.junit.Test;

/**
 * blog reference: <[http://www.blogjava.net/jiangpingcmt1/archive/2011/11/24/364741.html]>
 * 
 * $闭包的概念$: <[ 一个代码段被用来作为方法的参数]>
 * 
 * 1) <[:理解:]> java中没有直接使用某个方法作为另外一个方法的参数,java使用匿名内部类来模拟这种情况
 *               匿名内部类往往是作为内部类<interface定义的>的具体实现
 *               
 * 2) <[:场景:]> 在一些平台类<plateform class> 中有些模板方法,其中某些步骤是调用了内部类<interface定义的>
 *              中的某些方法,但是平台类将这些方法的具体实现延迟到了业务类中。业务类调用平台类的模板方法,但是传入
 *              匿名内部类的实现做为模板方法的参数
 *              
 * 3) <[:知识点:]> 为什么匿名内部类和局部内部类只能访问final变量 .
 *                blog reference: <[http://blog.csdn.net/zhaoyw2008/article/details/9565219]>  
 *                
 * 4) <[:语法:]>  详解内部类 
 *               blog reference: <[http://www.cnblogs.com/chenssy/p/3388487.html]>  
 *               
 *  其实在这个应用程序中我们还看到了如何来引用内部类:引用内部类我们需要指明这个对象的类型:
 *  OuterClasName.InnerClassName。同时如果我们需要创建某个内部类对象,必须要利用外部
 *  类的对象通过.new来创建内部类: 
 *  OuterClass.InnerClass innerClass = outerClass.new InnerClass();
 *  
 *  对于一个名为OuterClass的外围类和一个名为InnerClass的内部类,在编译成功后,
 *  会出现这样两个class文件:OuterClass.class和OuterClass$InnerClass.class。
 *
 *  在Java中内部类主要分为: <[ 成员内部类、局部内部类、匿名内部类、静态内部类]>
 */
public class ElegantInnerClass
{
    // DBCP,CP30,proxool连接池在spring hibernate中的配置 [DHCP]
    // reference <[http://zz563143188.iteye.com/blog/1833057]>
    // reference <[http://commons.apache.org/proper/commons-dbcp/configuration.html]>
	
  /*  
    1、 PreparedStatement接口继承Statement, PreparedStatement 实例包含已编译的 SQL 语句,所以其执行速度要快于 Statement 对象。
    2、作为 Statement 的子类,PreparedStatement 继承了 Statement 的所有功能。三种方法
          execute、 executeQuery 和 executeUpdate 已被更改以使之不再需要参数

    3、在JDBC应用中,如果你已经是稍有水平开发者,你就应该始终以PreparedStatement代替
          Statement.也就是说,在任何时候都不要使用Statement.
    基于以下的原因:
    一.代码的可读性和可维护性.
    虽然用PreparedStatement来代替Statement会使代码多出几行,但这样的代码无论从可读性还是可维护性上来说.都比直接用Statement的代码高很多档次:
    stmt.executeUpdate("insert into tb_name (col1,col2,col2,col4) values ('"+var1+"','"+var2+"',"+var3+",'"+var4+"')");//stmt是Statement对象实例

    perstmt = con.prepareStatement("insert into tb_name (col1,col2,col2,col4) values (?,?,?,?)");
    perstmt.setString(1,var1);
    perstmt.setString(2,var2);
    perstmt.setString(3,var3);
    perstmt.setString(4,var4);
    perstmt.executeUpdate(); //prestmt是 PreparedStatement 对象实例 

    不用我多说,对于第一种方法.别说其他人去读你的代码,就是你自己过一段时间再去读,都会觉得伤心.

    二.PreparedStatement尽最大可能提高性能.
    语句在被DB的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中(相当于一个涵数)
	就会得到执行这并不是说只有一个Connection中多次执行的预编译语句被缓存,而是对于整个DB中,只要预编译的语句语法和缓存中匹配.那么在任何时候就可以不需要再次
	编译而可以直接执行.而statement的语句中,即使是相同一操作,而由于每次操作的数据不同所以使整个语句相匹配的机会极小,几乎不太可能匹配.比如:
    insert into tb_name (col1,col2) values ('11','22');
    insert into tb_name (col1,col2) values ('11','23');
    即使是相同操作但因为数据内容不一样,所以整个个语句本身不能匹配,没有缓存语句的意义.事实是没有数据库会对普通语句编译后的执行代码缓存.

    当然并不是所以预编译语句都一定会被缓存,数据库本身会用一种策略,比如使用频度等因素来决定什么时候不再缓存已有的预编译结果.以保存有更多的空间存储新的预编译语句.

    三.最重要的一点是极大地提高了安全性.
    即使到目前为止,仍有一些人连基本的恶义SQL语法都不知道.
    String sql = "select * from tb_name where name= '"+varname+"' and passwd='"+varpasswd+"'";
    如果我们把[' or '1' = '1]作为varpasswd传入进来.用户名随意,看看会成为什么?

   select * from tb_name = '随意' and passwd = '' or '1' = '1';
    因为'1'='1'肯定成立,所以可以任何通过验证.更有甚者:
    把[';drop table tb_name;]作为varpasswd传入进来,则:
    select * from tb_name = '随意' and passwd = '';drop table tb_name;有些数据库是不会让你成功的,但也有很多数据库就可以使这些语句得到执行.

    而如果你使用预编译语句.你传入的任何内容就不会和原来的语句发生任何匹配的关系.只要全使用预编译语句,你就用不着对传入的数据做任何过虑.而如果使用普通的statement,
    有可能要对drop,;等做费尽心机的判断和过虑.
	
    上面的几个原因,还不足让你在任何时候都使用PreparedStatement吗?
  */
    
    /* 创建一个Statement    
    要执行SQL语句,必须获得java.sql.Statement实例,Statement实例分为以下3种类型:    
    1、执行静态SQL语句。通常通过Statement实例实现。    
    2、执行动态SQL语句。通常通过PreparedStatement实例实现。    
    3、执行数据库存储过程。通常通过CallableStatement实例实现。    
    具体的实现方式:    
    Statement stmt = con.createStatement() ;    
    PreparedStatement pstmt = con.prepareStatement(sql) ;    
    CallableStatement cstmt = con.prepareCall("{CALL demoSp(? , ?)}");
    */    
    
    // <[http://hzw2312.blog.51cto.com/2590340/748307]>
    Connection conn = null;
    ResultSet rs = null;
    Statement stmt = null; 
    
    // 内部接口也是回调接口,只定义抽象方法。    
    private interface Callback 
    {        
        Object doIt(Connection conn) throws SQLException;    
    }  
    
    // 模板方法(抽象)
    private Object execute(Callback callback) throws SQLException 
    {        
        conn = openConnection(); 
                   
        return callback.doIt(conn);        
    }    
    
    // 业务方法(具体)   
    public Object sqlQuery(final String sql) throws SQLException 
    {        
        //匿名内部类做为模板方法的参数来模拟闭包        
        return execute (new Callback() 
        {            
            public Object doIt(Connection conn) throws SQLException 
            {     
                stmt = conn.createStatement();
                return stmt.executeQuery(sql);            
                }        
            });  
    }    
    
    public Connection openConnection() throws SQLException 
    {     
        try
        {
           Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
           String url = "jdbc:oracle:thin:@127.0.0.1:1521:ora11g";
           String user = "scott";
           String password = "tiger";
           return DriverManager.getConnection(url, user, password);    
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        
        return null;
    }    
    
    public void closeStatement(Statement stmt) throws SQLException 
    {        
        if (stmt != null ) 
        {            
            stmt.close();        
        }    
    }
    
    public void closeConnection(Connection conn) throws SQLException 
    {        
        if (conn != null && !conn.isClosed()) 
        {            
            conn.close();        
        }    
    }
    
    public void closeResultSet(ResultSet rs) throws SQLException 
    {        
        if (rs != null ) 
        {            
            rs.close();        
        }    
    }
    
    @Test
    public void runSql() throws SQLException
    {
        rs = (ResultSet) sqlQuery(" select t.*, t.rowid from emp t");
        
        while (rs.next()) 
        {   
           System.out.println(rs.getString("ename"));
        } 
        
        // 关闭资源: 
        closeConnection(conn);
        closeStatement(stmt);
        closeResultSet(rs);
    }
}

 

分享到:
评论

相关推荐

    javaSE代码实例

    15.4.2 基于接口实现的匿名内部类 335 15.4.3 匿名内部类的初始化 337 15.4.4 匿名内部类作用的体现 337 15.5 理解内部类 339 15.6 内部接口 340 15.6.1 定义在类中的内部接口 340 15.6.2 定义在接口中...

    JAVA入门1.2.3:一个老鸟的JAVA学习心得 PART1(共3个)

    大量使用流程图表示程序的执行过程,使用结构图表示程序的内部状态 每章最后都给出了典型的练习题,让读者及时练习,巩固提高,并提供了参考答案 目录 第1篇 Java语言基本语法 第1章 让自己的第一个Java程序跑...

    Java入门1·2·3:一个老鸟的Java学习心得.PART3(共3个)

    大量使用流程图表示程序的执行过程,使用结构图表示程序的内部状态 每章最后都给出了典型的练习题,让读者及时练习,巩固提高,并提供了参考答案 目录 第1篇 Java语言基本语法 第1章 让自己的第一个Java程序跑...

    疯狂JAVA讲义

    6.7.5 匿名内部类 212 6.7.6 闭包(Closure)和回调 215 6.8 枚举类 217 6.8.1 手动实现枚举类 217 6.8.2 枚举类入门 219 6.8.3 枚举类的属性、方法和构造器 220 6.8.4 实现接口的枚举类 223 6.8.5 包含抽象...

    Java范例开发大全(全书源程序)

    实例179 匿名内部类的使用规范 297 实例180 电话与移动电话 299 10.4 静态内部类 300 实例181 静态内部类的使用规范 300 实例182 苹果的来历 302 10.5 接口 303 实例183 求n的幂数与倍数 304 实例184 商品...

    Java开发技术大全 电子版

    4.13.5匿名内部类187 4.13.6内部类的作用188 4.14包189 4.14.1包的创建189 4.14.2包的使用191 4.14.3JAR文件的创建和使用193 4.14.4JDK中的常用包195 4.15本章小结196 第3篇Java数据处理 第5章数组与字符串...

    Java范例开发大全 (源程序)

     实例179 匿名内部类的使用规范 297  实例180 电话与移动电话 299  10.4 静态内部类 300  实例181 静态内部类的使用规范 300  实例182 苹果的来历 302  10.5 接口 303  实例183 求n的幂数与倍数 304 ...

    java范例开发大全(pdf&源码)

    实例179 匿名内部类的使用规范 297 实例180 电话与移动电话 299 10.4 静态内部类 300 实例181 静态内部类的使用规范 300 实例182 苹果的来历 302 10.5 接口 303 实例183 求n的幂数与倍数 304 实例184 商品订单 306 ...

    java范例开发大全源代码

     实例179 匿名内部类的使用规范 297  实例180 电话与移动电话 299  10.4 静态内部类 300  实例181 静态内部类的使用规范 300  实例182 苹果的来历 302  10.5 接口 303  实例183 求n的幂数与倍数 ...

    Java开发实战1200例(第1卷).(清华出版.李钟尉.陈丹丹).part3

    实例121 匿名内部类的简单应用 153 实例122 静态内部类的简单应用 154 第2篇 Java高级应用 第6章 多线程技术 158 6.1 线程的基础 159 实例123 新建无返回值的线程 159 实例124 查看线程的运行状态 160 实例125 查看...

    java范例开发大全

    实例179 匿名内部类的使用规范 297 实例180 电话与移动电话 299 10.4 静态内部类 300 实例181 静态内部类的使用规范 300 实例182 苹果的来历 302 10.5 接口 303 实例183 求n的幂数与倍数 304 实例184 商品订单 306 ...

    Maven权威指南 很精典的学习教程,比ANT更好用

    下载本章的例子 3.2. 创建一个简单的项目 3.3. 构建一个简单的项目 3.4. 简单的项目对象模型 (Project Object Model) 3.5. 核心概念 3.5.1. Maven插件和目标 (Plugins and Goals) 3.5.2. Maven生命周期 ...

Global site tag (gtag.js) - Google Analytics