mybatis不作任何處理算法
取值方式:spring
#{參數名/任意名}sql
<!-- Employee getEmpById(Integer id); --> <select id="getEmpById" resultType="com.mxc.bean.Employee"> select * from employee where id=#{id} </select>
mybatis會將多個參數自動封裝爲一個mapapache
key:param1,…,paramN,也能夠是0,…,N-1(即參數索引,N是參數的個數)安全
value:參數值數據結構
取值方式:mybatis
#{上述的key}app
<!-- Employee getEmpByIdAndLastName(Integer id, String lastName); --> <select id="getEmpByIdAndLastName" resultType="com.mxc.bean.Employee"> select * from employee where id=#{param1} and last_name=#{param2} </select>
爲多個參數指定明確的key數據結構和算法
@Param
註解能夠爲參數指定一個明確的key,方便在sql中取參數值ide
取值方式:
#{@Param註解指定的key}
<!-- Employee getEmpByIdAndLastName(@Param("id")Integer id, @Param("lastName")String lastName); --> <select id="getEmpByIdAndLastName" resultType="com.mxc.bean.Employee"> select * from employee where id=#{id} and last_name=#{lastName} </select>
參數多時會封裝map,爲了取參數值方便,使用@Param來指定封裝時使用的key
若多個參數恰好是一個POJO中的屬性值,能夠直接傳入一個POJO
取值方式:
#{屬性名}
<!-- Employee getEmpByIdAndLastName(Employee emp); --> <select id="getEmpByIdAndLastName" resultType="com.mxc.bean.Employee"> select * from employee where id=#{id} and last_name=#{lastName} </select>
若多個參數不是某一個POJO的屬性,能夠封裝爲一個Map
取值方式:
#{Map的key}
<!-- Employee getEmpByIdAndLastName(Map<String, Object> map); map: Map<String, Object> map = new HashMap<>(); map.put("id", 1); map.put("lastName", "mxc"); --> <select id="getEmpByIdAndLastName" resultType="com.mxc.bean.Employee"> select * from employee where id=#{id} and last_name=#{lastName} </select>
小試牛刀
Employee getEmp(@Param("id")Integer id,String lastName);
// 取值:id=>#{id/param1},lastName=>#{param2}
Employee getEmp(Integer id,@Param("e")Employee emp);
// 取值:id=>#{param1},lastName => #{param2.lastName/e.lastName}
#{}與${}的異同
同:
能夠獲取map中的值或者pojo對象屬性的值
異:
#{}:是以預編譯的形式,將參數設置到sql語句中,能夠防止sql注入
${}:取出的值直接拼裝在sql語句中,會有安全問題
使用場景
大多狀況下,取參數的值使用#{}。在原生JDBC不支持佔位符的地方能夠使用${}。如按年份分表查詢:select * from ${year}_salary;
package com.spring.test.service.mybatis; import org.apache.ibatis.builder.ParameterExpression; /** * */ public class paramHandler { public static void main(String[] args) { paramsTokenHandler(); } /** * 方法名:List<User> queryList(String name, RowBounds rowBounds, int age, @Param("address") String addresss); * 參數內部映射: * MethodSignature.SortedMap<Integer, String> params * 參數列表的下標->參數名字(若是是@Param,則顯示的是註解的value,不然爲參數列表當前的除了RowBounds,ResultHandler之外的參數排名次數) * 0->0 * 2->1 * 3->address * * MethodSignature.convertArgsToSqlCommandParam(Object[] args) 返回:ParamMap * * ParamMap內部存儲以下: * 參數名字->參數下標 * 0->name的值 * 1->age的值 * address->addresss的值 * * param1->name的值 * param2->age的值 * param3->addresss的值 * */ public static void paramsToParamMap(){ } /** * 例子:#{checkedTime,jdbcType=BIGINT,typeHandler=com.meituan.payment.fundsgateway.core.model.handler.DateForLongTypeHandler} */ public static void paramsTokenHandler(){ String token="checkedTime,jdbcType=BIGINT,typeHandler=com.meituan.payment.fundsgateway.core.model.handler.DateForLongTypeHandler"; ParameterExpression parameterExpression=new ParameterExpression(token); String name=parameterExpression.get("property"); System.out.println(name); String jdbcType=parameterExpression.get("jdbcType"); System.out.println(jdbcType); String typeHandler=parameterExpression.get("typeHandler"); System.out.println(typeHandler); } }
=>經過sql解析的ParameterMapping循環遍歷,從參數列表中獲取指定的值,設置至sql語句中的?佔位符。
=>將方法的參數列表包裝成MetaObject,提供統一獲取參數值的方法
=>根據sql語句佔位符#{propertyName}中的propertyName去MetaObject中獲取sql語句中的?的值。
=>將sql語句中#{}替換成?,並解析出List<ParameterMapping>