入参#{}的解析
那么如果是#{}该怎么处理呢?
<select id="get" resultType="com.entity.User">
select * from user where id = #{id}
</select>
List<User> get(Integer id);
由上文得知,由于没有${},那么SqlSource就会变成RawSqlSource。在创建RawSqlSource的时候,在构造方法中就会对#{}解析。
RawSqlSource的构造方法。
public RawSqlSource(Configuration configuration, SqlNode rootSqlNode, Class<?> parameterType) {
this(configuration, getSql(configuration, rootSqlNode), parameterType);
}
public RawSqlSource(Configuration configuration, String sql, Class<?> parameterType) {
SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
Class<?> clazz = parameterType == null ? Object.class : parameterType;
sqlSource = sqlSourceParser.parse(sql, clazz, new HashMap<>());
}
SqlSourceBuilder.parse
public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) {
ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType, additionalParameters);
GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);
String sql = parser.parse(originalSql);
return new StaticSqlSource(configuration, sql, handler.getParameterMappings());
}
这里用的hander是ParameterMappingTokenHandler,它的作用是将#{XXX}替换成 ?
ParameterMappingTokenHandler.handleToken
public String handleToken(String content) {
parameterMappings.add(buildParameterMapping(content));
return "?";
}
这时sql就变成了select * from user where id = ?,到这里还只是解析配置文件。在具体执行方法时也要调用getBoundSql方法将参数进行赋值
//RawSqlSource.getBoundSql
public BoundSql getBoundSql(Object parameterObject) {
return sqlSource.getBoundSql(parameterObject);
}
StaticSqlSource.getBoundSql,最后调用BoundSql的构造方法,将sql语句,入参等传入
public BoundSql getBoundSql(Object parameterObject) {
return new BoundSql(configuration, sql, parameterMappings, parameterObject);
}
之后就要创建数据库连接,进行查询了。回到这个方法SimpleExecutor.prepareStatement。回顾一下,这是创建StatementHandler后做的一些连接数据库的准备操作。
private Statement prepareStatement(StatementH