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目录下
<?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">

<configuration>

    <!-- 读取属性文件(jdbc.properties)-->
    <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>


    <!--注册mapper.xml文件-->
    <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<Users> getAll();
    }
    
    • 在该文件夹下,新建UsersMapper.xml文件,完成对users表的CRUD操作
    <?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.example.mapper.UsersMapper">
        <!--
            //获取全部用户信息
            List<Users> getAll();
        -->
        <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 = factory.openSession(true);设置事务自动提交,默认或者传入false代表手动提交
    }

    //归还SqlSession
    @After
    public void closeSession(){
        sqlSession.close();
    }

    @Test
    public void testGetAll(){
        //获取mybatis动态代理对象
        UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
        //调用代理的功能
        List<Users> 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
posted @ 2022-08-10 15:08  rocket-raccoon  阅读(419)  评论(0编辑  收藏  举报