Appearance
上一章我们最终的实现效果是传递参数调用Mapper中的SQL语句,即sqlSession.selectList("user.selectList", null);
;但这是传统方式,还是存在硬编码问题,user.selectList
就是硬编码,接下来我们来优化这个问题。
我们平时是怎样使用Mybatis的?首先定义一个接口,然后Mapper.xml和接口达成映射关系;我们来看getMapper
方法接收的参数是Class对象,如何根据Class对象寻找mapper文件,并根据方法找到对应的SQL语句呢?
所有的SQL语句都保存在Configuration的mappedStatementMap对象中,这是一个HashMap。
所以只有要key就能找到SQL语句及相关属性,key是构成是
namespcae.标签id
因此我们强制规定:namespace是dao接口的全路径名;标签上的id则必须是方法名称
java
package com.xk857.session;
public class DefaultSqlSession implements SqlSession {
@Override
public <T> T getMapper(Class<?> mapperClass) {
// 使用JDK动态代理生成基于接口的代理对象
Object proxy = Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[]{mapperClass}, (o, method, objects) -> {
// 1.获取方法名称
String methodName = method.getName();
// 2.获取所在类的全路径 com.xk857.dao.IUserDao
String className = method.getDeclaringClass().getName();
// 3.根据Key获取MappedStatement对象
String statementId = className + "." + methodName;
// 4.获取MappedStatement对象,判断当前是进行增删改查哪一项操作
MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementId);
String sqlCommandType = mappedStatement.getSqlCommandType();
switch (sqlCommandType) {
case "select":
// 5.获取返回值类型
Class<?> returnType = method.getReturnType();
boolean isCollection = Collection.class.isAssignableFrom(returnType);
// 6.如果是集合类,及返回值是一个数组则查询多个
if (isCollection) {
// 6.1 如果参数不为空,则传递参数
if (objects != null) {
return selectList(statementId, objects[0]);
}
// 6.2 否则传递null
return selectList(statementId, null);
}
return selectOne(statementId, objects[0]);
case "update":
// 执行更新方法调用
break;
case "delete":
// 执行delete方法调用
break;
case "insert":
// 执行insert方法调用
break;
}
return null;
});
return (T) proxy;
}
}
更改后的mapper文件
xml
<mapper namespace="com.xk857.dao.IUserDao"> <!--namespace="user"-->
<select id="selectList" resultType="com.xk857.domain.User">
select * from user
</select>
</mapper>
创建一个Dao接口
java
public interface IUserDao {
List<User> selectList();
}
测试
java
public class MainTest {
@Test
public void test2() throws Exception {
// 1.读取配置文件信息
InputStream is = Resources.getResourceAsSteam("sqlMapConfig.xml");
// 2.解析配置文件封装成JavaBean对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
// 3.配置执行器及默认实现DefaultSqlSessionFactory
SqlSession sqlSession = sqlSessionFactory.openSession();
// 4.通过接口调用完成查询
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
List<User> userList = userDao.selectList();
for (User user : userList) {
System.out.println(user);
}
}
}