MyBatis参数获取和传递

您所在的位置:网站首页 mybatis参数传递map MyBatis参数获取和传递

MyBatis参数获取和传递

2024-06-26 12:46| 来源: 网络整理| 查看: 265

1、参数获取方式

MyBatis可以通过以下两种方式获取参数值:

#{变量名} 本质是占位符赋值

${变量名}

本质是字符串拼接,如果拼接的是字符串类型或日期类型,则需要手动添加单引号

2、参数获取的几种情况: 2.1 mapper接口方法的参数为单个字面量类型

可以通过${}和#{}以任意名称获取变量值,需注意${}的单引号问题

如下:

public interface UserMapper { User selectUserByUserName(String username); } select * from t_user where username = #{username} 2.2 mapper接口方法的参数为多个时

mybatis会将多个参数封装到map集合中,并以两种方式存储:

方式一:以arg0,arg1,arg2,…为键,以参数为值方式二:以param1,param2,param3,…为键,以参数为值

可以通过#{}和${}两种方式以键的方式获取值即可,需注意${}的单引号问题

如下:

List selectUserByUserNameAndAge(String username, Integer age, String sex); select * from t_user where username = #{arg0} and age = #{arg1} and sex = #{arg2} 2.3 mapper接口方法有多个参数时,手动封装map参数

可以通过#{}和${}两种方式以键的方式获取值即可,需注意${}的单引号问题

如下:

@Test public void testQueryByMapParam(){ SqlSession sqlSession = SqlSessionUtil.getSqlSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); Map map = new HashMap(); map.put("username", "李斯"); map.put("age", 23); map.put("sex", "女"); List admin = userMapper.selectUserByMap(map); admin.stream().forEach(System.out::println); } List selectUserByMap(Map map); select * from t_user where username = #{username} and age = #{age} and sex = #{sex} 2.4 mapper接口方法的参数为实体类类型的参数

可以通过${}和#{}以任意名称获取变量值,需注意${}的单引号问题

如下:

@Test public void testInsertUser(){ SqlSession sqlSession = SqlSessionUtil.getSqlSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = new User(); user.setUsername("中华"); user.setPassword("123456"); user.setAge(32); user.setSex("男"); int i = userMapper.insertUser(user); System.out.println(i); } int insertUser(User user); insert into t_user values(null, #{username}, #{password}, #{age}, #{sex}) 2.5 使用@Param注解命名参数

mybatis会将多个参数封装到map集合中,并以两种方式存储:

方式一:以@Param注解的值为键,以参数为值方式二:以param1,param2,param3,…为键,以参数为值 因此可以通过${}和#{}以任意名称获取变量值,需注意${}的单引号问题 @Test public void testQueryByParam(){ SqlSession sqlSession = SqlSessionUtil.getSqlSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List admin = userMapper.selectUserByParam("李斯", 23, "女"); admin.stream().forEach(System.out::println); } List selectUserByParam(@Param("username") String username, @Param("age") Integer age, @Param("sex") String sex); select * from t_user where username = #{username} and age = #{age} and sex = #{sex} 3、MyBatis参数解析原理: 3.1 参数封装

主要分析MyBatis对接口参数的处理,如参数的封装、参数值的获取原理。

org.apache.ibatis.reflection.ParamNameResolver#ParamNameResolver org.apache.ibatis.reflection.ParamNameResolver#getNamedParams ParamNameResolver构造 构造方法中处理方法参数的映射,建立参数的索引和参数名的映射关系。 // 参数名称处理 public ParamNameResolver(Configuration config, Method method) { // 是否使用真实的参数名,默认为true this.useActualParamName = config.isUseActualParamName(); // 获取方法的参数类型数组 final Class[] paramTypes = method.getParameterTypes(); // 获取方法参数注解 final Annotation[][] paramAnnotations = method.getParameterAnnotations(); // 存储参数信息临时对象 final SortedMap map = new TreeMap(); int paramCount = paramAnnotations.length; // get names from @Param annotations for (int paramIndex = 0; paramIndex {{0, "M"}, {1, "N"}} aMethod(int a, int b) -> {{0, "0"}, {1, "1"}} aMethod(int a, RowBounds rb, int b) -> {{0, "0"}, {2, "1"}} */ if (isSpecialParameter(paramTypes[paramIndex])) { // 跳过特殊参数 ,如RowBounds 或 ResultHandler continue; } String name = null; for (Annotation annotation : paramAnnotations[paramIndex]) { if (annotation instanceof Param) { // 当前参数存在@Param注解时,参数名设置为注解的value值 hasParamAnnotation = true; name = ((Param) annotation).value(); break; } } if (name == null) { // 如果存在@Param注解,且没有指定参数名 if (useActualParamName) { // 取出方法参数名,如果时单一普通参数,则返回arg0 name = getActualParamName(method, paramIndex); } if (name == null) { // use the parameter index as the name ("0", "1", ...) // gcode issue #71 // 此时,将索引作为参数名 name = String.valueOf(map.size()); } } map.put(paramIndex, name); } names = Collections.unmodifiableSortedMap(map); } getNamedParams

建立参数名和参数值的映射关系,并返回参数值

/** *

* A single non-special parameter is returned without a name. Multiple parameters are named using the naming rule. In * addition to the default names, this method also adds the generic names (param1, param2, ...). *

* * @param args * the args * * @return the named params */ public Object getNamedParams(Object[] args) { final int paramCount = names.size(); if (args == null || paramCount == 0) { return null; } // 单一参数,且没有@Param注解时 if (!hasParamAnnotation && paramCount == 1) { Object value = args[names.firstKey()]; // 此处会对集合类型的参数进行包装处理 return wrapToMapIfCollection(value, useActualParamName ? names.get(names.firstKey()) : null); } else { // 建立参数名和值的映射,key:参数名 value:参数值 final Map param = new ParamMap(); int i = 0; for (Map.Entry entry : names.entrySet()) { // 1.添加命名参数和参数值的映射关系 param.put(entry.getValue(), args[entry.getKey()]); // add generic param names (param1, param2, ...) final String genericParamName = GENERIC_NAME_PREFIX + (i + 1); // ensure not to overwrite parameter named with @Param if (!names.containsValue(genericParamName)) { // 2.同时添加一个以param1,param2...为参数名 和 参数值的映射关系 param.put(genericParamName, args[entry.getKey()]); } i++; } return param; } }

wrapToMapIfCollection

/** * Wrap to a {@link ParamMap} if object is {@link Collection} or array. * * @param object * a parameter object * @param actualParamName * an actual parameter name (If specify a name, set an object to {@link ParamMap} with specified name) * * @return a {@link ParamMap} * * @since 3.5.5 */ public static Object wrapToMapIfCollection(Object object, String actualParamName) { // 如果是集合类型,则包装key为collection、list的map返回 if (object instanceof Collection) { ParamMap map = new ParamMap(); map.put("collection", object); if (object instanceof List) { map.put("list", object); } Optional.ofNullable(actualParamName).ifPresent(name -> map.put(name, object)); return map; } // 如果是数据组类型,则包装key为array的map返回 if (object != null && object.getClass().isArray()) { ParamMap map = new ParamMap(); map.put("array", object); Optional.ofNullable(actualParamName).ifPresent(name -> map.put(name, object)); return map; } // 如果不是集合类型或数组类型,则直接返回当前值 return object; } 3.2 参数调用

在org.apache.ibatis.binding.MapperMethod#execute方法中,通过convertArgsToSqlCommandParam获取参数值。

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); if (method.returnsOptional() && (result == null || !method.getReturnType().equals(result.getClass()))) { result = Optional.ofNullable(result); } } 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; }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3