>  기사  >  Java  >  Java에서 ${}와 #{}의 차이점은 무엇입니까?

Java에서 ${}와 #{}의 차이점은 무엇입니까?

王林
王林앞으로
2023-05-01 13:52:063870검색

    Preface

    ${} 및 #{}는 모두 MyBatis에서 매개변수를 대체하는 데 사용됩니다. 이는 MyBatis가 최종 생성한 SQL에 사용자가 전달한 매개변수를 대체할 수 있습니다. 그 차이는 매우 큽니다. 다음에 살펴보겠습니다. ${} 和 #{} 都是 MyBatis 中用来替换参数的,它们都可以将用户传递过来的参数,替换到 MyBatis 最终生成的 SQL 中,但它们区别却是很大的,接下来我们一起来看。

    1.功能不同

    ${} 是将参数直接替换到 SQL 中比如以下代码:

    <select id="getUserById" resultType="com.example.demo.model.UserInfo">
        select * from userinfo where id=${id}
    </select>

    最终生成的执行 SQL 如下: 

    Java에서 ${}와 #{}의 차이점은 무엇입니까?

     从上图可以看出,之前的参数 ${id} 被直接替换成具体的参数值 1 了。 而 #{} 则是使用占位符的方式,用预处理的方式来执行业务,我们将上面的案例改造为 #{} 的形式,实现代码如下:

    <select id="getUserById" resultType="com.example.demo.model.UserInfo">
        select * from userinfo where id=#{id}
    </select>

    最终生成的 SQL 如下: 

    Java에서 ${}와 #{}의 차이점은 무엇입니까?

    1.1 ${} 的问题

    当参数为数值类型时(在不考虑安全问题的前提下),${} 和 #{} 的执行效果都是一样的,然而当参数的类型为字符时,再使用 ${} 就有问题了,如下代码所示:

    <select id="getUserByName" resultType="com.example.demo.model.UserInfo">
        select * from userinfo where name=${name}
    </select>

    以上程序执行时,生成的 SQL 语句如下: 

    Java에서 ${}와 #{}의 차이점은 무엇입니까?

     这样就会导致程序报错,因为传递的参数是字符类型的,而在 SQL 的语法中,如果是字符类型需要给值添加单引号,否则就会报错,而 ${} 是直接替换,不会自动添加单引号,所以执行就报错了。 而使用 #{} 采用的是占位符预执行的,所以不存在任何问题,它的实现代码如下:

    <select id="getUserByName" resultType="com.example.demo.model.UserInfo">
        select * from userinfo where name=#{name}
    </select>

    以上程序最终生成的执行 SQL 如下: 

    Java에서 ${}와 #{}의 차이점은 무엇입니까?

    2.使用场景不同

    虽然使用 #{} 的方式可以处理任意类型的参数,然而当传递的参数是一个 SQL 命令或 SQL 关键字时 #{} 就会出问题了。比如,当我们要根据价格从高到低(倒序)、或从低到高(正序)查询时

    此时我们要传递的排序的关键字,desc 倒序(价格从高到低)或者是 asc 正序(价格从低到高),此时我们使用 ${} 的实现代码瑞安:

    <select id="getAll" resultType="com.example.demo.model.Goods">
      select * from goods order by price ${sort}
    </select>

    以上代码生成的执行 SQL 和运行结果如下: 

    Java에서 ${}와 #{}의 차이점은 무엇입니까?

     但是,如果将代码中的 ${} 改为 #{},那么程序执行就会报错,#{} 的实现代码如下:

    <select id="getAll" resultType="com.example.demo.model.Goods">
      select * from goods order by price #{sort}
    </select>

    以上代码生成的执行 SQL 和运行结果如下: 

    Java에서 ${}와 #{}의 차이점은 무엇입니까?

     从上述的执行结果我们可以看出:当传递的是普通参数时,需要使用 #{} 的方式,而当传递的是 SQL 命令或 SQL 关键字时,需要使用 ${} 来对 SQL 中的参数进行直接替换并执行。

    3.安全性不同

    ${} 和 #{} 最主要的区别体现在安全方面,当使用 ${} 会出现安全问题,也就是 SQL 注入的问题,而使用 #{} 因为是预处理的,所以不会存在安全问题,我们通过下面的登录功能来观察一下二者的区别。

    3.1 使用 ${} 实现用户登录

    UserMapper.xml 中的实现代码如下:

    <select id="login" resultType="com.example.demo.model.UserInfo">
      select * from userinfo where name=&#39;${name}&#39; and password=&#39;${password}&#39;
    </select>

    单元测试代码如下:

    @Test
    void login() {
        UserInfo userInfo = userMapper.login("java", "java");
        System.out.println(userInfo);
    }

    以上代码生成的执行 SQL 和运行结果如下: 

    Java에서 ${}와 #{}의 차이점은 무엇입니까?

     从结果可以看出,当我们传入了正确的用户名和密码时,能成功的查询到数据。但是,在我们使用 ${}

    1. 다양한 함수

    ${}는 매개변수를 SQL

    로 직접 바꾸는 것입니다.

    예를 들어 다음 코드는 Java에서 ${}와 #{}의 차이점은 무엇입니까?

    @Test
    void login() {
        UserInfo userInfo = userMapper.login("java", "&#39; or 1=&#39;1");
        System.out.println(userInfo);
    }
    🎜🎜최종 생성된 실행 SQL은 다음과 같습니다. 🎜🎜🎜Java에서 ${}와 #{}의 차이점은 무엇입니까🎜🎜 가능한 대로 위 그림을 보면 이전 매개변수 ${id}가 특정 매개변수 값 1로 직접 대체되었습니다. 그리고 🎜#{}는 자리 표시자와 전처리를 사용하여 비즈니스를 실행합니다🎜. 위의 경우를 #{} 형식으로 변환했습니다. 🎜구현 코드는 다음과 같습니다. 🎜🎜
    <select id="login" resultType="com.example.demo.model.UserInfo">
      select * from userinfo where name=#{name} and password=#{password}
    </select>
    🎜🎜최종적으로 생성된 SQL은 다음과 같습니다. 🎜 🎜🎜Java에서 ${}와 #{}의 차이점은 무엇입니까? 🎜

    1.1 ${}

    문제🎜매개변수가 숫자 유형인 경우(보안 문제를 고려하지 않음) ${} 및 #{} 실행 효과는 동일합니다. 그러나 매개변수 유형이 문자인 경우 ${}를 사용하면 문제가 발생합니다. 🎜다음 코드와 같이 🎜🎜
    @Test
    void login() {
        UserInfo userInfo = userMapper.login("java", "&#39; or 1=&#39;1");
        System.out.println(userInfo);
    }
    🎜🎜위 프로그램을 실행하면 다음과 같은 SQL 문이 생성됩니다. 🎜🎜 🎜 🎜🎜 전달된 매개변수가 문자 유형이기 때문에 프로그램에서 오류를 보고하게 되며, SQL 구문에서 문자 유형인 경우 값에 작은따옴표를 추가해야 합니다. 그렇지 않으면 오류가 보고됩니다. 및 ${} 직접 대체이며 작은따옴표가 자동으로 추가되지 않으므로 실행 시 오류가 보고됩니다. #{}를 사용하면 자리 표시자 사전 실행을 사용하므로 문제가 없습니다. 구현 코드는 다음과 같습니다. 🎜rrreee🎜🎜위 프로그램에서 생성된 최종 실행 SQL은 다음과 같습니다. 🎜🎜🎜Java에서 ${}와 #{}의 차이점은 무엇입니까🎜🎜2. 사용 시나리오는 다음과 같습니다. other🎜🎜#{}를 사용하면 모든 유형의 매개변수를 처리할 수 있지만 #{}는 전달된 매개변수가 SQL 명령 또는 SQL 키워드인 경우 문제를 발생시킵니다. 예를 들어 높은 가격에서 낮은 가격으로(역순), 낮은 가격에서 높은 가격(정방향)으로 쿼리하려는 경우 이때 전달하려는 정렬 키워드는 desc 역순(가격이 높은 것에서 낮은 값으로)입니다. ) 또는 asc 양수 순서(가격이 낮은 것부터 높은 것까지), 이때 ${} Ryan의 구현 코드를 사용합니다. 🎜rrreee🎜🎜위 코드에서 생성된 실행 SQL 및 실행 결과는 다음과 같습니다. 🎜🎜🎜${}와 #{}의 차이점은 무엇인가요? in java🎜🎜🎜 그러나 코드의 ${}를 #{}으로 변경하면 프로그램 실행에서 오류가 보고됩니다. #{}의 구현 코드는 다음과 같습니다. 🎜🎜rrreee🎜🎜The 위 코드를 통해 생성된 실행 SQL 및 실행 결과는 다음과 같습니다. 🎜🎜🎜What java🎜🎜🎜 ${}와 #{}의 차이점은 무엇입니까?" />🎜🎜🎜 위에서 실행 결과를 보면 다음과 같습니다. 🎜일반 매개변수를 전달할 때는 #{}를 사용해야 하고, SQL 명령을 전달할 때는 SQL 키워드는 SQL에서 매개변수를 직접 교체하고 실행하려면 ${}를 사용해야 합니다. 🎜🎜3. 다른 보안 🎜🎜 ${}와 #{}의 주요 차이점은 보안 측면에 반영됩니다. ${}를 사용하면 보안 문제가 발생합니다. , SQL 인젝션의 문제이며 #{}를 사용하면 전처리가 되어 있기 때문에 보안상의 문제는 없을 것입니다. 아래 로그인 함수를 통해 둘의 차이점을 살펴보겠습니다. 🎜

    3.1 ${}를 사용하여 사용자 로그인 구현

    🎜🎜UserMapper.xml의 구현 코드는 다음과 같습니다. 🎜🎜rrreee🎜🎜단위 테스트 코드는 다음과 같습니다. 🎜🎜rrreee🎜🎜실행 위 코드로 생성된 SQL과 런타임 결과는 다음과 같습니다. 🎜🎜🎜What java 🎜🎜에서 ${}와 #{}의 차이점은 올바른 사용자 이름과 비밀번호를 전달하면 데이터를 성공적으로 쿼리할 수 있다는 것을 결과에서 볼 수 있습니다. 그러나 ${}를 사용할 때 올바른 비밀번호를 모를 경우 SQL 주입 문을 사용하여 사용자의 개인 정보를 얻을 수도 있습니다. SQL 주입 구현 코드는 다음과 같습니다. rrreee🎜🎜 위 코드에서 생성된 실행 SQL과 실행 결과는 다음과 같습니다. 🎜🎜🎜🎜🎜

     从上述结果可以看出,当使用 ${} 时,在不知道正确密码的情况下也能得到用户的私人数据,这就像一个小偷在没有你们家钥匙的情况下,也能轻松的打开你们家大门一样,这是何其恐怖的事情。那使用 #{} 有没有安全问题呢?接下来我们来测试一下。

    3.2 使用 #{} 实现用户登录

    首先将 UserMapper.xml 中的代码改成以下内容:

    <select id="login" resultType="com.example.demo.model.UserInfo">
      select * from userinfo where name=#{name} and password=#{password}
    </select>

    接着我们使用上面的 SQL 注入来测试登录功能:

    @Test
    void login() {
        UserInfo userInfo = userMapper.login("java", "&#39; or 1=&#39;1");
        System.out.println(userInfo);
    }

    最终生成的 SQL 和执行结果如下: 

    Java에서 ${}와 #{}의 차이점은 무엇입니까?

     从上述代码可以看出,使用 SQL 注入是无法攻破 #{} 的“大门”的,所以可以放心使用。

    위 내용은 Java에서 ${}와 #{}의 차이점은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

    성명:
    이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제