저는 mybatis의 몇 가지 일반적인 기능을 사용하여 ORM 프레임워크인 Mybatis를 사용해 왔습니다. 오늘날 프로젝트 개발에서는 특정 테이블의 필드에 대한 각 사용자의 쿼리와 특정 필드의 표시 여부를 제한해야 하는 비즈니스가 있습니다. 예를 들어, 특정 테이블의 특정 필드는 사용자가 쿼리할 수 없습니다. 이 경우 테이블 이름과 필드 이름을 동적으로 전달하도록 SQL을 작성해야 합니다. 이제 같은 문제를 겪는 친구들에게 해결책을 요약해 보겠습니다.
동적 SQL은 mybatis의 강력한 기능 중 하나입니다. mybatis는 sql 문을 사전 컴파일하기 전에 sql을 동적으로 구문 분석하고 이를 BoundSql 개체로 구문 분석합니다. 먼저 mybatis에서 #{} 및 ${}의 사용법을 숙지해 보겠습니다.
동적 SQL 구문 분석 프로세스에서 #{} 및 ${}의 효과는 다릅니다.
#{ } 解析为一个 JDBC 预编译语句(prepared statement)的参数标记符。
예를 들어, 다음 SQL 문
select * from user where name = #{name};
은 다음과 같이 구문 분석됩니다.
select * from user where name = ?;
#{}가 매개변수 자리 표시자로 구문 분석되는 것을 볼 수 있습니까? .
${ } 仅仅为一个纯碎的 string 替换,在动态 SQL 解析阶段将会进行变量替换
예를 들어 다음 sql 문은 다음과 같습니다.
select * from user where name = ${name};
"sprite" 매개 변수를 전달하면 sql이 다음과 같이 구문 분석됩니다.
select * from user where name = "sprite";
미리보기를 볼 수 있습니다. 컴파일 전 SQL 문에는 더 이상 변수 이름이 포함되어 있지 않습니다.
정리하면 ${ }의 변수 교체 단계는 동적 SQL 구문 분석 단계이고, #{ }의 변수 교체는 DBMS입니다.
#{}과 ${}의 차이점은 다음과 같이 간략하게 요약할 수 있습니다.
#{}는 수신 매개변수를 문자열로 처리하고 이중 매개변수를 추가합니다.
${} 매개변수에 따옴표를 추가하면 따옴표
#{}를 추가하지 않고 SQL에 들어오는 매개변수를 직접 표시합니다. 이는 SQL 삽입을 크게 방지할 수 있습니다. ${ }SQL을 방지할 수 없습니다. 주입
${}은 사전 컴파일 전에 변수로 대체되어 SQL 주입 위험이 있습니다. 다음 sql
select * from ${tableName} where name = ${name}
전달된 매개변수 tableName이 user; delete user --인 경우 sql이 동적으로 구문 분석된 후 사전 컴파일 전 sql은 다음과 같습니다.
select * from user; delete user; -- where name = ?;
--다음 내용은 댓글로 적용되지 않습니다. 저와 친구들은 충격을 받았습니다. ! ! 원래 쿼리 문에 테이블 데이터를 삭제하는 SQL 문이 비밀리에 포함되어 있는 것을 보셨나요? ! ! 중요한 것을 세 번 말하면 위험이 얼마나 높은지 짐작할 수 있습니다.
${}는 일반적으로 데이터베이스의 테이블 이름, 필드 이름 등을 전송하는 데 사용됩니다.
#{}를 사용할 수 있는 경우에는 ${}를 사용하지 마세요.
요점을 파악하고 통과 위의 분석을 통해 테이블 이름과 필드 이름을 동적으로 호출하는 방법에 대한 몇 가지 아이디어를 이미 갖고 계실 것이라고 생각합니다. 예시는 다음과 같습니다.<select id="getUser" resultType="java.util.Map" parameterType="java.lang.String" statementType="STATEMENT"> select ${columns} from ${tableName} where COMPANY_REMARK = ${company} </select>
statementType:STATEMENT(非预编译),PREPARED(预编译)或CALLABLE中的任意一个,这就告诉 MyBatis 分别使用Statement,PreparedStatement或者CallableStatement。默认:PREPARED。这里显然不能使用预编译,要改成非预编译。
String name = "sprite"; name = "'" + name + "'";