Reputation: 137
I am fairly comfortable at using mybatis as an ORM tool. But i am not able to understand how parameter mapping works in mybatis.
say i have a mybatis mapper interface defined that has a method to fetch the user details.
And I have my Querybuilder
class defined, which has the select query
.
public interface UserMapper {
@SelectProvider(type = UserQueryBuilder.class, method = "getUserId")
Long getUserId(@Param("first") String firstName, @Param("last") String lastName, @Param("location") String location);
}
public class UserQueryBuilder(){
public String getUserId(String firstName, String lastName, String location) {
return new SQL() {{
SELECT("USER_TABLE.USER_ID");
FROM("USER_TABLE");
WHERE("USER_TABLE.FIRST_NAME" + " = #{first}");
WHERE("USER_TABLE.LAST_NAME" + " = #{last}");
WHERE("USER_TABLE.LOCATION" + " = #{location}");
}}.toString();
}
}
In the above mentioned QueryBuilder
, how the SQL query parameters were able to get mapped to "first" and "last" param values, defined in the 'userMapper' interface.
Upvotes: 0
Views: 1278
Reputation: 15861
The important thing is that UserQueryBuilder
does not get parameters defines in UserMapper
interface.
There are several components participating in query execution:
The mapper interface purpose is:
Mapper may define the query directly using annotation like @Select
, implicitly using the query defined in xml mapping or using the query builder via @SelectProvider
. The purpose of the builder is the same as of @Select
or xml mapping, namely to provide the query text
to mapper.
The actual implementation of the mapper is provided by the spring-mybatis
. That implementation is created dynamically based on the mapper class. The implementation works like this: when a method on the mapper is invoked it uses reflection to invoke appropriate methods (like selectOne
or selectList
based on the return type defined in the mapper method) on mybatis SqlSession
. In order to do that it needs query text and parameters. Query text is taken from builder/annotation/xml. Parameters are available as parameters to mapper method invocation. Then SqlSessoin
itself uses the query and parameters to execute the query using JDBC API.
Upvotes: 1
Reputation: 14217
MyBatis builds an dynamic proxy for mapper like Spring AOP Proxy, for MyBatis is using MapperProxyFactory to create the proxy instance MapperProxy with the proxy interface(UserMapper
).
So when invoke the getUserId
, MapperProxy
will catch the target method and parameters by:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
this will invoke the correspond MapperMethod to execute the sql with converted args to parameters by:
Object param = method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(command.getName(), param);
Since method.convertArgsToSqlCommandParam
actually will generated named parameters by @Param annotations.
and also need to replace placeholder(#{first}
) to ask and with correspond parameters, after this it will create BoundSql that own the raw sql and parameters, these will hand to jdbc dirver to execute like we use the jdbcTemplate directly.
Upvotes: 0