mybatis学习记录(二)

mybatis中有两种操作数据库的方式:
第一种比较古老,在mapper配置文件中做好配置之后,直接通过sqlSession提供的接口来关联配置文件中的sql进行操作,具体操作如下:
mapper配置:

 <select id="queryAllUsers" resultType="User">
     select * from hwc_users
 </select>

操作方式一:

 List<User> userList = sqlSession.selectList("com.huwc.mapper.UserMapper.queryAllUsers");
 for (User user : userList) {
     System.out.println(user);
 }

这种调用方式无需声明对应的mapper接口类,而是直接通过namespace和相应配置的id进行sql的定位,然后通过sqlSession的selectList/selectOne方法进行数据库的操作。

另外一种较为流行的数据库操作方式为:根据mapper配置文件中的namespace定义相应的mapper接口类,再根据mapper配置文件中相应配置的id在接口类中定义相应的接口方法,相当于将mapper接口类与mapper配置文件进行了关联,然后通过sqlSession的getMapper方法获取对应mapper接口的代理类,继而通过代理类中的相应方法的调用来进行数据库的操作。

操作方式二:
添加对应mapper接口:

public interface UserMapper {
    public List<User> queryAllUsers();
}

调用方式:

  UserMapper mapper = sqlSession.getMapper(UserMapper.class);
  List<User> users = mapper.queryAllUsers();
  for (User user : users) {
      System.out.println(user);
  }

第二种调用的方法通过接口类的声明,是的数据库处理的调用更加的优雅,去除了程序中的硬编码,但实际上生成的mapper接口的代理类,最后依然是执行相应的方式一中的处理来实现数据库的操作,就是底层依然是调用sqlSession的selectList方法。
mapper接口代理类的生成方式为jdk的动态代理,众所周知,jdk的动态代理中相应的处理过程是封装在InvocationHandler接口的实现中,在mybatis中的InvocationHandler则是MapperProxy类,此类中的invoke方法如下:

  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
      if (Object.class.equals(method.getDeclaringClass())) {
        return method.invoke(this, args);
      } else if (isDefaultMethod(method)) {
        return invokeDefaultMethod(proxy, method, args);
      }
    } catch (Throwable t) {
      throw ExceptionUtil.unwrapThrowable(t);
    }
    final MapperMethod mapperMethod = cachedMapperMethod(method);
    return mapperMethod.execute(sqlSession, args);
  }

可以看到,invoke方法中是调用MapperMethod中的execute方法,传入的参数为sqlSession和对应的参数,MapperMethod的execute方法代码如下:

public Object execute(SqlSession sqlSession, Object[] args) {
   Object result;
   switch (command.getType()) {
     case INSERT: {
     Object param = method.convertArgsToSqlCommandParam(args);
       result = rowCountResult(sqlSession.insert(command.getName(), param));
       break;
     }
     case UPDATE: {
       Object param = method.convertArgsToSqlCommandParam(args);
       result = rowCountResult(sqlSession.update(command.getName(), param));
       break;
     }
     case DELETE: {
       Object param = method.convertArgsToSqlCommandParam(args);
       result = rowCountResult(sqlSession.delete(command.getName(), param));
       break;
     }
     case SELECT:
       if (method.returnsVoid() && method.hasResultHandler()) {
         executeWithResultHandler(sqlSession, args);
         result = null;
       } else if (method.returnsMany()) {
         result = executeForMany(sqlSession, args);
       } else if (method.returnsMap()) {
         result = executeForMap(sqlSession, args);
       } else if (method.returnsCursor()) {
         result = executeForCursor(sqlSession, args);
       } else {
         Object param = method.convertArgsToSqlCommandParam(args);
         result = sqlSession.selectOne(command.getName(), param);
       }
       break;
     case FLUSH:
       result = sqlSession.flushStatements();
       break;
     default:
       throw new BindingException("Unknown execution method for: " + command.getName());
   }
   if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
     throw new BindingException("Mapper method '" + command.getName() 
         + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
   }
   return result;
 }

此execute方法中可以清楚看到sqlSession对应方法的调用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值