除了上面所说的问题,直接使用 JDBC 访问数据库还会有什么问题呢?这次我们将目光转移到执行结果的处理逻辑上。从上面的代码中可以看出,我们需要手动从 ResultSet 中取出数据,然后再设置到 Article 对象中。好在我们的 Article 属性不多,所以这样做看起来也没什么。假如 Article 对象有几十个属性,再用上面的方式接收查询结果,会非常的麻烦。而且可能还会因为属性太多,导致忘记设置某些属性。以上的代码还有一个问题,用户需要自行处理受检异常,这也是导致代码繁琐的一个原因。哦,还有一个问题,差点忘了。用户还需要手动管理数据库连接,开始要手动获取数据库连接。使用好后,又要手动关闭数据库连接。不得不说,真麻烦。
没想到直接使用 JDBC 访问数据库会有这么多的问题。如果在生产环境直接使用 JDBC,怕是要被 Leader 打死了。当然,视情况而定。如果项目非常小,且对数据库依赖比较低。直接使用 JDBC 也很方便,不用像 MyBatis 那样搞一堆配置了。
3.2.2 MyBatis VS JDBC上面说了一大堆 JDBC 的坏话,有点过意不去,所以下面来吐槽一下 MyBatis 吧。与 JDBC 相比,MyBatis 缺点比较明显,它的配置比较多,特别是 SQL 映射文件。如果一个大型项目中有几十上百个 Dao 接口,就需要有同等数量的 SQL 映射文件,这些映射文件需要用户自行维护。不过与 JDBC 相比,维护映射文件不是什么问题。不然如果把同等数量的 SQL 像 JDBC 那样写在代码中,那维护的代价才叫大,搞不好还会翻车。除了配置文件的问题,大家会发现使用 MyBatis 访问数据库好像过程也很繁琐啊。它的步骤大致如下:
读取配置文件
创建 SqlSessionFactoryBuilder 对象
通过 SqlSessionFactoryBuilder 对象创建 SqlSessionFactory
通过 SqlSessionFactory 创建 SqlSession
为 Dao 接口生成代理类
调用接口方法访问数据库
如上,如果每次执行一个 SQL 要经过上面几步,那和 JDBC 比较起来,也没什优势了。不过这里大家需要注意,SqlSessionFactoryBuilder 和 SqlSessionFactory 以及 SqlSession 等对象的作用域和生命周期是不一样的,这一点在 MyBatis 官方文档中说的比较清楚,我这里照搬一下。SqlSessionFactoryBuilder 对象用于构建 SqlSessionFactory,只要构建好,这个对象就可以丢弃了。SqlSessionFactory 是一个工厂类,一旦被创建就应该在应用运行期间一直存在,不应该丢弃或重建。SqlSession 不是线程安全的,所以不应被多线程共享。官方推荐的使用方式是有按需创建,用完即销毁。因此,以上步骤中,第1、2和第3步只需执行一次。第4和第5步需要进行多次创建。至于第6步,这一步是必须的。所以比较下来,MyBatis 的使用方式还是比 JDBC 简单的。同时,使用 MyBatis 无需处理受检异常,比如 SQLException。另外,把 SQL 写在配置文件中,进行集中管理,利于维护。同时将 SQL 从代码中剥离,在提高代码的可读性的同时,也避免拼接 SQL 可能会导致的错误。除了上面所说这些,MyBatis 会将查询结果转为相应的对象,无需用户自行处理 ResultSet。
总的来说,MyBatis 在易用性上要比 JDBC 好太多。不过这里拿 MyBatis 和 JDBC 进行对比并不太合适。JDBC 作为 Java 平台的数据库访问规范,它仅提供一种访问数据库的能力。至于使用者觉得 JDBC 流程繁琐,还要自行处理异常等问题,这些还真不怪 JDBC。比如 SQLException 这个异常,JDBC 没法处理啊,抛给调用者处理也是理所应当的。至于繁杂的步骤,这仅是从使用者的角度考虑的,从 JDBC 的角度来说,这里的每个步骤对于完成一个数据访问请求来说都是必须的。至于 MyBatis,它是构建在 JDBC 技术之上的,对访问数据库的操作进行了简化,方便用户使用。综上所述,JDBC 可看做是一种基础服务,MyBatis 则是构建在基础服务之上的框架,它们的目标是不同的。
3.3 使用 Spring JDBC 访问数据库上一节演示了 JDBC 访问数据的过程,通过演示及分析,大家应该感受到了直接使用 JDBC 的一些痛点。为了解决其中的一些痛点,Spring JDBC 应运而生。Spring JDBC 在 JDBC 基础上,进行了比较薄的包装,易用性得到了不少提升。那下面我们来看看如何使用 Spring JDBC。