日期:2014-05-16  浏览次数:20391 次

Mybatis原理分析一 从JDBC到Mybaits
1.引言

本文主要讲解JDBC怎么演变到Mybatis的渐变过程,重点讲解了为什么要将JDBC封装成Mybaits这样一个持久层框架。再而论述Mybatis作为一个数据持久层框架本身有待改进之处。

2.JDBC实现查询分析

我们先看看我们最熟悉也是最基础的通过JDBC查询数据库数据,一般需要以下七个步骤:

(1) 加载JDBC驱动

(2) 建立并获取数据库连接

(3) 创建 JDBC Statements 对象

(4) 设置SQL语句的传入参数

(5) 执行SQL语句并获得查询结果

(6) 对查询结果进行转换处理并将处理结果返回

(7) 释放相关资源(关闭Connection,关闭Statement,关闭ResultSet)

以下是具体的实现代码:

public static List<Map<String,Object>> queryForList(){
Connection connection = null;
ResultSet rs = null;
PreparedStatement stmt = null;
List<Map<String,Object>> resultList = new          ArrayList<Map<String,Object>>();

try {
//加载JDBC驱动
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
String url = jdbc:oracle:thin:@localhost:1521:ORACLEDB";

String user = "trainer";
String password = "trainer";
//获取数据库连接
connection = DriverManager.getConnection(url,user,password);

String sql = "select * from userinfo where user_id = ? ";
//创建Statement对象(每一个Statement为一次数据库执行请求)
             stmt = connection.prepareStatement(sql);

//设置传入参数
stmt.setString(1, "zhangsan");

//执行SQL语句
rs = stmt.executeQuery();

//处理查询结果(将查询结果转换成List<Map>格式)
ResultSetMetaData rsmd = rs.getMetaData();
int num = rsmd.getColumnCount();
   
while(rs.next()){
Map map = new HashMap();
for(int i = 0;i < num;i++){
String columnName = rsmd.getColumnName(i+1);
      map.put(columnName,rs.getString(columnName));
}
resultList.add(map);
}

} catch (Exception e) {
e.printStackTrace();
} finally {
try {
                   //关闭结果集
if (rs != null) {
rs.close();
rs = null;
}
                   //关闭执行
if (stmt != null) {
stmt.close();
stmt = null;
}
if (connection != null) {
connection.close();
connection = null;
}
} catch (SQLException e) {
e.printStackTrace();
}
}

return resultList;
}

3.JDBC演变到Mybatis过程

上面我们看到了实现JDBC有七个步骤,哪些步骤是可以进一步封装的,减少我们开发的代码量。

第一步优化:

问题描述:

数据库连接频繁的开启和关闭本身就造成了资源的浪费,影响系统的性能。

解决问题:

数据库连接的获取和关闭我们可以使用数据库连接池来解决资源浪费的问题。通过连接池就可以反复利用已经建立的连接去访问数据库了。减少连接的开启和关闭的时间。

问题描述:

但是现在连接池多种多样,可能存在变化,有可能采用DBCP的连接池,也有可能采用容器本身的JNDI数据库连接池。

解决问题:

我们可以通过DataSource进行隔离解耦,我们统一从DataSource里面获取数据库连接,DataSource具体由DBCP实现还是由容器的JNDI实现都可以,所以我们将DataSource的具体实现通过让用户配置来应对变化。

第二步优化:

问题描述:

我们使用JDBC进行操作数据库时,SQL语句基本都散落在各个JAVA类中,这样有三个不足之处:

第一,可读性很差,不利于维护以及做性能调优。

第二,改动Java代码需要重新编译、打包部署。

第三,不利于取出SQL在数据库客户端执行(取出后还得删掉中间的Java代码,编写好的SQL语句写好后还得通过+号在Java进行拼凑)。

解决问题:

我们可以考虑不把SQL语句写到Java代码中,那么把SQL语句放到哪里呢?首先需要有一个统一存放的地方,我们可以将这些SQL语句统一集中放到配置文件或者数据库里面(以key-value的格式存放)。然后通过SQL语句的key值去获取对应的SQL语句。

既然我们将SQL语句都统一放在配置文件或者数据库中,那么这里就涉及一个SQL语句的加载问题。

第三步优化:

问题描述:

很多情况下,我们都可以通过在SQL语句中设置占位符来达到使用传入参数的目的,这种方式本身就有一定局限性,它是按照一定顺序传入参数的,要与占位符一一匹配。但是,如果我们传入的参数是不确定的(比如列表查询,根据用户填写的查询条件不同,传入查询的参数也是不同的,有时是一个参数、有时可能是三个参数),那么我们就得在后台代码中自己根据请求的传入参数去拼凑相应的SQL语句,这样的话还是避免不了在Java代码里面写SQL语句的命运。既然我们已经把SQL语句统一存放在配置文件或者数据库中了,怎么做到能够根据前台传入参数的