`
michealBean
  • 浏览: 8977 次
  • 性别: 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);
    }
}

 

分享到:
评论

相关推荐

    JAVA代码大全的例子

    内部类可以是成员内部类、局部内部类或匿名内部类,它们在处理复杂逻辑或事件处理时特别有用。 此外,Java集合框架是编程中的重要部分,包括数组列表、链表、队列、栈、哈希映射和树等数据结构。这些例子将帮助你...

    JAVA入门程序例子

    - **事件处理**:Swing支持事件监听机制,通过匿名内部类或事件适配器处理用户交互事件。 4. **JDBC(Java Database Connectivity)连数据库技术**: - **驱动管理**:加载JDBC驱动,建立数据库连接。 - **SQL...

    100个Java经典例子后端- Java

    13. **Lambda表达式和函数式编程**: Java 8引入的新特性,简化了匿名内部类的使用,增强了代码的简洁性和可读性。 14. **Swing或JavaFX**: 创建图形用户界面(GUI)的应用程序,包括组件布局、事件处理等。 15. **...

    java 150个小例子

    例子会展示如何使用Lambda表达式简化匿名内部类和方法引用。 10. **Swing和JavaFX**:这两个是Java的图形用户界面(GUI)库,用于创建桌面应用。例子可能包括按钮、文本框、布局管理等组件的使用。 11. **网络编程...

    Java_54实用知识库分享

    涵盖Java基础知识、Java编程思想、Java集合框架、Java IO流、JDBC、Lambda表达式、抽象类、接口、重写与重载、垃圾回收机制、访问权限控制、静态初始化与枚举类型、内部类、匿名类等方面的知识。 1. Java基础知识:...

    java重点英语词汇

    6. **Anonymous inner classes(匿名内部类)**:匿名内部类是局部内部类,没有类名。它们最适合实现单一或非常少量的方法,可以节省代码并提高可读性。 7. **API(Application Programmer's Interface,应用程序...

    如何用Java编写一段代码引发内存泄露Java开发Java

    2. **匿名内部类与静态内部类:**非静态内部类会隐式持有一个对外部类的引用,如果外部类对象很大,这将导致内存泄露。特别是,如果将内部类实例作为成员变量并且该内部类实例具有生命周期很长的引用,比如静态变量...

    java核心技术源代码

    - 内部类:包括匿名内部类、成员内部类、局部内部类等,这些在源代码中都有实际的应用场景。 2. **进阶篇** - 集合框架:Java集合框架包括List、Set、Map等接口及其实现类,源代码将演示如何使用ArrayList、...

    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+英语词汇表.doc

    **概念解析:** 匿名内部类是 Java 中一种特殊的内部类,它没有显式的类声明,而是直接在需要的地方定义。它通常用于实现接口或继承类,并且只能在一个表达式中定义。 #### Application Programming Interface (API...

    Java应用教程(PPT&code)

    6. **内部类与匿名类**:讲解如何在类内部定义类,以及如何创建没有名称的临时类实例。 7. **输入/输出(I/O)**:涵盖流的概念,如FileInputStream、FileOutputStream、BufferedReader、PrintWriter等,以及NIO(非...

    java100例 源码

    例子可能展示了如何使用lambda简化匿名内部类,以及使用Stream API进行集合操作。 13. **并发工具类**:Java并发包(java.util.concurrent)提供了许多高级工具,如ExecutorService、Semaphore、CountDownLatch等。...

    学习必备之经典java100例

    12. **Lambda表达式与函数式编程**: Java 8引入了Lambda表达式,使得函数式编程风格成为可能,简化了匿名内部类的使用,特别是对于处理集合的操作。 13. **模块化系统**: Java 9引入了模块化系统,帮助组织大型项目...

    Spring2.5学习文档3.pdf

    通过传递一个匿名内部类实现`ConnectionCallback`接口,我们可以在回调方法`doInConnection()`中编写SQL语句和预编译参数。这样,JdbcTemplate会自动处理事务、异常和资源关闭等操作,极大地提高了代码的可读性和可...

    Java编程精选140例(源码)

    14. **Lambda表达式和函数式接口**:Java 8引入的新特性,简化匿名内部类,提高代码简洁性。 15. **并发编程**:原子类、并发工具类(如CountDownLatch、Semaphore)的使用,以及ConcurrentHashMap等并发安全的数据...

    Java语言程序设计第8版 习题解答+例题程序

    3. **高级特性**:如枚举、匿名内部类、Lambda表达式、Stream API等现代Java特性。 4. **实用框架应用**:如Spring框架的简单应用,Maven项目构建等。 通过这些习题、编程题和例题的解答,读者能够全面巩固Java语言...

    java实用程序设计100例

    9. **Lambda表达式**:Java 8引入的新特性,用于简化匿名内部类,提高代码简洁性。 10. **Stream API**:处理集合的新型方式,提供链式操作,便于进行过滤、映射、聚合等操作。 11. **日期和时间API**:Java 8中的...

    Java经典学习实例:100个源码.rar

    3. **函数对象(匿名内部类/lambda表达式)**:Java 8引入了lambda表达式,简化了函数式编程。这些实例可能会展示如何使用函数接口和lambda表达式来实现回调函数或简化代码。 4. **网络编程**:Java的`java.net`包...

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

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

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

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

Global site tag (gtag.js) - Google Analytics