框架|mybatis|(一)

1.原生jdbc

1.1jdbc程序

需求:使用jdbc查询mysql数据库中用户表的记录

statement:向数据库中发送一个sql语句

预编译statement:好处:提高数据库性能。

   预编译statement向数据库中发送一个sql语句,数据库编译sql语句,并把编译的结果保存在数据库砖的缓存中。下次再发sql时,如果sql相同,则不会再编译,直接使用缓存中的。

jdbc编程步骤:

1. 加载数据库驱动

2. 创建并获取数据库链接

3. 创建jdbc statement对象

4. 设置sql语句

5. 设置sql语句中的参数(使用preparedStatement)

6. 通过statement执行sql并获取结果

7. 对sql执行结果进行解析处理

8.  释放资源(resultSet、preparedstatement、connection)

 1 public class JDBCTest {
 2     public static void main(String[] args) {
 3         Connection connection = null;
 4         // 预编译的Statement,使用预编译的Statement提高数据库性能
 5         PreparedStatement preparedStatement = null;
 6         ResultSet resultSet = null;
 7         try {
 8             // 加载数据库驱动
 9             Class.forName("com.mysql.jdbc.Driver");
10             // 通过驱动管理类获取数据库链接
11             connection = DriverManager.getConnection(
12                             "jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8",
13                             "root", "root");
14             // 定义sql语句 ?表示占位符
15             String sql = "select * from t_user where username = ?";
16             //获取预处理statement
17             preparedStatement = connection.prepareStatement(sql);
18             // 设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
19             preparedStatement.setString(1, "王五");
20             // 向数据库发出sql执行查询,查询出结果集
21             resultSet = preparedStatement.executeQuery();
22             // 遍历查询结果集
23             while (resultSet.next()) {
24                 System.out.println(resultSet.getString("id") + "  "+ resultSet.getString("username"));
25             }
26         } catch (Exception e) {
27             e.printStackTrace();
28         } finally {
29             //释放资源
30             if (resultSet != null) {
31                 try {
32                     resultSet.close();
33                 } catch (SQLException e) {
34                     e.printStackTrace();
35                 }
36             }
37             if (preparedStatement != null) {
38                 try {
39                     preparedStatement.close();
40                 } catch (SQLException e) {
41                     e.printStackTrace();
42                 }
43             }
44             if (connection != null) {
45                 try {
46                     connection.close();
47                 } catch (SQLException e) {
48                     e.printStackTrace();
49                 }
50             }
51         }
52     }
53 }
View Code

 

1.2JDBC中存在的问题

1.工作量大。我们需要先连接,然后处理JDBC底层事务,处理数据类型,操作connection对象,statement对象,result对象等一系列操作。并且要对JDBC编程可能产生的异常进行捕捉处理并且正确关闭资源。

2.频繁连接数据库损耗数据库性能。数据库连接使用时创建,不使用释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响数据库性能。

解决方案:使用数据库连接池管理数据库连接。

3. 将sql语句硬编码到Java代码中,如果sql语句修改,需要重新编译java代码,不利于系统维护。

解决方案:将sql语句配置在xml配置文件中,即使sql变化, 不需要对java代码进行重新编译。

4. 向preparedStatement中设置参数,对占位符位置和设置参数值,硬编码在Java代码中,不利于系统维护。

解决方案:将sql语句及占位符和参数全部配置在xml中。

5. 从resultSet中遍历结果集数据时,存在硬编码,将获取表的字段进行硬编码,不利于系统维护。

解决方案:将查询的结果集,自动映射成Java对象。

2.ORM模型(对象关系映射)

由于JDBC存在的缺陷,实际工作中我们很少使用JDBC,进而提出了ORM模型。

ORM模型就是数据库表和简单的JAVA对象(pojo)的映射关系模型。

它主要解决数据库数据和pojo对象的相互映射。

通过这层映射关系我们可以简单迅速的将数据库表的数据转换为pojo。

3.MyBatis

3.1MyBatis是什么?

MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。

Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。

3.2MyBatis工作原理

3.2.1MyBatis架构

(1)API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。

(2)数据处理层:负责具体的SQL查找、SQL解析、SQL执行执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。

(3)基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载、缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。

3.2.2MyBatis工作流程


 

Mybatis的运行分为

 

第一部分是读取配置文件缓存到Coufiguration对象,用以创建SqlSessionFactory

第二部分是SqlSession的执行过程。(两种执行方式)

(1)构建SqlSessionFactory过程

SqlSessionFactory是Mybatis的核心类

主要功能时提供创建Mybatis的核心接口SqlSession,我们需要创建SqlSessionFactory,为此我们提供配置文件和相关参数。通过SqlSessionFactoryBuilder去构建。

1.通过XMLConfigBuilder解析配置的XML文件,读取配置参数(基础配置XML文件、映射器XML文件)并将读取的数据存入这个Configuration类中。

2.使用Configuration对象去创建SqlSessionFactory

  1) 构建Configuration

  Configuration的作用:读取配置文件,包括基础配置的XML文件和映射器的XML文件

            初始化基础配置,比如Mybatis的别名等,一些重要的类对象

            例如:插件、映射器、ObjectFactory和typeHandler对象。

            提供单例,为后续创建SqlSessionFactory服务并提供配置的参数。

            执行一些重要的对象方法,初始化配置信息

 

SqlSession是一个接口,使用它并不复杂。我们构建SqlSessionFactory就可以轻松容易地拿到Sqlseesion了。

(2)SqlSession运行过程

  SqlSession用于获取映射器或者直接通过命名信息执行SQL(两种执行方式

  1)  映射器的动态代理

    映射器是JAVA接口和XML文件组成的

    Mapper映射是通过动态代理来实现的。映射器的xml命名空间对应的便是这个接口的全路径,那么它根据全路径和方法名便能够绑定起来,通过动态代理技术,让这个接口跑起来。

    映射器其实就是一个动态代理对象,进入到了MapperMethod的execute方法。它经过简单的判断就进入了SqlSession的删除、更新、插入和选择等方法。

  2)  SqlSession下的四大对象

  SqlSession是通过Executor创建StatementHandler来运行的,而StatementHandler要经过下面的三步。Prepared预编译SQL、parametersize设置参数和query/update执行SQL。

    1.parametersize是调用parameterHandler的方法去设置的,而参数是根据类型处理器typeHandler去处理。

    2.query/update方法通过resultHandler进行处理结果的封装,如果是update语句,它就返回整数,否则它就通过typeHandler处理结果类型。

    3.用ObjectFactory提供的规则组装对象,返回给调用者。

 

Mapper的执行其实就是通过Executor、StatementHandler、ParameterHandler和ResultHandler来完成数据操作和结果的返回。

  执行器(Executor):它是一个真正执行Java和数据交互的地方。在Mybatis中有三种执行器。SIMPLE(简单执行器,这是默认的)、REUSE(重用预处理语句)和Batch(执行重用语句和批量更新,它是针对批量专用的执行器)。由它来调度StatementHandler、Parameterhandler、ResultHandler等来执行对应的SQL。

  数据库会话器(StatementHandler):专门来处理数据库会话的。使用数据的Statement执行操作,它是四大对象的核心,起到承上启下的作用。

  参数处理器(ParameterHandler):对预编译语句进行参数处理。

  结果处理器(ResultSetHandler):组装结果集的返回。

Mapped Statement

Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。

Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。

Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。

4.Demo

5.SqlSession使用范围

5.1 SqlsessionFactoryBuilder

通过SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory,将SqlSessionFactoryBuilder当成一个工具类使用即可,不需要使用单例管理SqlSessionFactoryBuilder。

在需要创建SqlSessionFactory时候,只需要new一次SqlSessionFactoryBuilder即可。

5.2 SqlsessionFactory

通过SqlSessionFactory创建SqlSession,使用单例模式管理SqlSessionFactory(工厂一旦创建,使用一个实例)。

将来MyBatis和Spring整合后,使用单例模式管理SqlSessionFactory。

5.3 SqlSession

SqlSession是一个面向用户(程序员)的接口。

SqlSession提供了很多操作数据库的方法,如:selectOne(返回单个对象)、selectList(返回单个或多个对象)。

SqlSession是线程不安全的,在SqlSession实现类中除了有接口中的方法(操作数据库的方法)还有数据域属性。

SqlSession最佳应用场合在方法体内,定义成局部变量使用。

6.原始DAO开发

程序员需要写dao接口和dao实现类。

需要向dao的实现类中注入SqlSessionFactory,在方法体内通过SqlSessionFactory创建SqlSession.

原始dao开发问题

(1)dao接口实现类方法中存在大量模板方法,设想能否将这些代码提取出来,大大减轻程序员工作量。

(2)调用sqlSession方法时将statement的id硬编码了。

(3)调用sqlSession方法时传入的变量,由于sqlSession方法使用泛型,即使变量类型传入错误,在编译阶段也不报错,不利于程序员开发。

7.mapper代理

思路(mapper代理开发规范)

程序员需要编写mapper.xml映射文件

程序员编写mapper接口需要遵循一些开发规范,mybatis可以自动生成mapper接口实现类代理对象。

开发规范:

(1)在mapper.xml中namespace等于mapper接口地址

(2)mapper.java接口中的方法名和mapper.xml中statement的id一致

(3)mapper.java接口中的方法输入参数类型和mapper.xml中statement的parameterType指定的类型一致。

(4)mapper.java接口中的方法返回值类型和mapper.xml中statement的resultType指定的类型一致。

总结:

以上方法开发规范主要是对下边的代码进行统一生成:

User user = sqlSession.selectOne("test.findUserById", id);
sqlSession.insert("test.insertUser", user);
......

 

仅限个人使用 禁止转载

参考文献:

[1]Joanna.Yan.Spring+SpringMVC+MyBatis深入学习及搭建[EB/OL].http://www.cnblogs.com/Joanna-Yan/,2018-9-28.

[2]想你的夜713.Mybatis的基本运行原理[EB/OL].https://blog.csdn.net/u010289197/article/details/55061222?utm_source=copy,2018-9-28.

 

posted @ 2018-09-28 15:17  liouyee  阅读(108)  评论(0)    收藏  举报