欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-04-10 22:21:08
查询一张表的所有数据。 环境: 使用工具IntelliJ IDEA 2018.2版本。 创建Maven工程不用骨架 2.映射器XML 3.映射器配置文件 4.实现类 5.测试类 6.数据库核心配置文件XML 7.省略log4j日志配置文件,目录结构。 8.在测试类打断点,开始deBug跟踪,从这里开 ......

查询一张表的所有数据。

环境:

使用工具intellij idea 2018.2版本。

创建maven工程不用骨架

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <project xmlns="http://maven.apache.org/pom/4.0.0"
 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     <modelversion>4.0.0</modelversion>
 6 
 7     <groupid>com.jxjdemo</groupid>
 8     <artifactid>day34_mybatis1_curd_dao</artifactid>
 9     <version>1.0-snapshot</version>
10 
11     <properties><!--锁定编译版本与字符集-->
12         <project.build.sourceencoding>utf-8</project.build.sourceencoding>
13         <maven.compiler.source>1.8</maven.compiler.source>
14         <maven.compiler.target>1.8</maven.compiler.target>
15     </properties>
16 
17     <dependencies>
18         <dependency><!--导入mysql依赖-->
19             <groupid>mysql</groupid>
20             <artifactid>mysql-connector-java</artifactid>
21             <version>5.1.47</version>
22         </dependency>
23 
24         <dependency> <!--导入mybatis依赖-->
25             <groupid>org.mybatis</groupid>
26             <artifactid>mybatis</artifactid>
27             <version>3.5.2</version>
28         </dependency>
29 
30         <dependency> <!--导入日志依赖-->
31             <groupid>log4j</groupid>
32             <artifactid>log4j</artifactid>
33             <version>1.2.17</version>
34         </dependency>
35 
36         <dependency>
37             <groupid>junit</groupid>
38             <artifactid>junit</artifactid>
39             <version>4.12</version>
40         </dependency>
41     </dependencies>
42 </project>
  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"><!--mapper:映射器配置/namespace:映射器的全限定类名-->
6 
7         <select id="queryall" resulttype="com.jxjdemo.domain.user"><!--查询所有-->
8                 select * from user
9         </select>

 

      3.映射器配置文件

<?xml version="1.0" encoding="utf-8"?><!--引入约束-->
<!doctype mapper
        public "-//mybatis.org//dtd mapper 3.0//en"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
        <mapper namespace="com.jxjdemo.dao.userdao"><!--mapper:映射器配置/namespace:映射器的全限定类名-->

        <select id="queryall" resulttype="com.jxjdemo.domain.user">
                select * from user
        </select>
        </mapper>

      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<user> queryall() {
18         sqlsession session = factory.opensession();
19         list<user> 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<user> 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 <!--mybatis的核心配置文件,主要配置数据库连接信息-->
 6 <configuration><!--根标签-->
 7     <!--enxironments 可以配置多个数据库环境-->
 8     <environments default="mysql"><!--default 默认使用的数据库-->
 9         <environment id="mysql"><!--environment每一个数据库连接(配置)信息-->
10             <transactionmanager type="jdbc" /><!--事物管理方式-->
11             <datasource type="pooled"><!--数据源。不使用un连接池pooled,pooled使用连接池,jndi查找数据源配置文件-->
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分析

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

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

1 list<user> userlist = userdao.queryall();

9.到实现类,获取session

1 sqlsession session = factory.opensession();

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

1 list<user> list = session.selectlist("com.jxjdemo.dao.userdao.queryall");

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

1 @override
2   public <e> list<e> selectlist(string statement) {
3     return this.selectlist(statement, null);
4   }
5 
6   @override
7   public <e> list<e> selectlist(string statement, object parameter) {
8     return this.selectlist(statement, parameter, rowbounds.default);
9   }

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

 1 public <e> list<e> 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 <e> list<e> 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 <e> list<e> 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 <e> list<e> 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<e>) 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 <e> list<e> 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 <e> list<e> 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。