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

查询一张表的所有数据。

环境:

使用工具IntelliJ IDEA 2018.2版本。

创建Maven工程不用骨架

1.pom.xml

 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>day33_mybatis1_quicksta</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         <!--MySql数据库-->
19         <dependency><!-- 依赖  -->
20             <groupId>mysql</groupId><!--公司名/组织名groupId:域名倒写 -->
21             <artifactId>mysql-connector-java</artifactId><!--项目包/包名 -->
22             <version>5.1.47</version><!--版本号version:1.0-SNAPSHOT 开发版   1.0-RELEASE稳定发行版 -->
23         </dependency>
24             <!--MyBatis的jar包-->
25         <dependency>
26             <groupId>org.mybatis</groupId>
27             <artifactId>mybatis</artifactId>
28             <version>3.5.2</version>
29         </dependency>
30             <!--日志包-->
31         <dependency>
32             <groupId>log4j</groupId>
33             <artifactId>log4j</artifactId>
34             <version>1.2.17</version>
35         </dependency>
36             <!--单元测试-->
37         <dependency>
38             <groupId>junit</groupId>
39             <artifactId>junit</artifactId>
40             <version>4.12</version>
41             <scope>test</scope>  <!--加test单元测试只能写在test内-->
42         </dependency>
43     </dependencies>
44 
45 </project>

2.表-类

 1 package com.jxjdemo.domain;
 2 
 3 import java.util.Date;
 4 
 5 public class User {
 6     private Integer id;
 7     private String username;
 8     private Date birthday;   //导包,框架自动帮我们转可以这样写。
 9     private String sex;
10     private String address;
11 
12     @Override
13     public String toString() {
14         return "User{" +
15                 "id=" + id +
16                 ", username='" + username + '\'' +
17                 ", birthday=" + birthday +
18                 ", sex='" + sex + '\'' +
19                 ", address='" + address + '\'' +
20                 '}';
21     }
22 //省略Get与Set方法

3.映射器

1 package com.jxjdemo.dao;
2 import com.jxjdemo.domain.User;
3 import java.util.List;
4 /**
5  * 映射器:dao层的接口
6  */
7 public interface UserDao {
8       List<User> queryAll();
9 }

4.映射器配置文件

 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 <!--
 6    上面为引入的约束
 7  _____________________________________________________________
 8 下面的mapper:映射器配置
 9     namespace:映射器的全限定类名
10 -->
11 <mapper namespace="com.jxjdemo.dao.UserDao">
12     <!--
13        statement:映射器里面每个方法的配置信息,叫做statement
14        select标签:用于查询
15        insert标签:用于插入
16        update标签:用于修改
17        delete标签:用于删除
18 
19         以上四个标签都有的属性:
20         id:映射器里面写 方法的名称
21         resultType 结果集封装的类型
22     -->
23     <select id="queryAll" resultType="com.jxjdemo.domain.User">
24           select * from user
25     </select>
26 </mapper>

5.数据库核心配置文件

 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     <mappers><!--映射器-->
20         <mapper resource="com/jxjdemo/dao/UserDao.xml" />
21     </mappers>
22 </configuration>

6.测试类

 1 package com.jxjtest.test;
 2 
 3 import com.jxjdemo.dao.UserDao;
 4 import com.jxjdemo.domain.User;
 5 
 6 import org.apache.ibatis.io.Resources;
 7 import org.apache.ibatis.session.SqlSession;
 8 import org.apache.ibatis.session.SqlSessionFactory;
 9 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
10 import org.junit.Test;
11 
12 import java.io.IOException;
13 import java.io.InputStream;
14 import java.util.List;
15 
16 public class QuickstartTest { //Quickstart快速开始
17     @Test
18     public void testQuickStart() throws IOException {
19         //1.读取配置文件
20         InputStream is = Resources.getResourceAsStream("sqlMapConfig.xml"); //抛出异常
21 
22         //2.读取到Sqlsession对象.要从SqlSessionFactory里面生产SqlSession对象
23         SqlSessionFactory facyory = new SqlSessionFactoryBuilder().build(is);
24         //new一个工厂,给他传流,返回一个工厂对象
25         SqlSession session = facyory.openSession();//有了工厂对象,就用openSession得到session
26 
27         //3.操作数据库
28         UserDao userDao = session.getMapper(UserDao.class);//使用getMapper返回UserDao对象,动态代理有接口就行。创建代理对象
29         List<User> userList = userDao.queryAll();
30         for (User user : userList) {
31             System.out.println(user);
32         }
33         //4.释放资源
34         session.close();
35         is.close();
36     }
37 }

7.项目结构

8..在测试类打断点,开始deBug跟踪,从这里开始。首先得到UserDao,dao对象是一个代理对象。

1  UserDao userDao = session.getMapper(UserDao.class);//使用getMapper返回UserDao对象
2 
List<User> userList = userDao.queryAll();

9.到MapperProxy.java里的invole方法

 1  @Override
 2   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 3     try {
 4       if (Object.class.equals(method.getDeclaringClass())) {//1.
 5         return method.invoke(this, args);
 6       } else if (method.isDefault()) {//2.
 7         return invokeDefaultMethod(proxy, method, args);
 8       }
 9     } catch (Throwable t) {
10       throw ExceptionUtil.unwrapThrowable(t);
11     }
12     final MapperMethod mapperMethod = cachedMapperMethod(method);//3.
13     return mapperMethod.execute(sqlSession, args);//4.开始执行映射器的方法进入方法
14   }

10.到了MapperMethod.java中

 1 public Object execute(SqlSession sqlSession, Object[] args) {
 2     Object result;
 3     switch (command.getType()) {//1.判断登陆类型
 4       case INSERT: {
 5         Object param = method.convertArgsToSqlCommandParam(args);
 6         result = rowCountResult(sqlSession.insert(command.getName(), param));
 7         break;
 8       }
 9       case UPDATE: {
10         Object param = method.convertArgsToSqlCommandParam(args);
11         result = rowCountResult(sqlSession.update(command.getName(), param));
12         break;
13       }
14       case DELETE: {
15         Object param = method.convertArgsToSqlCommandParam(args);
16         result = rowCountResult(sqlSession.delete(command.getName(), param));
17         break;
18       }
19       case SELECT:
20         if (method.returnsVoid() && method.hasResultHandler()) {
21           executeWithResultHandler(sqlSession, args);//2.执行查询,就是select
22           result = null;
23         } else if (method.returnsMany()) {//3.根据方法返回值判断,returnsMany()返回多个
24           result = executeForMany(sqlSession, args);//4.调了executeForMany进入
25         } else if (method.returnsMap()) {
26           result = executeForMap(sqlSession, args);
27         } else if (method.returnsCursor()) {
28           result = executeForCursor(sqlSession, args);
29         } else {
30           Object param = method.convertArgsToSqlCommandParam(args);
31           result = sqlSession.selectOne(command.getName(), param);
32           if (method.returnsOptional()
33               && (result == null || !method.getReturnType().equals(result.getClass()))) {
34             result = Optional.ofNullable(result);
35           }
36         }
37         break;

11.到了executeForMany

1 private <E> Object executeForMany(SqlSession sqlSession, Object[] args) {
2     List<E> result;
3     Object param = method.convertArgsToSqlCommandParam(args);//1.准备方法的参数
4     if (method.hasRowBounds()) {//2.因为查询全部,没有参数,所以参数是null
5       RowBounds rowBounds = method.extractRowBounds(args);
6       result = sqlSession.selectList(command.getName(), param, rowBounds);
7     } else {
8       result = sqlSession.selectList(command.getName(), param);//到了这里setlectList与
9     }

12.剩余请看步骤截图。与https://www.cnblogs.com/jxearlier/p/11625253.html从11步开始。

13.完整流程如下。

猜你喜欢

转载自www.cnblogs.com/jxearlier/p/11626279.html
今日推荐