【MyBatis篇】MyBatis动态代理总结

本人正在浅学mybatis,正学到mybatis动态代理,在查询多方资料之后做出以下总结,以便于系统学习时回顾;

目录

MyBatis为什么引入动态代理

mybatis的动态代理

 Dao代理技术


MyBatis为什么引入动态代理

因为程序员的  懒,为了节省代码的书写量,将书写复杂,没有一点子营养的机械代码交给java内置工具去写,下面使用案例解释;

一个完整的项目应该直接或间接拥有以下结构:

我们可以了解到里面有一个dao层的接口,还有dao层的实现dao.impl,之所以写这个接口,是因为在规范的实际开发中,写dao层的接口是编程规范,是必须写的。我们前期学习的时候会感觉dao层接口是没有实际作用的,也就是可以没有 ,但是实际开发中必不可少;下面是我前期的dao层代码;

编写AccountDao接⼝,以及AccountDaoImpl实现类

public interface AccountDao {
 /**
 * 根据账号获取账户信息
 * @param actno 账号
 * @return 账户信息
 */
 Account selectByActno(String actno);
 /**
 * 更新账户信息
 * @param act 账户信息
 * @return 1表示更新成功,其他值表示失败
 */
 int update(Account act);
}
package com.powernode.bank.dao.impl;
import com.powernode.bank.dao.AccountDao;
import com.powernode.bank.pojo.Account;
import com.powernode.bank.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
public class AccountDaoImpl implements AccountDao {
 @Override
 public Account selectByActno(String actno) {
 SqlSession sqlSession = SqlSessionUtil.openSession();
 Account act = (Account)sqlSession.selectOne("selectByActno", actno
);
 sqlSession.close();
 return act;
 }
 @Override
 public int update(Account act) {
 SqlSession sqlSession = SqlSessionUtil.openSession();
 int count = sqlSession.update("update", act);
 sqlSession.commit();
 sqlSession.close();
 return count;
 }
}

与之对应的sql映射文件,也就是mapper.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="account">
 <select id="selectByActno" resultType="com.powernode.bank.pojo.Accoun
t">
 select * from t_act where actno = #{actno}
 </select>
 <update id="update">
 update t_act set balance = #{balance} where actno = #{actno}
 </update>
</mapper>

实际应用dao层以及dao的实现类:

public class AccountServiceImpl implements AccountService {
 private AccountDao accountDao = new AccountDaoImpl();
 @Override
 public void transfer(String fromActno, String toActno, double money) t
hrows MoneyNotEnoughException, AppException {
 // 查询转出账户的余额
 Account fromAct = accountDao.selectByActno(fromActno);
 if (fromAct.getBalance() < money) {
 throw new MoneyNotEnoughException("对不起,您的余额不⾜。");
 }
 try {
 // 程序如果执⾏到这⾥说明余额充⾜
 // 修改账户余额
 Account toAct = accountDao.selectByActno(toActno);
 fromAct.setBalance(fromAct.getBalance() - money);
 toAct.setBalance(toAct.getBalance() + money);
 // 更新数据库
 accountDao.update(fromAct);
 accountDao.update(toAct);
 } catch (Exception e) {
 throw new AppException("转账失败,未知原因!");
 }
 }
}

以上就是一个雏形的mybatis项目中的dao层的使用与代码书写; 

上面的案例演示中只涵盖了一张表,然而当我们的项目中包含了很多张表,每一张表都对应一个mapper.xml文件,那就会需要多个dao层的接口,那我们是不是要写很多的实现类呢???数量到达千万级,岂不是要做很多重复的代码,枯燥无味。

于是前辈们就想能不能使用一个方法,让dao层的某一个接口默认直接和某一个mapper.xml文件相互映射对应;让dao层接口中的每一个方法都完全正确的对应mapper.xml文件中的一个SQL语句,这样我们就可以避免书写dao层的实现类,换句话说:就是让MyBatis框架给我们自动生成dao层接口的实现类。

mybatis的动态代理

上面的想法是可以实现的,称为MyBatis的动态代理。

employeeDao mapper = sqlSession.getMapper(employeeDao.class);

使⽤以上代码的前提是:AccountMapper.xml⽂件中的namespace必须和dao接⼝的全限定名称⼀致, id必须和dao接⼝中⽅法名⼀致。

<mapper namespace="com.node.dao.employeeDao">
    <insert id="insert">
        insert into employee
            (id, name, age, position)
            value
            (#{id},#{name},#{age},#{position});
    </insert>

 dao接口:

public interface employeeDao {
    /**
    *@auther 
    *Description 插入数据
    *@Date 15:08 2023/10/6
    *@param emp
    *@Return int
    **/
    int insert(employee emp);
}

当我们执行下面这条语句时:

employeeDao mapper = sqlSession.getMapper(employeeDao.class);

 MyBatis框架底层是根据你的Dao接口,通过反射技术 在内存中虚拟的创建了dao接口的实现类对象。MyBatis把这个技术叫做  dao 的动态代理,或者是dao的代理技术;

然后我们就可以使用这个Mapper对象,对数据表进行增删改查:

employee employee = mapper.selectById(1);

 Dao代理技术

由MyBatis创建Dao接口的实现类DaoImpl,使用这个框架创建的实现类来代替你自己写的实现类的功能;那么这样就不需要开发人员自己写实现类了;但是框架实际创建的并不是就叫这个名字, 框架创建的实现类的真正名字是  proxy。

使用MyBatis动态代理技术的前提:
AccountMapper.xml⽂件中的namespace必须和dao接⼝的全限定名称⼀致, id必须和dao接中⽅法名⼀致。

在mapper.xml文件中,<mapper>标签有一个namespace属性,这个属性的属性值在整个项目中是惟一的。每一个SQL语句的标签,select,insert,delete等,都有一个id属性值,这个id属性值在这个mapper.xml文件中又是唯一的。这样根据这个字符串地址就能唯一确定一个SQL语句。

按照编码规范,namespace属性值必须是这个mapper.xml文件对应的dao层接口类的全限定路径名称。id属性值必须是这个sql 语句对应的dao层接口类中的方法名。

只有这样,MyBatis才能自动生成dao层接口对应的实现类。才能实现dao层接口的动态代理。

实际应用:

public class proxyTest {
    @Test
    public void test(){
        SqlSession sqlSession = mybatisUtil.getSqlSession();
        employeeDao mapper = sqlSession.getMapper(employeeDao.class);
        employee employee = mapper.selectById(1);
        System.out.println(employee);
    }
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值