Mybatis接口式编程的原理

网友投稿 242 2023-06-02


Mybatis接口式编程的原理

Mybatis 有两种实现方式

其一:通过xml配置文件实现

其二:面向接口编程的实现

前者原理在Mybatis运行套路里面大致说了一下,此节说的是后者,面向接口的编程,可以解决掉 namespace / 传入参数 / 返回值 / 与Sql关联Id 等四处风险。

意思就是,Mybatis配置文件Dao.xml找了一个接口作为自己的代言人,并告诉其他的java对象,以后访问数据库不要再骚扰我这个Dao.xml文件了,你去找我的代言人助理它会全权负责的。

如果接口助理要全权负责Dao.xml文件的所有工作,那么,Dao.xml文件肯定要和代言接口交接清楚工作任务,不能然接口乱搞。

仍旧以访问数据库信息列表为例:

首先要定义一个接口IMessage和Dao.xml文件里面的各种配置项一一对应:

package hdu.terence.dao;

import java.util.List;

import hdu.terence.bean.Message;

public interface IMessage {

publicList queryMessageList(Message message);

}

Dao.xml文件配置:

wBqWS PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

SELECTID,COMMAND,DESCRIPTION,CONTENT FROM message WHERE 1=1

andCOMMAND=#{command}

andDESCRIPTION like '%' #{description} '%'

测试:

public List queryMessageListByMybatis(Stringcommand,String description)

{

DBAccess dbAccess =new DBAccess();

SqlSession sqlSession=null;

ListmessageList=new ArrayList();

try {

sqlSession=dbAccess.getSqlSession();

Message message=new Message();

message.setCommand(command);

message.setDescription(description);

//方式二:通过接口调用配置文件里面的sql语句

IMessageimessage=sqlSession.getMapper(IMessage.class);

messageList=imessage.queryMessageList(message);

} catch (IOException e) {

e.printStackTrace();

}

finally{

if(sqlSession!=null)

{

sqlSession.close(); //要关闭数据库会话

}

}

return messageList;

}

第一,Dao.xml文件命名空间要和接口的全名保持一致:写接口的全名(包括报名com.terence.dao.IMessage)方便接口找到配置文件的命名空间。

第二,接口定义代言的sql语句对应的方法:queryMessageList(),方法名要和代言的sql语句配置项的id:queryMessageList相同,方便接口根据自己声明的方法映射到对应的配置项id。

第三,接口声明的方法带入的形参Message要和Dao.xml文件对应配置项需要的参数保持一致。

第四,接口声明的方法的返回值类型List要和Dao.xml文件id配置项resultMap类型一致。

这样就完成了接口的代理工作,配置文件会告诉其他的Java代码,以后通过这个接口就可以完成我本来要完成的工作,执行Sql语句对数据库完成交互工作;很明显,这种接口式编程比以前的直接调用配置文件方便多了,以前直接调用配置文件,每次使用配置文件,都需要写配置文件的命名空间、id、参数和返回值,这些地方有时候会手滑写不一致,如果出错,编译器不会出现提示,开发者只能根据执行结果错误提示推敲错误的地方慢慢调试。如果使用接口式编程,通过将配置文件dao.xml和定义的接口一一匹配对应,通过接口代理配置文件,以后不管谁使用都可以直接调用接口下,不用管配置文件里面的命名空间和sql配置ID,调用接口时如果出错,会自动提示,更有利于错误的查找。

但是,如果仅仅在Mybatis中使用接口式编程,并没有什么显著的效果,但是当Mybatis遇到sprinhttp://g的时候,效果就显著了。

当Mybatis遇到Spring,Mybatis的核心配置文件Configuration.xml中连接数据库的配置,就会取代了Spring中的DB层,Mybatis中的SqlSession会话将会托管给Spring,上述的MessageDao.xml部分带入参数调用接口的部分都会托管给Spring的Service来完成。此时我们定义的IMessage接口将会替代原来的Dao层,此时的Dao层只剩下接口文件和JavaDao.xml配置文件.

Mybatis接口式编程的原理

第一个问题,明天为什么接口Imssage.queryMessageList()没有实现类,但是却可以调用对应的方法?

首先要有一个创建代理实例的类,类里面有个方法invoke();

MapperProxy implements InvocationHandler

{

MapperProxy.invoke();

}

当我们调用接口的时候,走的是Invoke()方法,会通过Proxy.NewProxyInstance()加载一个代理实例,实际上也就是通过sqlSession.getMapper()来获取代理实例,即

sqlSession.getMapper()==Proxy.newProxyInstance();

IMessage imessage=sqlSession.getMapper(IMessage.class);

messageList=imessage.queryMessageList(message);

这样,即使IMessage自身没有实现类,但是通过SqlSession的getMapper方法带入接口类IMessage.class,就可以获取一个IMessage类型的代理实例,很明显,这里是泛型在起作用,带入什么样的类型,就得到一个什么类型的接口,原因是Mybatis已经利用泛型做了强转了;

第二个问题,既然是通过invoke()方法,它是怎么知道我们要调用sqlSession.selectList()方法?

因为刚初始化sqlSession的时候,加载了Configuration.xml文件,并在改文件中加载了各个JavaDao.xml文件,而这个Configuration.xml文件对应了Mybatis中相关的类:Configuration,接口的全名称在Invoke()方法里面都可以拿到, 接口全名称.方法名==namespace.id,所以可以拿到配置文件中的查询方法。

SqlSession的获取

public SqlSession getSqlSession() throws IOException

{

//1、通过配置文件获取数据库连接相关信息

Readerreader=Resources.getResourceAsReader("hdu/terence/config/Configuration.xml");

//2、通过配置信息构建SqlSessionFactory

SqlSessionFactorySSF=newSqlSessionFactoryBuilder().build(reader);

//3、通过SqlSessionFactory打开数据库会话

SqlSessionsqlSession=SSF.openSession();

return sqlSession; }

SqlSession通过上述配置实现,首先通过Resources.getResourceAsReader(“配置文件路径”)方法加载配置文件包装一个reader对象,然后通过SqlSessionFactory这个接口带入reader对象,获取一个动态代理实例,即SqlSessionFactory会话工厂,通过会话工厂得到一个会话SqlSession().

其中,在获取会话工厂获取实例的时候,底层实现源码是将带入的参数read作为key,找到Map中对应的value值,即MapperProxyFactory。

以上所述是给大家介绍的Mybatis接口式编程的原理,希望对大家有所帮助,如果大家有任何疑问请给我留言,会及时回复大家的。在此也非常感谢大家对我们网站的支持!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:如何设计一个秒杀系统
下一篇:Java 基础之事务详细介绍
相关文章

 发表评论

暂时没有评论,来抢沙发吧~