Mybatis 映射器接口实现类的方式 运行过程debug分析

查询一张表的所有数据。

环境:

使用工具IntelliJ IDEA 2018.2版本。

创建Maven工程不用骨架

 1 
 2  3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     4.0.0
 6 
 7     com.jxjdemo
 8     day34_mybatis1_curd_dao
 9     1.0-SNAPSHOT
10 
11     
12         UTF-8
13         1.8
14         1.8
15     
16 
17     
18         
19             mysql
20             mysql-connector-java
21             5.1.47
22         
23 
24          
25             org.mybatis
26             mybatis
27             3.5.2
28         
29 
30          
31             log4j
32             log4j
33             1.2.17
34         
35 
36         
37             junit
38             junit
39             4.12
40         
41     
42 
  1. 表User
 1 package com.jxjdemo.domain;
 2 import java.util.Date;
 3 
 4 public class User {
 5     private Integer id;
 6     private String username;
 7     private Date birthday; //框架会帮我们自动转
 8     private String sex;
 9     private String address;
10 
11     @Override
12     public String toString() {
13         return "User{" +
14                 "id=" + id +
15                 ", username='" + username + '\'' +
16                 ", birthday=" + birthday +
17                 ", sex='" + sex + '\'' +
18                 ", address='" + address + '\'' +
19                 '}';
20     }
21 //省略Get与Set方法

        2.映射器XML

1 xml version="1.0" encoding="utf-8"?>
2 DOCTYPE mapper
3         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
4         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5         <mapper namespace="com.jxjdemo.dao.UserDao">
6 
7         <select id="queryAll" resultType="com.jxjdemo.domain.User">
8                 select * from user
9         select>

 

      3.映射器配置文件


DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
        

        
        

      4.实现类

 1 package com.jxjdemo.dao.impl;
 2 import com.jxjdemo.dao.UserDao;
 3 import com.jxjdemo.domain.User;
 4 import org.apache.ibatis.session.SqlSession;
 5 import org.apache.ibatis.session.SqlSessionFactory;
 6 import java.util.List;
 7 
 8 public class UserDaoImpl implements UserDao {//执行SQL语句用实现类做,不用代理对象。
 9     //从工厂里面获取sqlsession对象
10     private SqlSessionFactory factory;//以后由sping整合sping创建,现在去测试类里面创建
11 
12     public UserDaoImpl(SqlSessionFactory factory) {
13         this.factory = factory;
14     }
15 
16     @Override
17     public List queryAll() {
18         SqlSession session = factory.openSession();
19         List list = session.selectList("com.jxjdemo.dao.UserDao.queryAll");//返回的是Object但实际得到的是(UserDao)
20         session.close();//session关闭流,释放资源
21         return list;
22     }

5.测试类

 1 package com.jxjtest.test;
 2 
 3 import com.jxjdemo.dao.UserDao;
 4 import com.jxjdemo.dao.impl.UserDaoImpl;
 5 import com.jxjdemo.domain.User;
 6 import org.apache.ibatis.io.Resources;
 7 import org.apache.ibatis.session.SqlSessionFactory;
 8 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
 9 import org.junit.After;
10 import org.junit.Before;
11 import org.junit.Test;
12 
13 import java.io.IOException;
14 import java.io.InputStream;
15 import java.util.Date;
16 import java.util.List;
17 
18 public class MybatisCurdTest {
19     private SqlSessionFactory factory; 
20     private InputStream is;      
21     private UserDao userDao;  
22 
23     @Test
24     public void testQueryAll(){ //查询全部
25         //读取配置文件,获取sqlsession对象工厂,获取映射器提取
26         List userList = userDao.queryAll();
27         for (User user : userList){
28             System.out.println(user);
29         }
30     }
31 @Before
32     public void init() throws IOException { //重复执行的代码,单独提取出来
33         is = Resources.getResourceAsStream("sqlMapConfig.xml");//提取成员变量后
34 
35         // SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); //获取sqlsession对象,通过工厂构建一个,提取成员变量
36         factory = new SqlSessionFactoryBuilder().build(is);
37         userDao = new UserDaoImpl(factory);//提取成员变量
38     }
39     @After
40     public void destroy() throws IOException {  //关流
41         is.close();
42     }
43 }

 6.数据库核心配置文件XML

 1 xml version="1.0" encoding="UTF-8" ?>
 2 DOCTYPE configuration
 3         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 4         "http://mybatis.org/dtd/mybatis-3-config.dtd">
 5 
 6 <configuration>
 7     
 8     <environments default="mysql">
 9         <environment id="mysql">
10             <transactionManager type="JDBC" />
11             <dataSource type="POOLED">
12                 <property name="driver" value="com.mysql.jdbc.Driver" />
13                 <property name="url" value="jdbc:mysql://localhost:端口号/库名"/>
14                 <property name="username" value="账号"/>
15                 <property name="password" value="密码"/>
16             dataSource>
17         environment>
18     environments>
19 
20     <mappers>
21         <mapper resource="com/jxjdemo/dao/UserDao.xml" />
22     mappers>
23 configuration>

  7.省略log4j日志配置文件,目录结构。

Mybatis 映射器接口实现类的方式 运行过程debug分析_第1张图片

8.在测试类打断点,开始deBug跟踪,从这里开始。

相册里面有步骤截图,可以配合一起看。

1 List userList = userDao.queryAll();

9.到实现类,获取session

1 SqlSession session = factory.openSession();

10.跟踪这行代码做了什么事情,进入这个方法。

1 List list = session.selectList("com.jxjdemo.dao.UserDao.queryAll");

11.到了DefaultSqlSession.java类里面,在selectList调了selectList,方法的重载。

1 @Override
2   public  List selectList(String statement) {
3     return this.selectList(statement, null);
4   }
5 
6   @Override
7   public  List selectList(String statement, Object parameter) {
8     return this.selectList(statement, parameter, RowBounds.DEFAULT);
9   }

12.到了ms,获取数据库,配置文件信息,与SQL类型。关键在于executor.query执行查询。

 1 public  List selectList(String statement, Object parameter, RowBounds rowBounds) {
 2     try {
 3       MappedStatement ms = configuration.getMappedStatement(statement);
 4       return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
 5     } catch (Exception e) {
 6       throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
 7     } finally {
 8       ErrorContext.instance().reset();
 9     }
10   }

13.先对wrspCollection(parameter)包装一下。回到12.

1 if (object instanceof Collection) {这里省略}

14.进入CachingExecutor.java.这个类自己不执行。

1  @Override
2   public  List query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
3     BoundSql boundSql = ms.getBoundSql(parameterObject);

15.这里第一步,从ms.getBoundSql获取到了绑定的SQL语句。

CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);//缓存相关忽略

16.继续调query方法重载。

return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);

17.到了query方法。

1 @Override
2   public  List query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
3       throws SQLException {
4     Cache cache = ms.getCache();

18.找缓存。

1 if (cache != null) {

19.缓存里面没有,CachingExecutor.java.这个类自己不执行,就调了delegate委托者。

 return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);

20.CachingExecutor.java.这个类是从父类继承的,所以到了BaseExecutor.java.

@Override
  public  List query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());

21.往下走。

if (closed) {//1.
if (queryStack == 0 && ms.isFlushCacheRequired()) {//2.
queryStack++;//3.
list = resultHandler == null ? (List) localCache.getObject(key) : null;//4.
if (list != null) {//5.

22.到了queryFromDatabase开始到库里面查询。

list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);

23.BaseExecutor.java.执行了doQuery方法

localCache.putObject(key, EXECUTION_PLACEHOLDER);//1
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);//2.

24.进入doQuery查看,到了SimpleExecutor.java

1 public  List doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
2     Statement stmt = null;//1
3 Configuration configuration = ms.getConfiguration();//2.configuration所有的配置信息
4 StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);//3.
5 stmt = prepareStatement(handler, ms.getStatementLog());//4.准备得到一个
6 return handler.query(stmt, resultHandler);//5.handler.query开始真正执行了

25.进入query到了RoutingStatementHandler.java

return delegate.query(statement, resultHandler);//调了delegate

26.调了delegate到了PreparedStatementHandler.java

1 public  List query(Statement statement, ResultHandler resultHandler) throws SQLException {
2     PreparedStatement ps = (PreparedStatement) statement;PreparedStatement预编译对象
3     ps.execute();//2.获取预编译对象,执行任意语句
4     return resultSetHandler.handleResultSets(ps);//
5   }

到了这里就是最终的结果,剩余处理结果集,封装的事情了。

结果:Mybatis封装的再深底层还是JDBC。

 

 

 

 

 

你可能感兴趣的:(Mybatis 映射器接口实现类的方式 运行过程debug分析)