最近,查找一个生产问题的原因,需要深入研究框架的源码。 虽然最后发现问题的原因与此无关,但这个过程加深了对框架原理的理解。
本文主要讲一下框架的原理。
可能现在很多人已不再使用 ibatis 或者说也没听 ibatis,不过肯定了解过 Mybatis。ibatis 就是 Mybatis框架的前身,虽然 ibatis 框架已经比较老,但是其核心功能与 Mybatis 一致。
痛点解决
我们首先看一个使用 JDBC 查询的示例。
使用原生 JDBC 查询有两个痛点:
使用起来非常繁琐,需要处理各种数据库异常,关闭各种资源。
数据转换比较麻烦。 在查询之前,需要将Java对象的属性值设置为 ,查询返回后,需要将其设置为返回的对象。
这些复杂的数据库连接查询代码被封装在 中,并处理各种异常和关闭各种资源。 另外,自动处理Java对象和数据库类型之间的自动转换,实现业务代码和SQL代码的解耦。
数据类型转换原理
数据类型转换主要分为两类。 首先,将查询中传入的Java对象数据转换为SQL类型数据。 第二个查询返回的数据库信息被映射为Java对象。
SQL需要在配置文件中定义。 查询SQL语句配置如下:
框架启动过程会解析配置文件并生成子类。 如果配置了,就会生成对应的对象。
相关类图如下。
、 和 中将保存两个重要的对象。 通过这两个对象,将完成Java类型和数据库类型之间的相互转换。
将 Java 对象转换为数据库类型
以上面的配置为例,这里我们需要做的是从传入的com.query中获取属性值。 对象,然后通过.setxx将其设置到查询参数中。
解析配置中的SQL语句时,会获取#之间的内容,并替换为?。 然后按顺序保存到一个[]数组中,这个数组就会保存到对象中。
与解析字段相关的信息将被保存。
最终解析的SQL为:
select * from TEST_QUERY where ID=?
该SQL可以通过.(" * from where ID=?");生成对象。
然后根据 和 指定的类型创建适当的 和 对象。
对象会按照数组中的顺序保存变量和方法数组。
会采用反射获取的方式按照数组中的顺序返回值,生成数组。
最后,循环遍历数组并通过调用.setxx设置相关值。
有许多子类,通过它们可以正确处理Java对象和数据库类型转换。
转换的时序图为:
时序图来源于:https://www.ibm.com/developer...
映射到 Java 对象的数据库字段
SQL执行完成后,将返回查询结果。 这里,SQL查询结果将被转换为返回结果com.query。 这里需要上面提到的对象。
SQL执行结束并返回对象后,使用.()获取返回信息元数据对象。
可以获取返回的结果字段名、类型等信息,然后按顺序存储到数组中。
然后在数组中使用调用.getxx获取实际返回的数据并将其保存到数组中。
该对象将基于适当的且具有指定类型的对象。 与上面的对象一样,对象也存储变量和方法的数组。
最后根据反射生成返回对象,然后利用反射调用方法,并依次设置相关值。
映射返回对象的时序图为:
时序图来源于:https://www.ibm.com/developer...
样板代码
上面讲完了数据类型转换的原理,我们来看一下调用JDBC的示例代码。
例如,执行查询语句时,调用te。 在te中,会做一些必要的准备工作,比如准备事务,最后将SQL语句委托执行。
这里使用委托者模式,接受请求的对象将请求委托给另一个对象来处理。这种模式的优点在于解耦了业务代码与实际执行代码的联系,在于对外隐藏真正执行对象,易于扩展。
#执行过程主要分为以下三步。
第一步获取,使用conn.(sql)获取。
第二步是调用 . 方法设置参数。 到这里就完成了上面Java对象类型到SQL类型的转换。
第三步,调用.()执行SQL语句。
第四步,使用获取返回值。 这一步就完成了数据库类型和Java类型之间的转换。
帮助链接
深入解析系统架构及框架映射原理