写点什么

MyBatis 初步理解

作者:andy
  • 2022-10-27
    北京
  • 本文字数:4067 字

    阅读完需:约 13 分钟

一、持久层框架的缘由


从整个项目开发的角度,与数据库进行连接的就是持久层代码。而 Java 提供了原生的数据层(数据层也就是持久层)技术,即 JDBC。通过数据库提供的驱动程序,实现 JDBC 与数据库进行交互。实际执行的 SQL 语句由 JDBC 进行封装。


随着时代的不断进步,业务的复杂度不断提高。单纯重复地编写 JDBC 与智能化代码的需求,两者之间的矛盾越来越突出。无论任何时代,只要是单纯重复的劳动,都将会被时代淘汰。



JDBC 代码示例:


package org.fuys.owndb.model;import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.util.Arrays;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * JDBC model from java original code * @author ys * */public class JDBCModel {	private static Logger logger = LoggerFactory.getLogger(JDBCModel.class);		/**	 * MySql-connector-java 6.0.6 version<br>	 * It is different from the formal versions<br>	 * It depends on MySql database	 * 	 */	private static String driverClass = "com.mysql.cj.jdbc.Driver";	/**	 * MySql 5.7 requirement<br>	 * It is different from the formal version<br>	 * It depends on MySql database<br>	 * Be careful of SSL in the MySql 5.7.+	 */	private static String url = "jdbc:mysql://localhost:3306/owndb?useSSL=false&serverTimezone=UTC";	private static String userName = "root";	private static String password = "admin";	/**	 * database connection class	 */	private static Connection connect = null;	/**	 * static code block has highest priority execution<br>	 * in this class	 */	static {		try {			// loading database driver class			Class.forName(driverClass);			// get database connection			connect = DriverManager.getConnection(url, userName, password);		} catch (Exception e) {			logger.error("DriverManager getConnection Exception", e);		}	}	/**	 * define insert method	 * @param sql	 * @param parameters	 * @return	 */	public static int insert(String sql ,String[]parameters){		logger.info("Sql --> {}", sql);		logger.info("Parameters --> {}", Arrays.toString(parameters));		int result = 0;		try {			PreparedStatement pre = connect.prepareStatement(sql);			for(int x=1;x<=parameters.length;x++){				pre.setString(x, parameters[x-1]);			}			result = pre.executeUpdate();			logger.info("Result --> {}", result);		} catch (Exception e) {			logger.error("Insert operate exception -->", e);		}		return result;	}	/**	 * define update method	 * @param sql	 * @param parameters	 * @return	 */	public static int update(String sql ,String[]parameters){		logger.info("Sql --> {}" ,sql);		logger.info("parameters --> {}", Arrays.toString(parameters));		int result = 0;		try {			PreparedStatement pre = connect.prepareStatement(sql);			for(int x=1;x<=parameters.length;x++){				pre.setString(x, parameters[x-1]);			}			result = pre.executeUpdate();			logger.info("Result --> {}",result);		} catch (Exception e) {			logger.error("Update operate exception -->", e);		}		return result;	}	/**	 * define delete method	 * @param sql	 * @param parameters	 * @return	 */	public static int delete(String sql,String[]parameters){		logger.info("Sql --> {}" ,sql);		logger.info("parameters --> {}", Arrays.toString(parameters));		int result = 0;		try {			PreparedStatement pre = connect.prepareStatement(sql);			for(int x=1;x<=parameters.length;x++){				pre.setString(x, parameters[x-1]);			}			result = pre.executeUpdate();			logger.info("Result --> {}",result);		} catch (Exception e) {			logger.error("Delete operate exception -->", e);		}		return result;	}	/**	 * define query method	 * @param sql	 * @param parameters	 * @return	 */	public static int query(String sql,String[]parameters){		logger.info("Sql --> {}" ,sql);		logger.info("parameters --> {}", Arrays.toString(parameters));		int result = 0;		try {			PreparedStatement pre = connect.prepareStatement(sql);			for(int x=1;x<=parameters.length;x++){				pre.setString(x, parameters[x-1]);			}			ResultSet resultSet = pre.executeQuery();			logger.info("Result ------------------------->");			String strResult = null;			while(resultSet.next()){				result++;				strResult = "";				for(int y=1;y<=resultSet.getMetaData().getColumnCount();y++){					strResult += resultSet.getMetaData().getColumnName(y)							+ "=" + resultSet.getString(y) + " ,";				}				logger.info("MetaData {} --> {}",resultSet.getRow(),strResult.substring(0, strResult.lastIndexOf(",")));			}			if(strResult == null){				logger.info("MetaData is NULL");			}		} catch (Exception e) {			result = -1;			logger.error("Query operate exception -->", e);		}		logger.info("Total row --> {}", result);		return result;	}	}
复制代码


我们在编写 JDBC 原生技术代码时,会发现,冗余的代码太多,对于开发者,需要做的机械重复性工作很多。因此,对于开发者的效率有很大的影响。这时,便出现了自己编写一套自动化的数据库操作代码。但是,仍然需要面临许多问题,比如:

  • 为了达到自动化,需要不断使用反射机制,反射机制也就是通过提供类信息(包含类路径),从而达到重新获取类对象的目的,框架也正是基于这个原理;

  • 为了能够贴合数据库,需要匹配数据库的对象;

  • 自己编写的代码,很难具有通用性,性能比较低。

综上所述,开发者非常迫切能够出现一些第三方的框架,以解决这些问题。随后,在技术的不断发展过程中,出现了许多的持久层框架,如 Entity Bean、JDO、hibernate、Ibatis、JPA、MyBatis 等等。

Mybatis 是当前阶段,简单方便,性能优良的框架首选。


二、对象关系映射


对象关系映射(ORMapping),通过对象的操作达到对数据库的操作。这是因为开发者更喜欢操作对象,而不是去处理数据库的 SQL 语句。


李兴华在课上讲述了 ORM 最初的实现是由 JDBC 完成的,这一点,我不敢苟同。为什么这么说,这是因为 JDBC 需要编写 SQL,SQL 的变化值需要通过字符串定义“?”的位置,使用 PreparedStatement 进行赋值,一点没有见到对象操作的痕迹,如果硬要说,使用 VO 进行值传递,那和通过 PreparedStatement 进行传值没有区别。



图 原始数据库操作


随着时代不断发展,因为 JDBC 编写的冗余和繁琐以及 ORMapping 思想的提出,人们开始在数据层和 JDBC 之间寻找 ORM 的实现组件。



图 ORM 思想实现数据库操作


随着时代的发展,出现了以下的 ORMapping 开发组件。

1、EJB 2.x(实体 Bean 技术),这是 EJB 容器基于 JDBC 进行开发的技术。

EJB 2.x 包含 CMP(容器管理持久化)和 BMP(对象管理持久化),CMP 指的是用户不需要编写 JDBC 代码,其适合数据库的移植,BMP 需要开发者编写 JDBC 代码。

EJB 技术通过将所有数据读取到内存中,方便进行数据随时匹配更新操作,简单 Java 类通过 set()方法实现数据变更,这样就可以不用编写 JDBC 代码。

EJB 容器技术复杂,开发难度大,而且非常昂贵。

2、JDO(Java 数据对象),通过利用反射机制,编写一些代码达到部分的 JDBC 的自动化处理操作。因为 JDO 有限,已停止发展。

3、Hibernate(原意是冬眠),Hibernate 已改过去 ORM 组件的弊病,取得了巨大的成功,在十多年的 ORM 框架发展中,处于统治地位。

  • Hibernate 设计理念来源于 EJB 技术,因此,也没有解决好 EJB 中的一些性能问题,诸如对象状态的问题,对象通过 setter 方法就可以实现数据库操作,就得长久存储实例对象,这需要消耗巨大的内存空间进行对象状态的保持。

  • 开发的配置文件异常复杂,而且非常的多,一定要使用诸如 MyEclipse 开发工具。

  • 提供了缓存机制,包含一级缓存、二级缓存。

  • 可以实现数据库移植,不同类型的数据库以及同一类型的不同机器数据库的数据迁移,都可以叫做数据库移植。由于最初的时代,数据库产品很多,随着数据库的统一以及 nosql 的兴起,此已不再是项目的关注点了。



图 数据库移植


4、EJB 3.X、JPA(Java 持久化接口)标准,Hibernate 的思想来源于 EJB,但是其性能好于 EJB,但是开发过于复杂。因此,Hibernate 的设计者开发了 EJB 3.x 技术,这项技术里引入了 Annotation 实现实体层的配置。随后,Hibernate 也支持了 JPA 技术,也出现了 JPA 框架。

5、IBatis 和 MyBatis 框架,在 Hibernate 最初的阶段,IBatis 发展比较缓慢,但是随后,谷歌于 2009 年收购了 IBatis,并对于进行改进,推出了 MyBatis。而 MyBatis 配置简单,开发方便,越来越受到广大开发者的欢迎。


三、MyBatis


MyBaits 是一款支持定制化 SQL(custom SQL)、存储过程(stored procedures)和高级映射(advanced mappings)的持久层框架(persistence framework)。MyBatis 消除了 JDBC 编码、手工参数赋值以及获取结果集。MyBatis 使用简单的 XML、配置的 Annotation 和映射原生信息,将接口和 POJOs(Plain Old Java Objects)映射到数据库记录中。


问题一:

Hibernate 与 MyBatis 的区别?

简略的说,Hibernate 需要像 JDBC 编写数据层实现代码,而 MyBatis 不需要编写数据层代码,通过调用接口,实现数据层操作。

Hibernate 适合于移植性的开发,而 MyBatis 不具备此项能力。


问题二:

在一九易工作期间,孔哥曾经提出 SqlServer 数据迁移的需求,在基于供货系统(SSI 框架)和供货管理系统(SSM 框架),是否可以实现此需求?


用户头像

andy

关注

还未添加个人签名 2019-11-21 加入

还未添加个人简介

评论

发布
暂无评论
MyBatis初步理解_andy_InfoQ写作社区