永发信息网

Mybatis之#和$的区别及其实现方式

答案:2  悬赏:50  手机版
解决时间 2021-04-05 02:54
Mybatis之#和$的区别及其实现方式
最佳答案
简单的说#{}和${}的区别:$是String 拼接插入的#则是占位符来做处理的,写法比如字符串类型,$需要自己添加''#就不需要添加,对于日志的差别就是$会打印在日志里面,#则显示?
大多数我们都是用#{} 因为可以防止sql注入,但是有时候${}还是很必要的,比如传入tableName,或者fieldName比如Order By id||time 就需要${}传入 #{}就无法搞定
typeHandler就无法对${}起作用
---只有明白工具是如何玩耍的,我们才能更好的使用工具
先介绍一个解析#{}和${}的类,这里${}就替换成对对应的值了,而#{}替换成?,并且在这里解析了这个属性的字段,包括判断了类型等等
public class GenericTokenParser {

private final String openToken;//这个比如#{ 或者${
private final String closeToken;//这里基本上就是}
private final TokenHandler handler;//根据#{key}或者${key}得到key的值

public GenericTokenParser(String openToken, String closeToken, TokenHandler handler) {
this.openToken = openToken;
this.closeToken = closeToken;
this.handler = handler;
}

public String parse(String text) {
StringBuilder builder = new StringBuilder();
if (text != null && text.length() > 0) {
char[] src = text.toCharArray();
int offset = 0;
int start = text.indexOf(openToken, offset);
while (start > -1) {
if (start > 0 && src[start - 1] == '\\') {
// the variable is escaped. remove the backslash.
builder.append(src, offset, start - 1).append(openToken);
offset = start + openToken.length();
} else {
int end = text.indexOf(closeToken, start);
if (end == -1) {
builder.append(src, offset, src.length - offset);
offset = src.length;
} else {
builder.append(src, offset, start - offset);
offset = start + openToken.length();
String content = new String(src, offset, end - offset);//拿到#{key}||${key}中的key
builder.append(handler.handleToken(content));//根据key获取对应的"value"
offset = end + closeToken.length();
}
}
start = text.indexOf(openToken, offset);
}
if (offset < src.length) {
builder.append(src, offset, src.length - offset);
}
}
return builder.toString();
}

}
其实最大的区别也就是下面的两个不同的实现类
1.${} 的解析实现类
判断一下参数的类型,然后就把value给搞定了,没有添加其他的东西,万能的Ognl
private static class BindingTokenParser implements TokenHandler {

private DynamicContext context;

public BindingTokenParser(DynamicContext context) {
this.context = context;
}

public String handleToken(String content) {
Object parameter = context.getBindings().get("_parameter");
if (parameter == null) {
context.getBindings().put("value", null);
} else if (SimpleTypeRegistry.isSimpleType(parameter.getClass())) {
context.getBindings().put("value", parameter);
}
Object value = OgnlCache.getValue(content, context.getBindings());
return (value == null ? "" : String.valueOf(value)); // issue #274 return "" instead of "null"
}
}
2.#{} 的解析实现类
这里就比较复杂了,判断了javaType,typeHandler,数字精度,通过hanlder,我们就可以处理一些列复杂的数据
private static class ParameterMappingTokenHandler extends BaseBuilder implements TokenHandler {

private List parameterMappings = new ArrayList();
private Class parameterType;
private MetaObject metaParameters;

public ParameterMappingTokenHandler(Configuration configuration, Class parameterType, Map additionalParameters) {
super(configuration);
this.parameterType = parameterType;
this.metaParameters = configuration.newMetaObject(additionalParameters);
}

public List getParameterMappings() {
return parameterMappings;
}

public String handleToken(String content) {
parameterMappings.add(buildParameterMapping(content));
return "?";
}

//这里就是把#{key}内容进行解析成一个带有一些列属性的类然后再由一些列typehanlder来setValue
private ParameterMapping buildParameterMapping(String content) {
Map propertiesMap = parseParameterMapping(content);
String property = propertiesMap.get("property");
Class propertyType;
if (metaParameters.hasGetter(property)) { // issue #448 get type from additional params
propertyType = metaParameters.getGetterType(property);
} else if (typeHandlerRegistry.hasTypeHandler(parameterType)) {
propertyType = parameterType;
} else if (JdbcType.CURSOR.name().equals(propertiesMap.get("jdbcType"))) {
propertyType = java.sql.ResultSet.class;
} else if (property != null) {
MetaClass metaClass = MetaClass.forClass(parameterType);
if (metaClass.hasGetter(property)) {
propertyType = metaClass.getGetterType(property);
} else {
propertyType = Object.class;
}
} else {
propertyType = Object.class;
}
ParameterMapping.Builder builder = new ParameterMapping.Builder(configuration, property, propertyType);
Class javaType = propertyType;
String typeHandlerAlias = null;
for (Map.Entry entry : propertiesMap.entrySet()) {
String name = entry.getKey();
String value = entry.getValue();
if ("javaType".equals(name)) {
javaType = resolveClass(value);
builder.javaType(javaType);
} else if ("jdbcType".equals(name)) {
builder.jdbcType(resolveJdbcType(value));
} else if ("mode".equals(name)) {
builder.mode(resolveParameterMode(value));
} else if ("numericScale".equals(name)) {
builder.numericScale(Integer.valueOf(value));
} else if ("resultMap".equals(name)) {
builder.resultMapId(value);
} else if ("typeHandler".equals(name)) {
typeHandlerAlias = value;
} else if ("jdbcTypeName".equals(name)) {
builder.jdbcTypeName(value);
} else if ("property".equals(name)) {
// Do Nothing
} else if ("expression".equals(name)) {
throw new BuilderException("Expression based parameters are not supported yet");
} else {
throw new BuilderException("An invalid property '" + name + "' was found in mapping #{" + content + "}. Valid properties are " + parameterProperties);
}
}
if (typeHandlerAlias != null) {
builder.typeHandler(resolveTypeHandler(javaType, typeHandlerAlias));
}
return builder.build();
}

private Map parseParameterMapping(String content) {
try {
return new ParameterExpression(content);
} catch (BuilderException ex) {
throw ex;
} catch (Exception ex) {
throw new BuilderException("Parsing error was found in mapping #{" + content + "}. Check syntax #{property|(expression), var1=value1, var2=value2, ...} ", ex);
}
}
}
全部回答
mybatis中拼接SQL参数用#{}
拼接可执行的函数的参数需要使用${}输出参数.
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
应县一中高二2016月考成绩报表
表示珍惜眼前人的句子,珍惜眼前的美好不要好
单选题国务院法制办公室关于《中华人民共和国
单选题WhichisRIGHT?A.MyEnglishbooksar
商贸(建材)公司运营,贷款问题
有懂陨石的老师谢谢帮我看看这是陨石吗
我空腹葡萄糖是9.72,正常吗
如何修改微信预留的手机号码,因为我现在已经
为什么我的微信添加不了QQ好友,我绑定了QQ的
21O÷42x6用简便方法这么做
立早乒乓培训地址在什么地方,我要处理点事!
柳惠珠和朴知浩结婚了么?
如何用一条直线将一个梯形分成两个三角行??
CSOL怎么棺材跳 最好有视频加文字教程
求小说,主角是康熙和敏妃。。。。急急急!!
推荐资讯
弯弯的柳树像什么
智用于众人之所不能知,而能用于众人之所不能
柠檬片泡水有什么体质的人是不适宜喝的呢?
宝马740后驱 四驱 其实真没什么可纠结的
鲁迅写故乡的诗词,鲁迅写的诗句有哪些?
买二手房,原房东的维修基金发票丢失可以补办
非常好的朋友今天过生日我该怎么祝贺他我们不
描写“木”的词语有哪些?
看起来正常会议我们都要听这些胡言乱语了.(I
利润表中根据本期发生额分析填列的项目有(
单选题结核杆菌是胞内寄生菌,下列关于结核杆
我帮一个男的打过飞机,我算不算认识他?
正方形一边上任一点到这个正方形两条对角线的
阴历怎么看 ?