This is the 25th day of my participation in the August Genwen Challenge.More challenges in August
SpringBoot Mybatis parameter as field/table name considerations
Today I met a very interesting thing, a friend feedback, the same SQL, why directly through mysql terminal execution results are inconsistent with mybatis execution results, I feel a bit spookily; Then I look at it and see that this is a typical problem, the difference between #{} and ${}
Let’s take a look at this problem and relearn the difference between the two
I. Environment configuration
We use SpringBoot + Mybatis + MySql to build the example demo
- Springboot: 2.2.0. RELEASE
- Mysql: 5.7.22
1. Project configuration
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
Copy the code
The core relies on mybatis-spring-boot-starter. For version selection, go to the MVN repository and find the latest one
Another unavailable db configuration information is appliaction.yml
spring:
datasource:
url: JDBC: mysql: / / 127.0.0.1:3306 / story? useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password:
Copy the code
2. Database tables
Database for testing
CREATE TABLE `money` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL DEFAULT ' ' COMMENT 'Username',
`money` int(26) NOT NULL DEFAULT '0' COMMENT 'money',
`is_deleted` tinyint(1) NOT NULL DEFAULT '0',
`create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Creation time',
`update_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'Update Time'.PRIMARY KEY (`id`),
KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=551 DEFAULT CHARSET=utf8mb4;
Copy the code
II. Scene replaying
A simple demo to demonstrate the use of posture, according to the pass parameter, to specify the sort of field;
List<MoneyPo> orderBy(@Param("order") String order);
Copy the code
The corresponding XML is as follows
<select id="orderBy" resultMap="BaseResultMap">
select * from `money` order by #{order} asc
</select>
Copy the code
The above implementation may be inconsistent with our expectations, as follows
1. Troubleshooting
In the example above, we were hoping to sort by pass-through parameters, but the result will be sorted by ID
To solve the above problem, it is also easy to change # to $
<select id="orderBy" resultMap="BaseResultMap">
select * from `money` order by ${order} asc
</select>
Copy the code
Again, the test is as expected
2. Cause analysis
The key reason for the above question lies in the essential difference between $and #. If you know a little bit, you will know that $is a replacement and # is a placeholder
For example, the above two are converted into SQL, which corresponds to the following
# {}
:select * from money order by 'money' asc
- Notice that money is passed in as a string
The ${}
:select * from money order by money asc
- Note money as the column name
The first SQL statement above, which is very interesting, does not throw the error, the execution of the normal (note that this is dependent on the database version, not all versions of the normal)
3. #{} vs. ${}
# {} | The ${} |
---|---|
Parameter placeholder, equivalent to? | Replace directly to part of SQL |
Dynamic parse -> precompile -> Execute | Dynamic parsing -> Compile -> Execute |
Variable substitution is in the DBMS | Variable substitution is outside the DBMS |
After variable substitution, the corresponding variable is automatically quoted as “”. | ${} will not be quoted as ” |
SQL injection prevention | SQL injection cannot be protected |
Matters needing attention:
select * from money where name = #{name}
select * from money where name = ${name}
Copy the code
As in the above two SQL, there will be a significant to go when the specific parameter is passed
- # {name} : ginseng
A gray
The corresponding SQL is as followsSelect * from money where name = '1'
- The ${name} : ginseng
A gray
The corresponding SQL is as followsSelect * from money where name = 1
- Note that in the SQL above, the name parameter is not quoted, so it is just bad SQL
- So the passing parameter should be
'A Grey'
, you need to add single quotation marks manually
Use posture:
- Use #{} where you can use #{}, use ${} less or less
- ${}; ${};
- ${} is required when ordering by.
- Pay attention to when to add or not add single quotes, i.e. {}, when to add or not add single quotes, i.e. {} and ‘${}’
III. Can’t miss the source code and related knowledge points
0. Project
- Project: github.com/liuyueyi/sp…
- Source: github.com/liuyueyi/sp…
1. Wechat official account: Yash Blog
As far as the letter is not as good, the above content is purely one’s opinion, due to the limited personal ability, it is inevitable that there are omissions and mistakes, if you find bugs or have better suggestions, welcome criticism and correction, don’t hesitate to appreciate
Below a gray personal blog, record all the study and work of the blog, welcome everyone to go to stroll
- A grey Blog Personal Blog blog.hhui.top
- A Grey Blog-Spring feature Blog Spring.hhui.top