阿里巴巴面试题:如何创建Mybatik的Dao接口和XML文件SQL之间的关系?
阿里巴巴的这样一个面试题:
如何创建Mybatis Dao接口和XML文件SQL之间的关系?如果有两个 XML 文件与这个 DAO 形成关系,那不是会发生冲突吗?
如果你看过作者之前关于Mybatis源码分析的博文,我想你绝对可以给出很好的答案。 ? 。
1。创建SqlSource
Mybatis将每个SQL标签封装成一个SqlSource对象。然后根据SQL语句的不同,分为动态SQL和静态SQL。其中,静态SQL包括String类型的SQL语句;而动态SQL则由SqlNode组成。
假设我们有这样的 SQL:
<select id="getUserById" resultType="user">
select * from user
<where>
<if test="uid!=null">
and uid=#{uid}
</if>
</where>
</select>
相应的 SqlSource 对象应如下所示:
2。创建MappedStatement
XML文件中的每个SQL标签都对应一个MappedStatement对象,这两个属性非常重要。
- id
ID由完整的类名+方法名组成。
- sqlSource
与当前 SQL 标识符对应的 SqlSource 对象。
创建MappedStatement
对象后,将其缓存在Configuration#mappedStatements
中。
配置对象,我们知道它是Mybatis中的大管家,基本上所有的配置信息都维护在这里。解析完所有的XML之后,Configuration就包含了所有的SQL信息。
至此,XML解析完成。如果你看到上图,如果你足够聪明,你可能会有一个想法。当我们执行Mybatis方法时,通过全限定类名+方法名找到 我们的 Dao 接口没有实现类。那么,当我们调用它时,它最终是如何执行我们的SQL语句的呢? 首先,在Spring的配置文件中,我们通常定义如下: 或者如果你的项目是基于SpringBoot的,你一定见过这样的:MapperScan("com.xxx.dao") 他们做同样的事。注册Spring Bean中包路径下的所有类,并将其beanClass设置为 有趣的是, 那么这个方法有什么作用呢? 不了解此内容的朋友可以先熟悉一下spring中FactoryBean和JDK动态代理相关的资料。 曾经有朋友问过这样的问题: Mapper实现的dao接口还用代理吗? 答案是肯定的,只要配置 这到底是什么意思?我们来看一个例子。 然后我们将其添加到userDao的服务方法中。猜猜会发生什么? 也许你猜对了,是的,它开始报错。因为在注入的时候发现了两个UserMapper实例对象。日志如下: 当然,也许我们的命名不是规格非常正确。其实我们可以通过名称来添加,例如: 详细原理请找作者的文章: 了解Spring中的全自动配置和Autowired——掘金 juejin.im可能扯得太远了,我们还是回到Mybatis吧。所以现在我们还有一个通过 Dao 接口的代理实现来执行其上的方法。 上面说过,当我们调用Dao接口方法时,实际上调用的是代理对象的call方法。这里,实际上调用的是SqlSession这个东西。 看到上面的代码就说明我们想得不错。它通过命令 说到这里我们又回到了开头提到的问题。也许你可以更好地回答他们。同时,笔者觉得,如果在这个问题中讨论以下关键词,面试官就能非常满意。 作者:青狂羽MappedStatement
对象,并解析其中的SQL内容并执行。
2。 Dao 接口代理
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.viewscenes.netsupervisor.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
MapperFactoryBean
。 MapperFactoryBean
实现了FactoryBean
接口,俗称工厂bean。然后当我们通过@Autowired
添加这个Dao接口时,返回的对象就是这个工厂bean上的MapperFactoryBean
方法对象。
简单来说就是通过JDK动态代理返回一个Dao接口代理对象。该代理对象的处理器是 MapperProxy
对象。所有,当我们通过@Autowired
添加Dao接口时,代理对象就被注入了。当我们调用Dao接口的方法时,会调用MapperProxy
对象的call方法。 MapperScan
,它就会扫描然后创建代理。但是,如果你的 dao 接口有一个实现类,并且该实现类也是一个 Spring Bean,则取决于你在Autowired
时添加哪一个。
如果我们为userDao制作一个实现类并注册到Spring中。 @Component
public class UserDaoImpl implements UserDao{
public List<User> getUserList(Map<String,Object> map){
return new ArrayList<User>();
}
}
@Service
public class UserServiceImpl implements UserService{
@Autowired
UserMapper userDao1;
public List<User> getUserList(Map<String,Object> map) {
return userDao1.getUserList(map);
}
}
No valid bean type [com.viewscenes.netsupervisor.dao.UserDao] Defined: Expected a single Matching bean but found 2: userDaoImpl,userDao
@Autowired UserMapper userDao;
或@Autowired UserMapper userDaoImpl;
或者将@Primary添加到Beannation中。 3。执行
public class DefaultSqlSession implements SqlSession {
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
MappedStatement ms = configuration.getMappedStatement(statement);
return executor.query(ms,
wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
}
}
}
完全限定类名+方法名
获取一个MappedStatement对象,然后通过执行器Executor执行指定的SQL并返回。 4。总结
答案是显而易见的。无论有多少 XML 与 Dao 关联,只要确保 namespace+id
是唯一的即可。
来源:知乎
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。