Mybatis 映射器接口实现类的方式 运行过程debug分析
查询一张表的所有数据。
环境:
使用工具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>
- 表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分析的更多相关文章
- Mybatis映射器接口代理对象的方式 运行过程
查询一张表的所有数据. 环境: 使用工具IntelliJ IDEA 2018.2版本. 创建Maven工程不用骨架 1.pom.xml <?xml version="1.0" ...
- mybatis 映射器(mappers) 配置说明 加载映射文件方式
映射器(mappers) 既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要定义 SQL 映射语句了.但是首先我们需要告诉 MyBatis 到哪里去找到这些语句. Java 在自动查找这 ...
- MyBatis映射器(转载)
什么是MyBatis映射器? MyBatis框架包括两种类型的XML文件,一类是配置文件,即mybatis-config.xml,另外一类是映射文件,例如XXXMapper.xml等.在MyBatis ...
- MyBatis映射器(一)--多参数传递方式
在mybatis映射器的接口中,一般在查询时需要传递一些参数作为查询条件,有时候是一个,有时候是多个.当只有一个参数时,我们只要在sql中使用接口中的参数名称即可,但是如果是多个呢,就不能直接用参数名 ...
- mybatis映射器配置细则
前面三篇博客我们已经多次涉及到映射器的使用了,增删查基本上都用过一遍了,但是之前我们只是介绍了基本用法,实际上mybatis中映射器可以配置的地方还是非常多,今天我们就先来看看映射器还有哪些需要配置的 ...
- mybatis 映射器
1 映射器 Mapper 是由java接口和 XML 文件共同组成.它的作用如下 1)定义参数类型 2)描述缓存 3)描述 SQL 语句 4)定义查询结果和POJO的映射关系 2 SqlSession ...
- 【长文】Spring学习笔记(七):Mybatis映射器+动态SQL
1 概述 本文主要讲述了如何使用MyBatis中的映射器以及动态SQL的配置. 2 MyBatis配置文件概览 MyBatis配置文件主要属性如下: <settings>:相关设置,键值对 ...
- MyBatis映射器元素
映射器是MyBatis最强大的工具,也是我们使用MyBatis时用的最多的工具,映射器中主要有增删改查四大元素,来满足不同场景的需要: 下面是主要元素的介绍: select:查询语句 ...
- Mybatis映射器(一)
XML查询参数: parameterType:可以给出类别名,全名等. resultType:查询结果,可以为 int,float,map等不可以与resultMap同时使用. resultMap: ...
随机推荐
- Sigmoid函数与Softmax函数的理解
1. Sigmod 函数 1.1 函数性质以及优点 其实logistic函数也就是经常说的sigmoid函数,它的几何形状也就是一条sigmoid曲线(S型曲线). 其中z ...
- NLP中的预训练语言模型(一)—— ERNIE们和BERT-wwm
随着bert在NLP各种任务上取得骄人的战绩,预训练模型在这不到一年的时间内得到了很大的发展,本系列的文章主要是简单回顾下在bert之后有哪些比较有名的预训练模型,这一期先介绍几个国内开源的预训练模型 ...
- 网络编程 TCP协议:三次握手,四次回收,反馈机制 socket套接字通信 粘包问题与解决方法
TCP协议:传输协议,基于端口工作 三次握手,四次挥手 TCP协议建立双向通道. 三次握手, 建连接: 1:客户端向服务端发送建立连接的请求 2:服务端返回收到请求的信息给客户端,并且发送往客户端建立 ...
- ubuntu下vi/vim 的基本用法
https://blog.csdn.net/weixin_37657720/article/details/80645991 :q! 不保存强制推出. :wq 保存并退出.
- 每天一道Rust-LeetCode(2019-06-03)
每天一道Rust-LeetCode(2019-06-02) 有序链表转换二叉搜索树 坚持每天一道题,刷题学习Rust. 原题 题目描述 给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜 ...
- jdbc笔记2
private static String driver; private static String url; private static String username; private sta ...
- ESA2GJK1DH1K基础篇: 关于各大物联网平台的MQTT通信
前言 这节稍微唠叨点 其实我很长时间都没有出怎么连接现成的物联网平台的教程, 一直写的是教给大家自己搭建服务器,主要原因是因为我感觉连接现有的学不到东西. 现在出这种教程,是因为发现确实很多人喜欢用. ...
- 洛谷 p3870 开关 线段树模板
这两天学了很长时间于是做了一道水题 我就用了模板,就连任何优化都没有 就AC了,复杂度也很爆炸10个点1500多毫秒 这个题就是把lazy[]改成记录下修改的次数,每次修改的时候mod 2,因为反过来 ...
- 4.28(TG模拟赛)总结
1.挖地雷 题目背景 NOIp1996提高组第三题 题目描述 在一个地图上有N个地窖(N≤20),每个地窖中埋有一定数量的地雷.同时,给出地窖之间的连接路径.当地窖及其连接的数据给出之后,某人可以从任 ...
- Burnside引理
参考了神仙gzy的博客 置换:把一个排列变成另外一个排列,简单来说就是一一映射. 置换群:置换的集合. 置换即给定一个排列\({f_1,f_2,...,f_n}\),若其作用在一个排列上,则这个排列置 ...