在百度百科上找了一段定义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到数据库的桥梁,只提供了一个大致规范,所有对特定数据库的操作都需要第三方来提供实现。