mybatis学习笔记3:完成DAO层的开发及实现过程分析

在开发中,一般不推荐自己去实现DAO接口类,而是直接使用mybatis封装好的功能,但是从学习的角度来看,也有必要明白如何使用mybatis完成DAO层的开发。

文章目录

  • 一、自定义DAO实现类完成CRUD
    • 1.自定义DAO实现类
      • 1.1实现findAll()方法
      • 1.2注意测试类的改造
      • 1.2实现saveUser()方法
      • 1.3实现updateUser()方法
  • 二、自定义实现DAO的过程分析
    • 1.查询操作分析
    • 2.增删改操作分析
  • 三、代理对象实现DAO的过程分析

一、自定义DAO实现类完成CRUD

1.自定义DAO实现类

1.1实现findAll()方法

注意其中工厂类的属性设置和初始化,以及查询类的实现

public class UserDaoImpl implements IUserDao {

    SqlSessionFactory factory;
    public UserDaoImpl(SqlSessionFactory factory){
        this.factory = factory;
    }


    public List<User> findAll() {
        //1.根据factory获取SqlSession对象
        SqlSession session = factory.openSession();
        //2.调用SqlSession中的方法 完成查询
        // 这里面的参数就是 IUserDao.xml中 的namespace.id
        List<User> users = session.selectList("com.xpt.dao.IUserDao.findAll");
        //3.释放资源
        session.close();
        return users;
    }
    }

1.2注意测试类的改造

  • 初始化和销毁的改造

在这里插入图片描述- 测试方法

    @Test
    public void testFindAll(){
        //5.执行查询
        List<User> users = userDao.findAll();
        //6.打印
        for (User user : users) {
            System.out.println(user);
        }
    }
  • 可以发现自己写DAO实现类会多很多代码,所以并不推荐这种方式

1.2实现saveUser()方法

    public void saveUser(User user) {
        //1.根据factory获取SqlSession对象
        SqlSession session = factory.openSession();
        //2.调用方法实现保存 注意有两个参数
        session.insert("com.xpt.dao.IUserDao.saveUser",user);
        //3.保存操作需要提交事务
        session.commit();
        //4.释放资源
        session.close();

    }
  • 测试类代码:
    @Test
    public void testSaveUser(){
        User user = new User();
        user.setUsername("xiaopang");

        user.setAddress("sichaun");
        user.setSex("m");
        user.setBirthday( new Date());
        System.out.println("执行插入前:" + user);
        //5.执行查询
        userDao.saveUser(user);
        System.out.println("执行插入后:" + user);
    }

1.3实现updateUser()方法

    public void updateUser(User user) {
        //1.根据factory获取SqlSession对象
        SqlSession session = factory.openSession();
        //2.调用方法实现保存 注意有两个参数
        session.update("com.xpt.dao.IUserDao.updateUser",user);
        //3.保存操作需要提交事务
        session.commit();
        //4.释放资源
        session.close();
    }
  • 测试类
    @Test
    public void testUpdateUser(){
        User user = new User();
        user.setUsername("xiaozhu userdaoImpl");
        user.setId(50);

        user.setAddress("hunan");
        user.setSex("m");
        user.setBirthday( new Date());
//        System.out.println(user);
        //5.执行更新
        userDao.updateUser(user);
    }
  • 其余的方法,大同小异,不再赘述

二、自定义实现DAO的过程分析

此节采用一步步debug的方式,对一个方法的执行过程进行深入分析,先以测试类中的testFindAll方法为例,尝试一步步看这个代码是如何执行的。

1.查询操作分析

  • 若直接根据方法名进行跳转,发现只能进入接口定义的方法,无法直接跳转到具体的实现类,所以这里需要debug的方式
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第1张图片- 分别在测试类和方法实现类中打断点
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第2张图片- 在测试类的方法中,开启debug模式
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第3张图片- 跳转执行
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第4张图片

  • 此时我们先暂时不继续往后debug,先搞清楚这个DefaultSqlSession对象是什么,这个类在哪里,以及方法selectList方法的实现。

  • 同样的,如果直接通过方法跳转,只能看到SqlSession这个接口中的方法
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第5张图片

  • 而通过刚才的debug,可以确定真正调用selectList方法的是DefaultSqlSession这个对象,所以这肯定是SqlSession的一个实现类,那如何找到这个实现类以及方法呢

mybatis学习笔记3:完成DAO层的开发及实现过程分析_第6张图片

  • 现在找到了这个方法,发现一个有三个,那到底真正调用的哪一个呢
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第7张图片mybatis学习笔记3:完成DAO层的开发及实现过程分析_第8张图片
  • 所以接下来,我们需要找到executor这个类,直接点击跳转,发现又是一个接口,采用上述的方法查看接口的实现类,发现具有多个实现类,为了能确定这里是哪一个实现类调用了方法,这里又只能打断点来查看具体的实现类是哪一个
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第9张图片mybatis学习笔记3:完成DAO层的开发及实现过程分析_第10张图片
  • 仍然从测试类方法开始debug,此时前面两个断点可以取消掉,只保留上述的一个断点,此时会直接跳转到此处
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第11张图片
  • 可以发现,点击debug后,会直接跳转到上述断点位置,此时就可以确定这个具体的实现类是CachingExecutor
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第12张图片
  • 下面我们就进入CachingExecutor类,找到对应方法
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第13张图片在这里插入图片描述
  • 继续debug到上述断点的位置
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第14张图片
  • 跳转到上述的query方法内
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第15张图片
  • 继续往后执行
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第16张图片mybatis学习笔记3:完成DAO层的开发及实现过程分析_第17张图片mybatis学习笔记3:完成DAO层的开发及实现过程分析_第18张图片
  • 查看SimpleExecutor
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第19张图片
    在这里插入图片描述
  • 发现和query相关的方法只有一个,但是这个类继承了BaseExecutor,所以肯定在这里进行了一步转换
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第20张图片
  • 查看BaseExecutor
    在这里插入图片描述
  • BaseExecutor找到query方法
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第21张图片
  • 查看queryFromDatabase方法
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第22张图片
  • 终于找到了doQuery,继续查看
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第23张图片
  • 这个抽象的doQuery就是被SimpleExecutor实现了,所以最终执行的是SimpleExecutordoQuery方法
  • 所以打断点,继续往后走
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第24张图片
  • 继续走,找到handler是谁
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第25张图片
  • 查看handlermybatis学习笔记3:完成DAO层的开发及实现过程分析_第26张图片
  • 发现query方法,打断点继续走
    在这里插入图片描述mybatis学习笔记3:完成DAO层的开发及实现过程分析_第27张图片- 查看PreparedStatementHandler
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第28张图片mybatis学习笔记3:完成DAO层的开发及实现过程分析_第29张图片
  • 找到query方法,打断点,进入
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第30张图片- 查看resultSetHandler
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第31张图片
    在这里插入图片描述-寻找方法handleResultSets
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第32张图片
  • 到这里就完成了整个findAll()方法的实现过程
  • 其他方法也几乎大同小异
    -下面再把整个过程串一下,用一张图总结,图小,点开看
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第33张图片

2.增删改操作分析

增删改和上述的稍微有一点点区别

  • 这里的分析,我们就从接口的实现类开始,可以看到,增删改的方法在实现中,其实只是用session调用了三个不同的方法而已
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第34张图片- 显然,这里的方法和上面一样都是接口SqlSession中的方法,实现类是DefaultSqlSession,所以我们进入这个类,查看相关方法
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第35张图片- 所以我们接下来,只需要分析这一个方法即可,可以发现这个方法,最后又集中到了这个方法中
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第36张图片- 这里和前文一致,我们直接进入CachingExecutor类,找到对应方法
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第37张图片

  • 同样的发现delegate这个对象,根据前文找到SimpleExecutor
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第38张图片

  • 发现一个doUpdate方法,根据前面的经验,这里仍然是通过BaseExecutor转换了一层,接下来进入BaseExecutor
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第39张图片

  • 这里显然和前文一样的处理方法在BaseExecutor中通过方法update调用抽象方法doUpdate,然后这个抽象方法doUpdate又被SimpleExecutor实现,所以这里又回到SimpleExecutor中执行
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第40张图片

  • 这里同样的发现,调用了一个handler的方法,进入handler,根据前文,这里handler是一个接口StatementHandler的实现类对象,这个实现类是RoutingStatementHandler,下面进入RoutingStatementHandler
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第41张图片

  • 发现这里又调用了一个delegate.update,根据前文经验,这里应该是PreparedStatementHandler,下面进入这个类,寻找update方法
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第42张图片

  • 终于找到了我们熟悉的JDBC中的相关对象

  • 这里就是最终执行sql的地方

三、代理对象实现DAO的过程分析

上面分析了自定义DAO的实现过程,但是mybatis更主流的还是不写实现类,直接通过代理对象来实现DAO,下面以findAll函数为例,分析代理对象的执行过程,只需要分析到selectList后面的流程都是一致的

  • 首先我们从代理对象的创建开始
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第43张图片

  • 通过session.getMapper方法,拿到了代理对象,下面进入getMapper方法
    在这里插入图片描述

  • 发现进入的是SqlSession接口中的方法,根据前文我们应该知道,这里的实现类是DefaultSqlSession
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第44张图片

  • 发现这里又调用了一层configuration.getMapper,继续进入configuration.getMapper
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第45张图片

  • 发现configuration就是一个java类,可以直接进入找到方法,又继续进入mapperRegistry,找到getMapper方法
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第46张图片

  • 继续进入mapperProxyFactory.newInstance(sqlSession),先明确调用顺序
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第47张图片

  • 再观察代码,发现这里的实现就是动态代理技术,下面进入mapperProxy
    在这里插入图片描述

  • 发现熟悉的InvocationHandler接口,和invoke方法
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第48张图片- 下面进入mapperMethod.execute方法
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第49张图片

  • 到这里,我们几乎明白了,这个代理对象到底是怎么工作的了,是如何通过接口实现代理方法的了,下面进入executeForMany
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第50张图片

  • 终于发现了selectList方法,后面的执行过程,就和前文一致了

  • 下面一张图简单总结上述过程
    mybatis学习笔记3:完成DAO层的开发及实现过程分析_第51张图片

你可能感兴趣的:(mybatis,JavaWeb)