Mybatis 映射器接口实现类的方式 运行过程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>
- 表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日志配置文件,目录结构。
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。
原文地址: https://www.cnblogs.com/jxearlier/p/11625253.html
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
相关文章