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();
fullContext.putAll(variablesContext);
fullContext.putAll(newVariablesContext);
} else