首页 > 代码库 > ORM framework源码分析:引言之Java JDBC

ORM framework源码分析:引言之Java JDBC

    在百度百科上找了一段定义ORM的话:对象关系映射(英语Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的“虚拟对象数据库”。那么ORM Framework就是提供对象到数据库关系映射的一套编程模型。现在流行的MyBaits、Hibernate都是这种框架。本章开始我们就来分析下这两种框架源码的分析,从而更深入的理解什么事ORM。

    在开始分析MyBaits3,Hibernate4这些当前比较流行的ORM框架的源码之前我们先来看看JDBC,它是所有这些框架的基础。说到JDBC,我们首先来看看java.sql包下有哪些类。

技术分享

技术分享

    我们再来看一下一次jdbc访问数据的完整过程。

	   Connection con = null;
	   Statement stmt = null;
	   ResultSet rs = null;
	   try{
	       Class.forName("com.mysql.jdbc.Driver");
	       con = DriverManager.getConnection("jdbc:mysql://localhost:3306/database", "root", "123456");
	       stmt = con.createStatement();       
	       String sql = "select * from `table`";
	       rs = stmt.executeQuery(sql);        
	       ResultSetMetaData rsmd = rs.getMetaData();
	       int j = 0;
	       j = rsmd.getColumnCount();
	       for(int k = 0; k<j; k++){
	           System.out.print(rsmd.getCatalogName(k+1));
	           System.out.print("\t");
	       }
	       while(rs.next())
	       {
	           for(int i=0;i<j;i++)
	           {
	               System.out.print(rs.getString(i+1));
	               System.out.print("\t");
	           }
	       }
	   }
	   catch(Exception e1)
	   {
	       System.out.println(e1.toString());
	   }
	   finally{
           try
	       {
	           if(rs != null) rs.close();
	           if(stmt != null) stmt.close();
	           if(con != null) con.close();
	       }
	       catch(SQLException e)
	       {
	           System.out.println(e.toString());
	       }            
	   }
     Class.forName(String)是java reflection中用来加载类的,这里加载了一个驱动,然后DriverManager.getConnection()获取数据库连接,我们来看看DriverManager类。

技术分享

    DriverManager做为驱动管理器,有个内部类DriverInfo用于存取驱动程序的信息,维护着一个Driver对象。在加载了驱动程序后就需要从DriverManager中获取数据库连接。

public static Connection getConnection(String url,
        String user, String password) throws SQLException {
        java.util.Properties info = new java.util.Properties();

        if (user != null) {
            info.put("user", user);
        }
        if (password != null) {
            info.put("password", password);
        }

        return (getConnection(url, info, Reflection.getCallerClass()));
    }
private static Connection getConnection(
        String url, java.util.Properties info, Class<?> caller) throws SQLException {
        /*
         * 如果callerCl是空,我们就得检查应用的类加载器,这样就能加载rt.jar以外的JDBC驱动
         */
        ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
        synchronized (DriverManager.class) {
            // synchronize loading of the correct classloader.
            if (callerCL == null) {
                callerCL = Thread.currentThread().getContextClassLoader();
            }
        }

        if(url == null) {
            throw new SQLException("The url cannot be null", "08001");
        }

        println("DriverManager.getConnection(\"" + url + "\")");

        SQLException reason = null;

        for(DriverInfo aDriver : registeredDrivers) {
            //如果该类加载器无加载该驱动的权限则跳过
            if(isDriverAllowed(aDriver.driver, callerCL)) {
                try {
                    println("    trying " + aDriver.driver.getClass().getName());
                    //利用驱动尝试连接数据库
                    Connection con = aDriver.driver.connect(url, info);
                    if (con != null) {
                        println("getConnection returning " + aDriver.driver.getClass().getName());
                        return (con);
                    }
                } catch (SQLException ex) {
                    if (reason == null) {
                        reason = ex;
                    }
                }
            } else {
                println("    skipping: " + aDriver.getClass().getName());
            }
        }
      //省略部分代码...
    }
     DriverManager会在类载入时调用静态代码块初始化加载数据库驱动,当用户用getConnection时Driver会尝试去连接数据库,一旦有一种Driver能连接当前数据库就返回这个连接。以Mysql的mysql-connector-java为例如果希望自己的数据库能被JDBC数据库连接必须实现Connection接口。Connection不仅能提供事务操作还有个抽象方法createStatement能创建一个sql声明,这里就讲到了JDBC的第二个比较重要的类Statement。同样这个也是一个接口,需要不同数据库的开发商自己提供实现,这个对象主要的作用就是执行sql返回ResultSet,同样这个ResultSet也是一个接口需要提供第三方实现,它类似一个Table数据结构,每次调用next()它就指向下一条数据库记录,针对不同类型字段调用不同的getXXX(String columnName)就能获取该条记录对应字段的值。除了以上的这些主要接口,JDBC还提供了描述数据库属性的DatabaseMetaData接口和一些Date之类类型类和异常类。

   从以上这些分析我们就可以看出,实际上JDBC API很简单,它只是一个java到数据库的桥梁,只提供了一个大致规范,所有对特定数据库的操作都需要第三方来提供实现。





ORM framework源码分析:引言之Java JDBC