下面是“MyBatis的通俗理解:SqlSession.getMapper()源码解读”的完整攻略。
一、背景介绍
在MyBatis中,SqlSession.getMapper()方法是一个非常重要的方法,可以获取到Mapper接口的代理对象,从而进行数据库操作。但是,为什么可以用一个接口进行数据库操作呢?这就需要了解一下MyBatis的动态代理机制。
二、MyBatis动态代理机制
在MyBatis中,每个Mapper接口都需要对应一个Mapper XML文件,该文件中定义了该接口中所有方法的SQL语句。但是,MyBatis并不是直接将该接口转换为SQL语句执行,而是通过动态代理方式生成该接口的实现类,从而运行接口中的方法。
例如,定义如下一个UserMapper接口:
public interface UserMapper {
User getUserById(int id);
}
对应的Mapper XML文件定义如下:
<mapper namespace="com.example.dao.UserMapper">
<select id="getUserById" parameterType="int" resultType="User">
select * from user where id = #{id}
</select>
</mapper>
则通过动态代理方式,可以生成如下的UserMapper实现类:
public class UserMapperImpl implements UserMapper {
private SqlSession sqlSession;
public UserMapperImpl(SqlSession sqlSession) {
this.sqlSession = sqlSession;
}
public User getUserById(int id) {
return sqlSession.selectOne("com.example.dao.UserMapper.getUserById", id);
}
}
这样,通过SqlSession的getMapper()方法获取到的UserMapper实例就是通过动态代理生成的,可以使用Mapper XML文件中定义的SQL语句进行数据库操作。
三、SqlSession.getMapper()源码解读
现在,我们来看看SqlSession.getMapper()方法的源码实现:
public <T> T getMapper(Class<T> type) {
return configuration.getMapper(type, this);
}
可以看到,这里调用了Configuration.getMapper()方法,而Configuration是MyBatis中的核心配置类,负责解析XML文件并创建相应的对象。我们可以继续查看getMapper()方法的实现:
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
if (mapperProxyFactory == null)
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
try {
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
可以看到,这里首先根据type从knownMappers中获取到MapperProxyFactory对象,MapperProxyFactory是一个代理工厂类,专门用于生成Mapper接口的代理对象。如果获取不到MapperProxyFactory对象,则说明该接口没有对应的Mapper XML文件,将抛出BindingException异常。否则,将通过mapperProxyFactory.newInstance()方法创建代理对象。
四、示例演示
下面通过两个示例演示如何使用SqlSession.getMapper()方法。
示例一
假设我们有一个UserMapper接口,定义了所有和用户相关的数据库操作方法,代码如下:
public interface UserMapper {
User getUserById(int id);
List<User> getUsersByGender(String gender);
void addUser(User user);
void updateUser(User user);
void deleteUser(int id);
}
正确的使用方式如下:
SqlSession sqlSession = MyBatisUtils.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUserById(1);
assert user != null;
sqlSession.commit();
sqlSession.close();
可以看到,通过SqlSession.getMapper()方法获取到UserMapper的代理对象,然后就可以使用该对象中定义的方法进行数据库操作。
示例二
如果我们有一个ArticleMapper接口,但是没有对应的Mapper XML文件,使用SqlSession.getMapper()方法将无法获取到该接口的代理对象,代码如下:
public interface ArticleMapper {
Article getArticleById(int id);
}
错误的使用方式如下:
SqlSession sqlSession = MyBatisUtils.getSqlSession();
ArticleMapper articleMapper = sqlSession.getMapper(ArticleMapper.class); // 会抛出BindingException异常
sqlSession.close();
可以看到,getMapper()方法将抛出BindingException异常,提示该接口对应的Mapper XML文件不存在。
五、总结
通过本文对MyBatis的通俗理解:SqlSession.getMapper()源码解读进行讲解,我们可以了解到MyBatis的动态代理机制是如何工作的,并且可以正确地使用SqlSession.getMapper()方法进行数据库操作。同时,通过示例演示,还可以更好地理解该方法的使用方式和常见错误。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:MyBatis的通俗理解:SqlSession.getMapper()源码解读 - Python技术站