• mybatis 05: mybatis中的动态代理


    mybatis中动态代理存在的意义

    • 图示

    image

    • 图示分析

      • 分层说明:界面层为第一层,业务逻辑层(接口层 + 实现层)为第二层,数据访问层(接口层 + 实现层)为第三层

      • 业务逻辑层和数据访问层:分别分两层来开发,是开发中的规范

        • 接口层:为了面向接口编程,使开发更加灵活
        • 实现层:落实具体功能,完成具体的实现
      • 调用规范:在每一层的实现层,用下一层的接口指向下一层的实现,通过调用该实现类的方法来完成功能

        • 例如,界面层的下一层为业务逻辑层,则在界面层的调用代码应为:业务逻辑层的接口指向业务逻辑层的实现,然后调用该实现类的方法

          UsersService uService = new UsersServiceImpl();
          uService.insert(XXXX);
          
    • mybatis框架中动态代理存在的意义

      • 但是,在mybatis框架中sql语句的执行是通过定位mapper.xml文件中的sql标签来实现的,而业务逻辑层的实现类无法使用上述"调用规范"
        • 原因:我们无法new出mapper.xml文件对象,这是一个".xml"文件,不是一个简单的实现类,也就无法使用该mapper.xml文件中的sql标签
      • 问题的本质:我们需要在业务逻辑实现层使用mapper.xml文件中的sql标签,调用其功能,但是又无法直接访问该mapper.xml文件
      • 使用动态代理解决需要访问mapper.xml文件,却又无法直接访问该mapper.xml文件的问题,这就是mybatis框架中动态代理存在的意义

    mybatis中动态代理的实现规范

    • UsersMapper.xml文件与UsersMapper.java的接口必须位于同一目录下
    • UsersMapper.xml文件与UsersMapper.java的接口文件名必须一样,后缀随意
    • UsersMapper.xml文件中标签的id值与UsersMapper.java的接口中方法的名称完全一致
    • UsersMapper.xml文件中标签的parameterType属性值与UsersMapper.java的接口中方法的参数类型完全一致
    • UsersMapper.xml文件中标签的resultType属性值与UsersMapper.java的接口中方法的返回值类型完全一致
    • UsersMapper.xml文件中的namespace属性必须是接口的完全限定名称,例如:com.example.mapper.UsersMapper
    • 在SqlMapConfig.xml文件中注册mapper文件时,使用class="接口的完全限定名称",例如:class=com.example.mapper.UsersMapper

    mybatis中动态代理访问的步骤

    参考:mybatis 02: 添加并配置mybatis

    • 新建users表,插入测试数据
    • 新建maven工程
      • 修改目录结构
      • 修改pom.xml文件,添加依赖
      • 添加资源文件指定
    • 添加jdbc.properties文件到resources目录下
    • 添加SqlMapConfig.xml文件到resources目录下
    
    configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    <configuration>
    
        
        <properties resource="jdbc.properties"/>
    
    
        
        <settings>
            <setting name="logImpl" value="STDOUT_LOGGING"/>
        settings>
    
    
        
        <typeAliases>
            <package name="com.example.pojo"/>
        typeAliases>
    
    
        
        <environments default="develop">
            <environment id="develop">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="${jdbc.driverClassName}"/>
                    <property name="url" value="${jdbc.url}"/>
                    <property name="username" value="${jdbc.username}"/>
                    <property name="password" value="${jdbc.password}"/>
                dataSource>
            environment>
        environments>
    
    
        
        <mappers>
            <mapper class="com.example.mapper.UsersMapper"/>
        mappers>
    configuration>
    
    • 添加实体类

    • 添加mapper文件夹,新建UsersMapper接口

      package com.example.mapper;
      
      import com.example.pojo.Users;
      
      import java.util.List;
      
      /**
       * 数据访问层的接口,定义对数据库完成的CRUD的操作
       */
      public interface UsersMapper {
          //获取全部用户信息
          List getAll();
      }
      
      • 在该文件夹下,新建UsersMapper.xml文件,完成对users表的CRUD操作
      
      mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      
      <mapper namespace="com.example.mapper.UsersMapper">
          
          <select id="getAll" resultType="users">
              select
                      id, username, birthday, sex, address
              from
                  users
          select>
      mapper>
      
    • 添加测试类,测试功能

    mybatis借助动态代理实现对users表的CRUD操作

    查询全部用户信息

    • 测试代码
    package com.example.mapper;
    
    import com.example.pojo.Users;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    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.List;
    
    public class TestUsersMapper {
        //SqlSession对象
        SqlSession sqlSession;
    
        //获取SqlSession
        @Before
        public void getSqlSession() throws IOException {
            //读取核心配置文件
            InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
            //创建SqlSessionFactory对象
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
            //获取SqlSession
            sqlSession = factory.openSession();
        }
    
        //归还SqlSession
        @After
        public void closeSession(){
            sqlSession.close();
        }
    
        @Test
        public void testGetAll(){
            //获取mybatis动态代理对象
            UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
            //调用代理的功能
            List users = usersMapper.getAll();
            //输出查询结果
            users.forEach(System.out::println);
        }
    }
    
    • 输出结果的部分内容
    Checking to see if class com.example.pojo.Users matches criteria [is assignable to Object]
    PooledDataSource forcefully closed/removed all connections.
    PooledDataSource forcefully closed/removed all connections.
    PooledDataSource forcefully closed/removed all connections.
    PooledDataSource forcefully closed/removed all connections.
    
    Opening JDBC Connection
    
    Created connection 1548946718.
    
    Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@5c530d1e]
    
    ==>  Preparing: select id, username, birthday, sex, address from users
    ==> Parameters: 
    <==    Columns: id, username, birthday, sex, address
    <==        Row: 1, 小涵, 2000-09-10, 2, 黑河市
    <==        Row: 2, 小王, 2001-07-12, 1, 芜湖市
    <==        Row: 3, 小张, 1999-02-22, 1, 长沙
    <==        Row: 4, 小吴, 2002-11-19, 1, 成都
    <==        Row: 5, 段, 2001-03-10, 1, 太原
    <==        Row: 6, 范成群, 2002-01-19, 1, 鲅鱼圈
    <==        Row: 7, 学委, 2001-05-13, 2, 平顶山市
    <==      Total: 7
    Users{id=1, userName='小涵', birthday=Sun Sep 10 00:00:00 CST 2000, sex='2', address='黑河市'}
    Users{id=2, userName='小王', birthday=Thu Jul 12 00:00:00 CST 2001, sex='1', address='芜湖市'}
    Users{id=3, userName='小张', birthday=Mon Feb 22 00:00:00 CST 1999, sex='1', address='长沙'}
    Users{id=4, userName='小吴', birthday=Tue Nov 19 00:00:00 CST 2002, sex='1', address='成都'}
    Users{id=5, userName='段', birthday=Sat Mar 10 00:00:00 CST 2001, sex='1', address='太原'}
    Users{id=6, userName='范成群', birthday=Sat Jan 19 00:00:00 CST 2002, sex='1', address='鲅鱼圈'}
    Users{id=7, userName='学委', birthday=Sun May 13 00:00:00 CST 2001, sex='2', address='平顶山市'}
    
    Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@5c530d1e]
    
    Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@5c530d1e]
    
    Returned connection 1548946718 to pool.
    
    Process finished with exit code 0
    
  • 相关阅读:
    问题汇总20231110
    《六月集训》(第二十四天)——线段树
    Go语言 context包源码学习
    ​​​​奇迹mu开服务端架设服务器
    Golang入门笔记(7)—— 函数 func
    输运方程的推导
    浮点数类型讲解
    设计模式-工厂设计模式
    唯品会获得vip商品详情 API 返回值说明
    Netty系列(一):Springboot整合Netty,自定义协议实现
  • 原文地址:https://www.cnblogs.com/nefu-wangxun/p/16572523.html