本篇文章重点阐述一些动态sql的技术细节,#{name}和${name}的区别,将在本篇文章中揭晓。也许读者早已了解它们之间的区别,但是,作为技术内幕,我们不仅要了解它们的区别,还要介绍它们的工作原理。
我在这里分享一个,有很多干货,包含jvm,netty,spring,线程,spring cloud等详细讲解,也有详细的学习规划图,面试题整理等,我感觉在面试这块讲的非常清楚:获取面试资料只需:点击这里领取!!! 暗号:CSDN
1. #{name}和${name}的区别。
#{name}:表示这是一个参数(ParameterMapping)占位符,值来自于运行时传递给sql的参数,也就是XXXMapper.xml里的parameterType。其值通过PreparedStatement的setObject()等方法赋值。
动态sql中的标签绑定的值,也是使用#{name}来使用的。
#{name}用在sql文本中。
n a m e : 表 示 这 是 一 个 属 性 配 置 占 位 符 , 值 来 自 于 属 性 配 置 文 件 , 比 如 j d b c . p r o p e r t i e s , 其 值 通 过 类 似 r e p l a c e 方 法 进 行 静 态 替 换 。 比 如 {name}:表示这是一个属性配置占位符,值来自于属性配置文件,比如jdbc.properties,其值通过类似replace方法进行静态替换。比如 name:表示这是一个属性配置占位符,值来自于属性配置文件,比如jdbc.properties,其值通过类似replace方法进行静态替换。比如{driver},将被静态替换为com.mysql.jdbc.Driver。
${name}则可以用在xml的Attribute属性,还可以用在sql文本当中。
<select id="countAll" resultType="${driver}">
select count(1) from (
select
stud_id as studId
, name, email
, dob
, phone
from students #{
offset}, ${
driver}
) tmp
</select>
2. ${name}的工作原理
org.apache.ibatis.builder.xml.XMLStatementBuilder.parseStatementNode()部分源码。
public void parseStatementNode() {
//...
XMLIncludeTransformer includeParser = new XMLIncludeTransformer(configuration, builderAssistant);
includeParser.applyIncludes(context.getNode());
// ...
}
org.apache.ibatis.builder.xml.XMLIncludeTransformer.applyIncludes(Node, Properties)部分源码。
private void applyIncludes(Node source, final Properties variablesContext) {
if (source.getNodeName().equals("include")) {
// new full context for included SQL - contains inherited context and new variables from current include node
Properties fullContext;
String refid = getStringAttribute(source, "refid");
// replace variables in include refid value
refid = PropertyParser.parse(refid, variablesContext);
Node toInclude = findSqlFragment(refid);
Properties newVariablesContext = getVariablesContext(source, variablesContext);
if (!newVariablesContext.isEmpty()) {
// merge contexts
fullContext = new Properties();
fullCon