查询一张表的所有数据。

环境:

使用工具IntelliJ IDEA 2018.2版本。

创建Maven工程不用骨架

 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.jxjdemo</groupId>
<artifactId>day34_mybatis1_curd_dao</artifactId>
<version>1.0-SNAPSHOT</version> <properties><!--锁定编译版本与字符集-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties> <dependencies>
<dependency><!--导入mysql依赖-->
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency> <dependency> <!--导入mybatis依赖-->
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency> <dependency> <!--导入日志依赖-->
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency> <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
</project>
  1. 表User
 package com.jxjdemo.domain;
import java.util.Date; public class User {
private Integer id;
private String username;
private Date birthday; //框架会帮我们自动转
private String sex;
private String address; @Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
//省略Get与Set方法

2.映射器XML

 <?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>

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.实现类

 package com.jxjdemo.dao.impl;
import com.jxjdemo.dao.UserDao;
import com.jxjdemo.domain.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import java.util.List; public class UserDaoImpl implements UserDao {//执行SQL语句用实现类做,不用代理对象。
//从工厂里面获取sqlsession对象
private SqlSessionFactory factory;//以后由sping整合sping创建,现在去测试类里面创建 public UserDaoImpl(SqlSessionFactory factory) {
this.factory = factory;
} @Override
public List<User> queryAll() {
SqlSession session = factory.openSession();
List<User> list = session.selectList("com.jxjdemo.dao.UserDao.queryAll");//返回的是Object但实际得到的是(UserDao)
session.close();//session关闭流,释放资源
return list;
}

5.测试类

 package com.jxjtest.test;

 import com.jxjdemo.dao.UserDao;
import com.jxjdemo.dao.impl.UserDaoImpl;
import com.jxjdemo.domain.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test; import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List; public class MybatisCurdTest {
private SqlSessionFactory factory;
private InputStream is;
private UserDao userDao; @Test
public void testQueryAll(){ //查询全部
//读取配置文件,获取sqlsession对象工厂,获取映射器提取
List<User> userList = userDao.queryAll();
for (User user : userList){
System.out.println(user);
}
}
@Before
public void init() throws IOException { //重复执行的代码,单独提取出来
is = Resources.getResourceAsStream("sqlMapConfig.xml");//提取成员变量后 // SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); //获取sqlsession对象,通过工厂构建一个,提取成员变量
factory = new SqlSessionFactoryBuilder().build(is);
userDao = new UserDaoImpl(factory);//提取成员变量
}
@After
public void destroy() throws IOException { //关流
is.close();
}
}

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

 <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--mybatis的核心配置文件,主要配置数据库连接信息-->
<configuration><!--根标签-->
<!--enxironments 可以配置多个数据库环境-->
<environments default="mysql"><!--default 默认使用的数据库-->
<environment id="mysql"><!--environment每一个数据库连接(配置)信息-->
<transactionManager type="JDBC" /><!--事物管理方式-->
<dataSource type="POOLED"><!--数据源。不使用UN连接池POOLED,POOLED使用连接池,JNDI查找数据源配置文件-->
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:端口号/库名"/>
<property name="username" value="账号"/>
<property name="password" value="密码"/>
</dataSource>
</environment>
</environments> <mappers>
<mapper resource="com/jxjdemo/dao/UserDao.xml" />
</mappers>
</configuration>

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

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

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

 List<User> userList = userDao.queryAll();

9.到实现类,获取session

 SqlSession session = factory.openSession();

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

 List<User> list = session.selectList("com.jxjdemo.dao.UserDao.queryAll");

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

 @Override
public <E> List<E> selectList(String statement) {
return this.selectList(statement, null);
} @Override
public <E> List<E> selectList(String statement, Object parameter) {
return this.selectList(statement, parameter, RowBounds.DEFAULT);
}

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

 public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
MappedStatement ms = configuration.getMappedStatement(statement);
return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}

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

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

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

  @Override
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
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方法。

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

18.找缓存。

 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);//
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);//2.

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

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

25.进入query到了RoutingStatementHandler.java

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

26.调了delegate到了PreparedStatementHandler.java

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

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

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

												

Mybatis 映射器接口实现类的方式 运行过程debug分析的更多相关文章

  1. Mybatis映射器接口代理对象的方式 运行过程

    查询一张表的所有数据. 环境: 使用工具IntelliJ IDEA 2018.2版本. 创建Maven工程不用骨架 1.pom.xml <?xml version="1.0" ...

  2. mybatis 映射器(mappers) 配置说明 加载映射文件方式

    映射器(mappers) 既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要定义 SQL 映射语句了.但是首先我们需要告诉 MyBatis 到哪里去找到这些语句. Java 在自动查找这 ...

  3. MyBatis映射器(转载)

    什么是MyBatis映射器? MyBatis框架包括两种类型的XML文件,一类是配置文件,即mybatis-config.xml,另外一类是映射文件,例如XXXMapper.xml等.在MyBatis ...

  4. MyBatis映射器(一)--多参数传递方式

    在mybatis映射器的接口中,一般在查询时需要传递一些参数作为查询条件,有时候是一个,有时候是多个.当只有一个参数时,我们只要在sql中使用接口中的参数名称即可,但是如果是多个呢,就不能直接用参数名 ...

  5. mybatis映射器配置细则

    前面三篇博客我们已经多次涉及到映射器的使用了,增删查基本上都用过一遍了,但是之前我们只是介绍了基本用法,实际上mybatis中映射器可以配置的地方还是非常多,今天我们就先来看看映射器还有哪些需要配置的 ...

  6. mybatis 映射器

    1 映射器 Mapper 是由java接口和 XML 文件共同组成.它的作用如下 1)定义参数类型 2)描述缓存 3)描述 SQL 语句 4)定义查询结果和POJO的映射关系 2 SqlSession ...

  7. 【长文】Spring学习笔记(七):Mybatis映射器+动态SQL

    1 概述 本文主要讲述了如何使用MyBatis中的映射器以及动态SQL的配置. 2 MyBatis配置文件概览 MyBatis配置文件主要属性如下: <settings>:相关设置,键值对 ...

  8. MyBatis映射器元素

     映射器是MyBatis最强大的工具,也是我们使用MyBatis时用的最多的工具,映射器中主要有增删改查四大元素,来满足不同场景的需要: 下面是主要元素的介绍:         select:查询语句 ...

  9. Mybatis映射器(一)

    XML查询参数: parameterType:可以给出类别名,全名等. resultType:查询结果,可以为 int,float,map等不可以与resultMap同时使用. resultMap: ...

随机推荐

  1. Python实现斐波那契数列,九九乘法表,金字塔方法。

    斐波那契数列普通函数实现 #普通函数 def fb(max): a,b=0,1 while a<max: print(a) a,b=b,a+b fb(100) 递归实现方法1 def fb1(m ...

  2. linux突然不能上网,eth0网卡消失

    情况:之前可以正常浏览网页,没有动其它的地方,浏览器突然不能上网 ifconfig # 发现eth0网卡不见了,只有lo卡 ifconfig -a # 发现了eth0,但是没有IP地址 dhclien ...

  3. Rxjava学习笔记

    1.使用Observable.range(int start, int count)创建一个发射特定整数序列的Observable,第一个参数为起始值,第二个为发送的个数,如果为0则不发送,负数则抛异 ...

  4. 201871010101-陈来弟《面向对象程序设计(java)》第二周学习总结

    201871010101-陈来弟<面向对象程序设计(java)>第二周学习总结 项目 内容 这个作业属于哪个课程 <任课教师博客主页链接>https://www.cnblogs ...

  5. udp,select超时和recvfrom收不到数据原因

    wirshark抓包,发现有数据.但是select超时,直接recvfrom又失败. 代码中需要改进:select超时后,会移除fd_set集合中超时的那个句柄,所以每次要重新进行FD_SET,然后再 ...

  6. 微信H5页面分享获取JS-SDK

    https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115  微信开发文档: 生成签名之前必须先了解一下jsapi_ti ...

  7. [RN] React Native 头部 滑动吸顶效果的实现

    React Native 头部 滑动吸顶效果的实现 效果如下图所示: 实现方法: 一.吸顶组件封装 StickyHeader .js import * as React from 'react'; i ...

  8. django -- ORM实现图书增删改查

    表结构设计 上篇我们实现了出版社的增删改查,出版社数据表有两个字段id和name,那图书的表结构怎么设计呢?图书也要有一个主键id,还要有一个名称title,是哪个出版社的,要有个字段press和Pr ...

  9. python总结四

    sql性能优化的几种方式: 1.查询的模糊匹配: 尽量避免在一个复杂查询里面使用like '%parm%',前面的%会导致相关列的索引无法使用,最好不要用 直接修改后台,根据输入条件,先查出符合条件的 ...

  10. 认识随机函数rand()和srand(unsigned int )

    rand函数 int rand( void ); 函数名:   rand 功   能:   随机数发生器 用   法:   int rand(void); 所在头文件: stdlib.h 函数说明 : ...