| public class SqlSessionUtils { |
| |
| public static SqlSession getSqlSession(){ |
| SqlSession sqlSession = null; |
| try { |
| InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); |
| SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); |
| sqlSession = sqlSessionFactory.openSession(true); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| } |
| return sqlSession; |
| } |
| |
| } |
| |
| # 测试方法 |
| @Test |
| public void testCheckLoginByParam(){ |
| SqlSession sqlSession = SqlSessionUtils.getSqlSession(); |
| ParameterMapper mapper = sqlSession.getMapper(ParameterMapper.class); |
| User user = mapper.checkLoginByParam("admin", "123456"); |
| System.out.println(user); |
| } |
- MyBatis获取参数值的两种方式:${}和#{}
| ${}的本质就是字符串拼接, |
| ${}使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单引号 |
| 但是 |
| 若mapper接口中的方法参数为单个的字面量类型 |
| 此时xml映射文件中,可以使用${}和#{}以任意的名称获取参数的值,注意${}需要手动加单引号 |
| |
| User getUser(String name); |
| |
| select * from user where username = #{name} |
| select * from user where username = #{aaa} |
| select * from user where username = '${name}' |
| select * from user where username = '${aaa}' |
| 若mapper接口中的方法参数为多个时 |
| 此时MyBatis会自动将这些参数放在一个map集合中,以arg0,arg1...为键,以参数为值;以 |
| param1,param2...为键,以参数为值;因此只需要通过${}和#{}访问map集合的键就可以获取相对应的 |
| 值,注意${}需要手动加单引号 |
| |
| User getUser(String name, String pwd); |
| |
| select * from user where username = #{arg0} and pwd = #{arg1} |
| select * from user where username = #{arg0} and pwd = #{param2} |
| select * from user where username = '${arg0}' and pwd = '${param2}' |
| |
| 若mapper接口中的方法需要的参数为多个时,此时可以手动创建map集合,将这些数据放在map中 |
| 只需要通过${}和 |
| |
| map.put("username", "goudan"); |
| map.put("pwd", "123"); |
| |
| User getUser(Map<String, Object> map); |
| |
| select * from user where username = |
| 若mapper接口中的方法参数为实体类对象时 |
| 此时可以使用${}和 |
| |
| int addUser(User user); |
| |
| insert into user values( |
| 可以通过@Param注解标识mapper接口中的方法参数 |
| 此时,会将这些参数放在map集合中,以@Param注解的value属性值为键,以参数为值;以 |
| param1,param2...为键,以参数为值;只需要通过${}和 |
| 注意${}需要手动加单引号 |
| |
| User getUser(@Param("name") String name, @Param("pwd") String pwd); |
| |
| select * from user where username = |
| # 打开MapperProxy.java |
| |
| @Override |
| public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { |
| try { |
| if (Object.class.equals(method.getDeclaringClass())) { |
| return method.invoke(this, args); |
| } else { |
| return cachedInvoker(method).invoke(proxy, method, args, sqlSession); |
| } |
| } catch (Throwable t) { |
| throw ExceptionUtil.unwrapThrowable(t); |
| } |
| } |
| |
| # 查看invoke方法 |
| private static class PlainMethodInvoker implements MapperMethodInvoker { |
| private final MapperMethod mapperMethod; |
| |
| public PlainMethodInvoker(MapperMethod mapperMethod) { |
| super(); |
| this.mapperMethod = mapperMethod; |
| } |
| |
| @Override |
| public Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable { |
| return mapperMethod.execute(sqlSession, args); |
| } |
| } |
| |
| # 进入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); |
| 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; |
| } |
| |
| # 查看convertArgsToSqlCommandParam方法 |
| public Object convertArgsToSqlCommandParam(Object[] args) { |
| return paramNameResolver.getNamedParams(args); |
| } |
| |
| # 再进入getNamedParams方法 |
| public Object getNamedParams(Object[] args) { |
| final int paramCount = names.size(); |
| if (args == null || paramCount == 0) { |
| return null; |
| } else if (!hasParamAnnotation && paramCount == 1) { |
| Object value = args[names.firstKey()]; |
| return wrapToMapIfCollection(value, useActualParamName ? names.get(0) : null); |
| } else { |
| final Map<String, Object> param = new ParamMap<>(); |
| int i = 0; |
| for (Map.Entry<Integer, String> entry : names.entrySet()) { |
| param.put(entry.getValue(), args[entry.getKey()]); |
| |
| final String genericParamName = GENERIC_NAME_PREFIX + (i + 1); |
| |
| if (!names.containsValue(genericParamName)) { |
| param.put(genericParamName, args[entry.getKey()]); |
| } |
| i++; |
| } |
| return param; |
| } |
| } |
| |
| # 查看name的来源 |
| private final SortedMap<Integer, String> names; |
| |
| private boolean hasParamAnnotation; |
| |
| public ParamNameResolver(Configuration config, Method method) { |
| this.useActualParamName = config.isUseActualParamName(); |
| final Class<?>[] paramTypes = method.getParameterTypes(); |
| final Annotation[][] paramAnnotations = method.getParameterAnnotations(); |
| final SortedMap<Integer, String> map = new TreeMap<>(); |
| int paramCount = paramAnnotations.length; |
| |
| for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) { |
| if (isSpecialParameter(paramTypes[paramIndex])) { |
| |
| continue; |
| } |
| String name = null; |
| for (Annotation annotation : paramAnnotations[paramIndex]) { |
| if (annotation instanceof Param) { |
| hasParamAnnotation = true; |
| name = ((Param) annotation).value(); |
| break; |
| } |
| } |
| if (name == null) { |
| |
| if (useActualParamName) { |
| name = getActualParamName(method, paramIndex); |
| } |
| if (name == null) { |
| |
| |
| name = String.valueOf(map.size()); |
| } |
| } |
| map.put(paramIndex, name); |
| } |
| names = Collections.unmodifiableSortedMap(map); |
| } |
| |
| # 回到getNamedParams方法 |
| public Object getNamedParams(Object[] args) { |
| final int paramCount = names.size(); |
| if (args == null || paramCount == 0) { |
| return null; |
| } else if (!hasParamAnnotation && paramCount == 1) { |
| Object value = args[names.firstKey()]; |
| return wrapToMapIfCollection(value, useActualParamName ? names.get(0) : null); |
| } else { |
| final Map<String, Object> param = new ParamMap<>(); |
| int i = 0; |
| for (Map.Entry<Integer, String> entry : names.entrySet()) { |
| param.put(entry.getValue(), args[entry.getKey()]); |
| |
| final String genericParamName = GENERIC_NAME_PREFIX + (i + 1); |
| |
| if (!names.containsValue(genericParamName)) { |
| param.put(genericParamName, args[entry.getKey()]); |
| } |
| i++; |
| } |
| return param; |
| } |
| } |
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决