匿名内部类与jdbc例子

 

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);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值