使用Mapper接口和数据库交互
Mybatis将配置文件中的每一个<mapper>节点抽象为一个Mapper接口,而这个接口中声明的方法和mapper节点的<select|update|delete|insert>节点项对应。
2.数据处理层
数据处理层可以说是MyBatis 的核心,从大的方面上讲,它要完成三个功能:
a. 通过传入参数构建动态SQL语句;
b. SQL语句的执行以及封装查询结果集成List<E>
2.1.参数映射和动态SQL语句生成
动态语句生成可以说是MyBatis框架非常优雅的一个设计,MyBatis 通过传入的参数值,使用 Ognl 来动态地构造SQL语句,使得MyBatis 有很强的灵活性和扩展性。
参数映射指的是对于java 数据类型和jdbc数据类型之间的转换:这里有包括两个过程:查询阶段,我们要将java类型的数据,转换成jdbc类型的数据,通过 preparedStatement.setXXX() 来设值;另一个就是对resultset查询结果集的jdbcType 数据转换成java 数据类型。
2.2. SQL语句的执行以及封装查询结果集成List<E>
动态SQL语句生成之后,MyBatis 将执行SQL语句,并将可能返回的结果集转换成List<E> 列表。MyBatis 在对结果集的处理中,支持结果集关系一对多和多对一的转换,并且有两种支持方式,一种为嵌套查询语句的查询,还有一种是嵌套结果集的查询。
3. 框架支撑层
3.1. 事务管理机制
事务管理机制对于ORM框架而言是不可缺少的一部分
3.2. 连接池管理机制
由于创建一个数据库连接所占用的资源比较大, 对于数据吞吐量大和访问量非常大的应用而言,连接池的设计就显得非常重要
3.3. 缓存机制
为了提高数据利用率和减小服务器和数据库的压力,MyBatis 会对于一些查询提供会话级别的数据缓存,会将对某一次查询,放置到SqlSession 中,在允许的时间间隔内,对于完全相同的查询,MyBatis 会直接将缓存结果返回给用户,而不用再到数据库中查找。
3. 4. SQL语句的配置方式
传统的MyBatis 配置SQL 语句方式就是使用XML文件进行配置的,但是这种方式不能很好地支持面向接口编程的理念,为了支持面向接口的编程,MyBatis 引入了Mapper接口的概念,面向接口的引入,对使用注解来配置SQL 语句成为可能,用户只需要在接口上添加必要的注解即可,不用再去配置XML文件了,但是,目前的MyBatis 只是对注解配置SQL 语句提供了有限的支持,某些高级功能还是要依赖XML配置文件配置SQL 语句。
mysql的主要构件
- SqlSession 作为MyBatis工作的主要顶层API,表示和数据库交互的会话,完成必要数据库增删改查功能
- Executor MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护
- StatementHandler 封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数、将Statement结果集转换成List集合。
- ParameterHandler 负责对用户传递的参数转换成JDBC Statement 所需要的参数,
- ResultSetHandler 负责将JDBC返回的ResultSet结果集对象转换成List类型的集合;
- TypeHandler 负责java数据类型和jdbc数据类型之间的映射和转换
- MappedStatement MappedStatement维护了一条<select|update|delete|insert>节点的封装,
- SqlSource 负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回
- BoundSql 表示动态生成的SQL语句以及相应的参数信息
- Configuration MyBatis所有的配置信息都维持在Configuration对象之中。
MyBatis把数据源分为三种:
- unpooled 不使用连接池的数据源
- pooled 使用连接池的数据源
- jndi 使用jndi实现的数据源
PooledDataSource需要创建java.sql.Connection实例对象时,还是通过UnpooledDataSource来创建。PooledDataSource只是提供一种缓存机制。
DataSource什么时候创建Connection对象
当我们需要创建SqlSession对象并需要执行SQL语句时,这时候Mybatis才会去调用dataSource对象来创建java.sql.Connection对象,也就是说,java.sql.Connection对象的创建一直延迟到执行SQL语句的时候。
UnpooledDataSource如何实现getConnection方法
使用UnpooledDataSource的getConnection(),每调用一次就会产生一个新的Connection实例对象
- 初始化驱动:
- 创建Connection对象
- 配置Connection对象:是否自动提交和隔离级别
- 返回Connection对象
每调用一次getConnection()方法,都会通过DriverManager.getConnection()返回新的java.sql.Connection实例
为什么要使用连接池?
创建一个Connection对象的代价是250ms,而sql执行时间为170ms,代价很高。
使用了连接池的PooledDataSource
PooledDataSource将Connection对象包裹成PooledConnection对象放到了PoolState类型的容器中维护,MyBatis将连接池中的PooledConnection分为两种状态:空闲状态和活动状态,这两种状态的PooledConnection对象分别存储到PoolState容器内的idleConnections和activeConnections两个List集合:
- idleConnections:调用getConnection()方法时,优先从此集合取PooledConnection对象
- activeConnections:如果从idleConnections集合中取PooledConnection对象时,没有取到,则看此集合是否已满,如果未满,PooledDataSource会创建出一个PooledConnection,添加到此集合中,并返回。
当程序中使用完Connection对象时,如果不使用数据库连接池,一般会用connetion.close()方法,关闭connection连接,释放资源。那么使用连接池之后如何处理呢?
怎样实现Connection对象调用了close()方法,而实际是将其添加到连接池中呢
这里要使用代理模式,为真正的Connection对象创建一个代理对象,代理对象所有的方法都是调用相应的真正Connection对象的方法实现,当代理对象执行close()时,要做特殊处理,不调用真正Connection对象的close()方法,而是将Connection对象添加到连接池中。
PooledConnection对象内持有一个真正的数据库连接java.sql.Connection实例对象和一个java.sql.Connection的代理。
mybatis事务管理机制
对数据库的事务而言,应该具有以下几点:创建(create)、提交(commit)、回滚(rollback)、关闭(close),对应地,mybatis将事务抽象成了Transaction接口。
myBatis事务管理机制分两种:
- 使用JDBC的事务管理机制:即利用java.sql.Connection对象完成对事务的提交、回滚、关闭
- 使用MANAGED的事务管理机制:这种机制mybatis自身不会去实现事务管理,而是让程序的容器来实现对事务的管理
可看代码:JdbcTransaction和ManagedTransaction