1. mapper.xml配置文件中,只要调用到了insert方法,不管name为不为空都会执行到preparedStatement.update()方法,如果name为null,此时就会报Query is Empty的异常
1 <insert id="insert"> 2 <if test="name != null"> 3 INSERT INTO user(name) VALUES( 4 #{name} 5 ) 6 </if> 7 </insert>
2. mapper.xml中过滤条件中可以调用方法,但不能使用< > <=等特殊符号(加CDATA也不行), and或者or不能大写,这与XML要求有关
如下:
1 <select id="selectById" resultMap="BaseResultMap"> 2 SELECT * 3 from account 4 WHERE 5 <if test="list != null and list.size() != 0"> 6 <foreach collection="list" item="model" open="id in (" close=")" separator=","> 7 #{model} 8 </foreach> 9 </if> 10 <if test="id != null"> 11 and id = #{id} 12 </if> 13 limit 0, 1 14 </select>
3. 对于SQL语句的执行mybatis使用的是StatementHandler,在newXxxStatementHandler()时会调用BaseStatementHandler的构造方法,详见随笔(http://www.cnblogs.com/stefanking/p/5102837.html)
PreparedStatementHandler执行过程:获取最终需要执行的SQL语句 --> prepare(sql) --> PreparedStatementHandler.update(Statement) --> PreparedStatement.execute() --> ...
对第一步的解释:在BaseStatementHandler的构造函数中获取最终要执行的SQL语句
代码:
1 protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { 2 this.configuration = mappedStatement.getConfiguration(); 3 this.executor = executor; 4 this.mappedStatement = mappedStatement; 5 this.rowBounds = rowBounds; 6 7 this.typeHandlerRegistry = configuration.getTypeHandlerRegistry(); 8 this.objectFactory = configuration.getObjectFactory(); 9 10 if (boundSql == null) { // issue #435, get the key before calculating the statement 11 generateKeys(parameterObject); 12 boundSql = mappedStatement.getBoundSql(parameterObject); 13 } 14 15 this.boundSql = boundSql; 16 17 this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql); 18 this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql); 19 } 20 21 /** 22 * MappedStatement 23 */ 24 public BoundSql getBoundSql(Object parameterObject) { 25 BoundSql boundSql = sqlSource.getBoundSql(parameterObject); 26 List<ParameterMapping> parameterMappings = boundSql.getParameterMappings(); 27 if (parameterMappings == null || parameterMappings.size() <= 0) { 28 boundSql = new BoundSql(configuration, boundSql.getSql(), parameterMap.getParameterMappings(), parameterObject); 29 } 30 31 // check for nested result maps in parameter mappings (issue #30) 32 for (ParameterMapping pm : boundSql.getParameterMappings()) { 33 String rmId = pm.getResultMapId(); 34 if (rmId != null) { 35 ResultMap rm = configuration.getResultMap(rmId); 36 if (rm != null) { 37 hasNestedResultMaps |= rm.hasNestedResultMaps(); 38 } 39 } 40 } 41 42 return boundSql; 43 } 44 45 /** 46 * DynamicSqlSource implements SqlSource 47 */ 48 public BoundSql getBoundSql(Object parameterObject) { 49 DynamicContext context = new DynamicContext(configuration, parameterObject); 50 rootSqlNode.apply(context); //此处处理if where trim等内部标签过滤条件,得到最终需要编译的SQL语句,参数未替换, 如: select * from user where userName = #{param.userName} and age = #{param.age} 51 SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration); 52 Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass(); 53 SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings()); //此处替换掉占位符,得到最终参数,和最终预编译的SQL语句: 如:select * from user where userName = ? and age = ? 54 BoundSql boundSql = sqlSource.getBoundSql(parameterObject); 55 for (Map.Entry<String, Object> entry : context.getBindings().entrySet()) { //占位符对应位置的参数值 56 boundSql.setAdditionalParameter(entry.getKey(), entry.getValue()); 57 } 58 return boundSql; 59 }