「Mybatis实战九」:Mybatis的dao层开发使用 - 代理开发方式

本文介绍了如何利用Mybatis的接口代理模式来优化传统开发中的DAO层设计,通过接口与XML映射文件的配合,实现自动化数据库操作,提升开发效率和代码清晰度。
摘要由CSDN通过智能技术生成

一、前言

​ 本文将进一步探讨在之前“「Mybatis实战八」:传统开发方式下的Mybatis DAO层构建”所奠定的基础之上,如何运用Mybatis的接口代理开发模式来优化持久层的设计与实现,解决上文中的问题。

二、代理开发方式简介

Mybatis提供的基于接口的代理开发方式是现代企业级应用中广泛采用的标准实践。这种方式允许开发者仅需专注于定义Mapper接口,而无需编写其实现类。Mybatis框架会在运行时依据这些接口自动生成代理对象,负责处理数据访问操作。为确保正确映射,遵循以下规范:

  1. Mapper.xml映射文件的namespace属性应与对应的Mapper接口的全限定名一致。
  2. Mapper接口的方法名必须与Mapper.xml中的每个SQL statement的id相匹配。
  3. Mapper接口方法的输入参数类型应当与XML中定义的SQL语句的parameterType类型相同。
  4. Mapper接口方法返回值类型(或输出参数类型)应与XML中定义的SQL语句的resultType类型保持一致。

在这里插入图片描述

通过这种方式,开发人员仅需关注业务逻辑相关的Mapper接口设计,具体的数据库交互由Mybatis自动完成。

三、代码演示

  1. 移除UserMapper接口原有的实现类UserMapperImpl。

  2. 调整UserMapper.xml配置文件以适应接口代理模式的使用要求。

    <?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="mapper.UserMapper">
       <!--  查询所有用户  -->
       <select id="findAll" resultType="user">
           select *
           from user
       </select>
    
       <!--根据id查找用户-->
       <select id="findUserById" parameterType="int" resultType="user">
           select * from user where id=#{id}
       </select>
    
       <!--新增用户-->
       <!--#{} : mybatis中的占位符,等同于JDBC中的
           parameterType :指定接收到的参数类型 -->
       <insert id="save" parameterType="domain.User">
           insert into user(username, birthday, sex, address)
           values (#{username}, #{birthday}, #{sex}, #{address})
       </insert>
    
       <!--  更新用户  -->
       <update id="update" parameterType="domain.User">
           update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
       </update>
    
       <!--删除用户 java.lang.Integer-->
       <delete id="delete" parameterType="int">
           delete from user where id = #{id}
       </delete>
    
    </mapper>
    
  3. 修改SqlMapConfig.xml文件,加载映射配置 即 mapper标签 需要更新

    注意 UserMapper 的接口类 需要 和 UserMapper.xml文件层级保持一致

    在这里插入图片描述

    SqlMapConfig.xml修改:

    <?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>
        <properties resource="jdbc.properties"></properties>
    
        <typeAliases>
            <!--方式一:给单个实体起别名-->
    <!--        <typeAlias type="domain.User" alias="user"></typeAlias>-->
            <!--方式二:批量起别名 别名就是类名,且不区分大小写-->
            <package name="domain"/>
        </typeAliases>
    
        <!--环境配置-->
        <environments default="mysql">
            <!--使用mysql环境-->
            <environment id="mysql">
                <!--使用jdbc事务管理亲-->
                <transactionManager type="JDBC"></transactionManager>
                <!-- 使用连接池-->
                <dataSource type="POOLED">
                    <property name="driver" value="${jdbc.driver}"/>
                    <property name="url" value="${jdbc.url}"/>
                    <property name="username" value="${jdbc.username}"/>
                    <property name="password" value="${jdbc.password}"/>
                </dataSource>
            </environment>
        </environments>
    
        <!--加载映射配置-->
        <mappers>
            <mapper resource="mapper/UserMapper.xml"></mapper>
        </mappers>
    
    </configuration>
    
  4. 修改测试类,将依赖从原来的实现类改为直接使用Mapper接口。

    package test;
    
    import domain.User;
    import mapper.UserMapper;
    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.Test;
    
    import java.io.InputStream;
    
    public class MybatisTest {
    
        @Test
        public void testFindUserById() throws Exception {
            InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
            SqlSession sqlSession = sqlSessionFactory.openSession();
    
            //获取Mapper代理对象
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
            User user = mapper.findUserById(1);
            System.out.println(user);
    
            sqlSession.close();
        }
    }
    
    
  5. 测试结果

    在这里插入图片描述

四、Mybatis基于接口代理方式的内部执行原理

当我们采用接口代理方式进行开发后,虽然表面上只保留了不包含具体实现的Mapper接口,但实际的数据查询工作是由Mybatis框架巧妙地通过动态代理机制完成的:

  1. Mybatis为每个定义的Mapper接口创建一个代理对象,该代理对象由MapperProxy类生成。

    在这里插入图片描述

  2. 当调用Mapper接口的某个方法时,实际上触发的是MapperProxy的invoke方法。

    • MapperProxy 实现了 InvocationHandler,也就是采用了 JDK动态代理,那么真正执行的方法在实现的invoke接口方法中

      在这里插入图片描述

    • invoke方法

      在这里插入图片描述

  3. 在invoke方法内部,进一步调用了mapperMethod.execute(sqlSession, args)来执行具体的数据库操作。

    在这里插入图片描述

  4. 最终,真正与数据库交互的核心组件SqlSession被调用,它根据映射规则执行相应的SQL,并将结果映射回Java对象,从而实现了透明化的数据访问服务。

  • 31
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值