在 MyBatis 中的区别
语法功能
#{}
:它是 MyBatis 中的占位符,用于预编译 SQL 语句。在处理#{}
时,MyBatis 会把 SQL 中的#{}
替换为?
,然后使用PreparedStatement
来设置参数,从而避免 SQL 注入问题。${}
:它是字符串替换,MyBatis 会直接将${}
替换为参数值。
示例代码
假设存在一个简单的 User 实体类,以及对应的查询操作。
public class User {
private int id;
private String name;
// 省略 getter 和 setter 方法
}
Mapper 接口如下:
import org.apache.ibatis.annotations.Param;
public interface UserMapper {
User selectUserByIdUsingHash(@Param("id") int id);
User selectUserByIdUsingDollar(@Param("id") int id);
}
Mapper XML 文件:
<mapper namespace="com.example.UserMapper">
<select id="selectUserByIdUsingHash" resultType="com.example.User">
SELECT * FROM users WHERE id = #{id}
</select>
<select id="selectUserByIdUsingDollar" resultType="com.example.User">
SELECT * FROM users WHERE id = ${id}
</select>
</mapper>
SQL 处理过程
#{}
:上述SELECT * FROM users WHERE id = #{id}
会被预编译成SELECT * FROM users WHERE id = ?
,之后使用PreparedStatement
的setInt
方法给?
赋值。${}
:SELECT * FROM users WHERE id = ${id}
会直接把${id}
替换成传入的参数值。比如传入id = 1
,最终 SQL 就是SELECT * FROM users WHERE id = 1
。
安全性
#{}
:由于使用预编译和参数化查询,能有效防止 SQL 注入攻击。${}
:直接进行字符串替换,若参数值来自用户输入且未经过严格过滤,就可能存在 SQL 注入风险。
使用场景
#{}
:适合大多数情况下的参数传递,尤其是涉及用户输入的情况。${}
:通常用于动态表名、动态列名等场景,因为预编译语句不支持表名和列名的参数化。
2. 在 Spring 框架配置文件中的区别
语法功能
#{}
:在 Spring 的 SpEL(Spring Expression Language)表达式里使用,能在运行时计算表达式的值。${}
:用于读取配置文件中的属性值。
示例代码
假设存在一个 application.properties
配置文件:
database.url=jdbc:mysql://localhost:3306/mydb
database.username=root
database.password=123456
Spring 配置类:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
@Configuration
@PropertySource("classpath:application.properties")
public class AppConfig {
@Value("${database.url}")
private String url;
@Value("${database.username}")
private String username;
@Value("${database.password}")
private String password;
@Bean
public DataSource dataSource() {
// 这里简单示例,实际使用会使用具体的数据源实现
return new DataSource() {
@Override
public Connection getConnection() throws SQLException {
// 省略具体实现
return null;
}
// 省略其他方法
};
}
}
使用场景
#{}
:可以进行复杂的表达式计算,例如方法调用、属性访问等。${}
:主要用于从配置文件中读取属性值,实现配置的外部化和可维护性。