Article directory
- foreword
- 1. Getting to know MyBatis for the first time
- 2. The positioning of MyBatis in the software development framework
- 3. Create a MyBatis project based on Spring Boot
- Fourth, the creation and use of MyBatis project structure
- 5. Add, delete, and modify operations through MyBatis
- 6. Realize query operation through MyBatis
- 7. The use of MyBatis dynamic SQL
foreword
In the field of software development, the choice of the persistence layer framework plays a vital role in the realization and maintenance of the project. As an excellent persistence layer framework, MyBatis has been widely concerned and applied for its flexibility, high degree of customization, and direct control over SQL. This article will explore the MyBatis framework in depth, from initial knowledge to practical application, and gradually reveal its key role in modern software development.
1. Getting to know MyBatis for the first time
1.1 What is MyBatis
MyBatis is an excellent open source Java persistence layer framework, which is used to simplify the process of database access and operation. It allows developers to use a simple method XML或注解配置
to map the relationship between Java objects and database tables, so as to realize the persistent operation of the database. MyBatis is not a comprehensive ORM (object-relational mapping) framework, but more emphasis on precise control of SQL, enabling developers to write and optimize SQL statements more directly.
ORM (Object-Relational Mapping) framework:
ORM, the full name of Object-Relational Mapping (Object-Relational Mapping), is a software technology used to combine object models in object-oriented programming languages (such as Java, Python, etc.) Mapping and transformation between data models in the database. Simply put, the ORM framework allows developers to use object-oriented thinking to operate databases without directly writing SQL statements.
The core idea of MyBatis lies in the decomposition of SQL, which 将 SQL 语句与 Java 代码
separates, thereby reducing the coupling of the code and providing greater flexibility and maintainability . By configuring the mapping file (Mapper XML), developers can clearly define the mapping relationship between SQL statements and query results, while Java codes focus on writing business logic. In addition, MyBatis also supports features such as dynamic SQL, parameter binding, and caching, making database operations more efficient and convenient.
1.2 Why learn MyBatis
For back-end development, the program is composed of the following two important parts, namely the back-end program and the database.
For these two important components to communicate, they must rely on database connection tools, such as the previous JDBC and the current MyBatis framework, both to connect and operate the database.
However, the operation of using JDBC will be very cumbersome, so you need to use other simpler and more efficient database connection methods, and MyBatis is a better choice.
As a persistence layer framework, MyBatis has many advantages and values in modern software development. The main reasons for learning MyBatis are:
1. Flexible SQL control: MyBatis allows developers to directly write and control SQL statements, which is very useful for scenarios that require precise control and optimization of database operations. Developers can write their own SQL statements and adjust them according to specific needs without being limited by the automatically generated SQL.
2. Good performance: Since developers can optimize SQL statements to make them more suitable for specific database and query requirements, MyBatis has excellent performance. Properly written and optimized SQL statements can significantly improve the database access efficiency of applications.
3. Adapt to different databases: MyBatis supports a variety of databases, so no matter which relational database (such as MySQL, Oracle, SQL Server, etc.) is used, MyBatis can adapt and provide a consistent mode of operation.
4. Good scalability: MyBatis allows developers to write custom TypeHandlers, Plugins, etc. to meet specific needs, thereby enhancing the scalability and customization of the framework.
5. Lightweight framework: Compared with some heavyweight ORM frameworks, MyBatis is a relatively lightweight framework with low learning costs and relatively easy to use.
6. Can be integrated with other frameworks: MyBatis can be easily integrated with other popular frameworks (such as Spring, Spring Boot), making the overall development process smoother.
7. Better understand the database: By learning MyBatis, you will not only learn a framework, but also have a deeper understanding of the working method and performance optimization method of the database, which is very helpful for database design and application optimization.
2. The positioning of MyBatis in the software development framework
It is very important to understand the positioning of MyBatis in the entire software development framework, especially for understanding its role and role in the system architecture. The following is a simple interactive flowchart showing the position and interaction of MyBatis in the entire application architecture:
In the above process, MyBatis is mainly located in the persistence layer (Persistence), and its role is to encapsulate and manage the interaction between business logic and database . The following is the interaction between the layers:
-
Front-end interface : This is the user interface of the application through which the user interacts with the system and sends requests.
-
Control layer (Controller) : The control layer receives requests from the user interface, handles the distribution and scheduling of requests, and calls the appropriate service layer for business processing.
-
Service layer (Service) : The service layer contains the business logic of the application. It receives requests passed by the control layer, processes business logic, and may need to interact with the persistence layer for data.
-
Persistence layer (Persistence - MyBatis) : MyBatis is located in the persistence layer, which is responsible for converting data access requirements in business logic into operations on the database. Through mapping files (Mapper XML) and corresponding interfaces (Mapper Interface) for relational mapping , MyBatis manages the data conversion between Java objects and database tables.
-
Database (DB) : The database is where the actual data is stored. MyBatis performs actual database operations through SQL statements, and reflects operations such as data storage, retrieval, and update to the database.
In this process, MyBatis acts as a bridge in the persistence layer, responsible for connecting business logic with database operations . It allows developers to define the relationship between database tables and Java objects through mapping files or annotations, so as to realize data access. This positioning enables developers to take full advantage of the performance and functionality of the database while maintaining code maintainability and scalability.
3. Create a MyBatis project based on Spring Boot
3.1 Add support for MyBatis framework
- Create a Spring Boot project
- Add MyBatis dependency
When creating a Spring Boot project, if you want to create a MyBatis project, you need to check it in the dependencies. MyBatis Framework
In addition, you need to check a specific database driver, such as MySQL Driver
.
3.2 Configure the database connection information and the storage path of the mapping file (Mapper XML)
After creating the Spring Boot project, you also need to configure application.yml
the database connection information and the storage path of the mapping file (Mapper XML) for MyBatis in the configuration file.
The content of the configuration is as follows:
# 配置数据库的连接字符串
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/database?characterEncoding=utf8
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
This part of the configuration is used to set the database connection information. url
You need to modify the , username
and fields according to the actual situation password
to connect to your own MySQL database. The driver-class-name
field specifies the class name of the MySQL database driver.
# 设置 Mybatis 的 xml 保存路径,在 resources/mapper 创建所有表的 xml ⽂件
mybatis:
mapper-locations: classpath:mapper/*Mapper.xml
This part of the configuration sets Mapper XML
the save path of the file. mapper-locations
field specifies that MyBatis should classpath:mapper/
look for files under the path Mapper XML
. MyMapper
First, you need to create a file corresponding to the interface in this path Mapper XML
before you can use MyBatis.
Fourth, the creation and use of MyBatis project structure
4.1 Preparation of database and tables
userinfo
Create a table and articleinfo
tables here :
-- 创建数据库
drop database if exists mycnblog;
create database mycnblog DEFAULT CHARACTER SET utf8mb4;
-- 使用数据数据
use mycnblog;
-- 创建表[用户表]
drop table if exists userinfo;
create table userinfo(
id int primary key auto_increment,
username varchar(100) not null,
password varchar(32) not null,
photo varchar(500) default '',
createtime timestamp default current_timestamp,
updatetime timestamp default current_timestamp,
`state` int default 1
) default charset 'utf8mb4';
-- 创建文章表
drop table if exists articleinfo;
create table articleinfo(
id int primary key auto_increment,
title varchar(100) not null,
content text not null,
createtime timestamp default current_timestamp,
updatetime timestamp default current_timestamp,
uid int not null,
rcount int not null default 1,
`state` int default 1
)default charset 'utf8mb4';
-- 添加一个用户信息
INSERT INTO `mycnblog`.`userinfo` (`id`, `username`, `password`, `photo`, `createtime`, `updatetime`, `state`) VALUES
(1, 'admin', 'admin', '', '2023-8-09 10:10:48', '2023-8-09 10:10:48', 1);
-- 文章添加测试数据
insert into articleinfo(title,content,uid) values('Java','Java正文',1);
insert into articleinfo(title,content,uid) values('C++','C++正文', 1);
insert into articleinfo(title,content,uid) values('Python','Python', 1);
insert into articleinfo(title,content,uid) values('PHP','PHP正文', 1);
4.2 Create entity classes based on database tables
userinfo
For example, create an entity class for a table :
@Data
public class UserInfo {
private Integer id;
private String username;
private String password;
private String photo;
private LocalDateTime createtime;
private LocalDateTime updatetime;
private Integer state;
}
The attribute names in the entity class generally match the fields in the database table for better compatibility. Here, the annotations in the Lombok library are used @Data
to automatically generate methods such as getter, setter, equals, hashCode and toString of the entity class, which can reduce the writing of boilerplate code.
4.3 Create Mapper interface and XML mapping file
The above entity class already contains the attributes corresponding to the database table fields and the corresponding data types. Just make sure that the interface and documentation correctly match the entity class MyBatis
when used. You can create a corresponding interface and file, and then use annotations to mark the interface.Mapper
Mapper XML
Mapper
XML
@Mapper
mapper
Create an interface under the directory UserMapper
:
Among them, @Mapper
annotation is an annotation in MyBatis, which is used to mark a Mapper interface whose interface is MyBatis, so as to tell MyBatis that this interface defines the method of database operation. In this interface, you only need to write code related to database operations, for example, to obtain all User
information:
import com.example.demo.entity.UserInfo;
import java.util.List;
@Mapper
public interface UserInfoMapper {
List<UserInfo> getAll();
}
Create an XML mapping file:
-
First
resources
create amapper
subdirectory under the directory to storeMapper XML
files:
-
mapper
CreateUserInfoMapper.java
an XML file corresponding to the interface under this pathUserInfoMapper.xml
:
- Then you need to fill this file with the following content:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserInfoMapper">
</mapper>
Among them namespace
, the field specifies the path of the interface UserInfoMapper.xml
corresponding to UserInfoMapper
, at this time, the mapping relationship between the XML file and the interface is established.
When the plug-in is installed in IDEA MyBatisX
, you can find a pair of birds. At this time, click UserInfoMapper.xml
the blue bird on the side to adjust to UserInfoMapper
the interface mapped to it.
Conversely, clicking UserInfoMapper
the red bird in the interface will also jump to the corresponding UserInfoMapper.xml
file.
At this time, it is found that the method in the interface will report an error, because there is Mapper XML
no corresponding SQL statement in the file.
Implement the SQL statement corresponding to the getAll method:
When UserInfoMapper.xml
writing a SQL statement to query all users:
Among them, id
the field specifies the method in the Mapper interface corresponding to this SQL statement, that is getAll
, resultType
the field is the type of the returned data, and the object returned here UserInfo
, the MyBatis framework will configure according to this mapping. After the query execution is completed, the Query results are automatically mapped into UserInfo
objects. But the prerequisite is to ensure that the attribute names in the entity class match the field names of the database table, so that MyBatis can correctly map the results.
4.4 Create service layer Service and control layer Controller
- Create a service layer
service
directory, and create classes under that directoryUserInfoService
:
@Service
public class UserInfoService {
@Autowired
private UserInfoMapper userInfoMapper;
public List<UserInfo> getAll(){
return userInfoMapper.getAll();
}
}
- Create a control layer
controller
directory, and then create a class in that directoryUserInfoController
:
@RequestMapping("/user")
@RestController
public class UserInfoController {
@Autowired
private UserInfoService userInfoService;
@GetMapping("/getAll")
public List<UserInfo> getAll(){
return userInfoService.getAll();
}
}
At this point, the creation of the service layer and the control layer has been completed. The control layer is responsible for processing HTTP requests and the interaction with users and the service layer; while the service layer is used to process business logic related to user information and provide Return the result of processing. This structure conforms to the typical three-tier architecture (Controller - Service - Repository/DAO) design pattern, making the code clearer and easier to maintain.
In the above code, UserInfoService
is responsible for calling to UserInfoMapper
perform database operations, and UserInfoController
is responsible for processing HTTP requests, separating business logic from database operations.
In this basic structure, it is allowed to /user/getAll
obtain all user information through access. For example, run the server at this time, and then enter in the browser http://localhost:8080/user/getAll
to access, you can see that all user information in the database has been obtained:
5. Add, delete, and modify operations through MyBatis
5.1 Add users
1. UserInfoMapper
Add a addUser
method to the interface:
// 增加用户
int addUser(UserInfo user);
2. UserInfoMapper.xml
Write the corresponding SQL statement in:
<insert id="addUser">
insert into userinfo(username, password) values (#{username}, #{password})
</insert>
3. At this point, you can addUser
unit test the
UserInfoMapper
1) Right-click on the interface first , and then select Generate
:
2) Select one of them Test
:
3) Create a unit test class
Select Add Test addUser
Method here. After the addition is complete, you can test
find the corresponding test class in the directory:
4) Write test code
Simple explanation:
- In the test code,
@SpringBootTest
annotations are used to indicate that this is a Spring Boot test. @Autowired
The annotation is used for automatic injectionUserInfoMapper
, allowing it to be used in tests.@Transactional
Annotations are used to represent transactional operations during the test, which will be rolled back at the end of the test to avoid actual impact on the database.
Run the test code and find that it passes the test, indicating that the code just now is correct:
5.2 Modify user
For example, you need to id
modify the user name through the user at this time:
1. UserInfoMapper
Add a updateUserById
method to the interface:
// 根据id修改用户名
int updateUserById(Integer id, String username);
2. UserInfoMapper.xml
Write the corresponding SQL statement in:
<update id="updateUserById">
update userinfo set username=#{username} where id=#{id}
</update>
3. Run unit tests:
1) Add test method
@Test
void updateUserById() {
}
2) Write test code
At this time, userinfo
the content in the table is:
It is required to id
change the user name whose is 1 to admin
:
@Test
void updateUserById() {
Integer id = 1;
String username = "admin";
int res = userInfoMapper.updateUserById(id, username);
System.out.println("影响行数:" + res);
}
3) Run the test method
Execution successful:
Check the table again userinfo
and find that the modification has been successfully performed:
5.3 Delete user
Now, ask to id
delete the specified user by user:
1. UserInfoMapper
Add a deleteUserById
method to the interface:
// 根据 id 删除用户
int deleteUserById(Integer id);
2. UserInfoMapper.xml
Write the corresponding SQL statement in:
<delete id="deleteUserById">
delete from userinfo where id=#{id}
</delete>
3. Run unit tests:
1) Add test method
@Test
void deleteUserById() {
}
2) Write the test method
To delete id
the user whose is 12 at this time:
@Test
void deleteUserById() {
Integer id = 12;
int res = userInfoMapper.deleteUserById(id);
System.out.println("影响行数:" + res);
}
3) Run the test code
Test passed:
userinfo
It is found that the user with 12 in the table id
is deleted at this time :
6. Realize query operation through MyBatis
6.1 Single table query
6.1.1 Query by user ID
1. UserInfoMapper
Add getUserById
a method to the interface:
// 根据id查询用户
UserInfo getUserById(Integer id);
2. UserInfoMapper.xml
Write the corresponding SQL in:
Use #{}
parameter placeholders:
<select id="getUserById" resultType="com.example.demo.entity.UserInfo">
select * from userinfo where id=#{id}
</select>
Use ${}
parameter placeholders:
<select id="getUserById" resultType="com.example.demo.entity.UserInfo">
select * from userinfo where id=${id}
</select>
3) Run unit tests
Query id
for users with 1:
@Test
void getUserById() {
UserInfo user = userInfoMapper.getUserById(1);
System.out.println(user);
}
Run results using #{}
parameter placeholders:
The result of using ${}
the parameter placeholder:
It is not difficult to find through the above test code:
- When using
#{}
the parameter placeholder, the parameter position in the SQL statement to be executed is?
, that is, it has been precompiled by SQL, and it needs to be?
assigned later; - When using
${}
the parameter placeholder, the parameter is directly replaced.
6.1.2 Parameter placeholders #{} and ${}
In MyBatis, #{}
and ${}
are two commonly used parameter placeholders for referencing parameter values in SQL statements. Although they look similar, there are some important differences when used.
1. #{}
Placeholders:
#{}
When the placeholder is used in the SQL statement, it will自动进行预编译,防止 SQL 注入攻击
and can handle the type conversion of the parameter. It works with most SQL parameters like strings, numbers, etc.
2. ${}
Placeholders:
${}
Placeholders are used when used in SQL statements将参数值直接嵌入到 SQL 语句中,不进行预编译
. This can pose a SQL injection risk and needs to be used with caution. It is suitable for some special scenarios, such as dynamic table names or column names, etc.
#{}
Therefore, it is recommended to use placeholders as much as possible in most cases to ensure the safety and maintainability of SQL. ${}
Use placeholders only when necessary , while ensuring the legality and safety of input parameters.
6.1.3 SQL Injection Issues
${}
The following SQL injection problem occurs when using simulated login:
1. UserInfoMapper
Add getUserById
a method to the interface:
// 实现登录操作
UserInfo login(UserInfo user);
2. UserInfoMapper.xml
Write the corresponding SQL in:
<select id="login" resultType="com.example.demo.entity.UserInfo">
select * from userinfo where username='${username}' and password='${password}'
</select>
Since the use ${}
is a direct parameter replacement, it needs to ${}
be added outside ''
.
3. Write unit tests
First a normal demo:
@Test
void login(){
String username = "zhangsan";
String password = "123456";
UserInfo user = new UserInfo();
user.setUsername(username);
user.setPassword(password);
UserInfo loginUser = userInfoMapper.login(user);
System.out.println(loginUser);
}
At this point, the object can be successfully obtained:
But if you password
change to:
String password = "' or 1='1";
Run the test code again:
It is found that all the content in the database has been obtained at this time, and the executed SQL statement is:
select * from userinfo where username='zhangsan' and password='' or 1='1'
That is, regardless of whether the input username
and password
are correct, where
the condition is always true true
, which is the risk of SQL injection.
If you ${}
change to #{}
:
<select id="login" resultType="com.example.demo.entity.UserInfo">
select * from userinfo where username=#{username} and password=#{password}
</select>
Run the previous code again:
At this time, by precompiling and then obtaining parameters, the risk of SQL injection is avoided.
6.1.3 like query
Use like
fuzzy query by user name:
1. UserInfoMapper
Add getListByName
a method to the interface:
// like 模糊查询
List<UserInfo> getListByName(@Param("username") String username);
2. UserInfoMapper.xml
Write the corresponding SQL in:
Use #{}
parameter placeholders:
<select id="getListByName" resultType="com.example.demo.entity.UserInfo">
select * from userinfo where username like '%#{username}%'
</select>
At this time, through the unit test, it is found that an error will be reported at the end:
This is because when used #{}
, the resulting SQL statement is:
select * from userinfo where username like '%'ang'%'
And this is a wrong SQL statement, all will report an error, so like
when using the query, you need to use ${}
the parameter placeholder for direct replacement .
<select id="getListByName" resultType="com.example.demo.entity.UserInfo">
select * from userinfo where username like '%${username}%'
</select>
Run the test code again and find that it can be found successfully:
However, there is still a SQL injection problem, so it still needs to be used #{}
. For this situation, you can use the built-in function of MySQL concat
to solve it:
<select id="getListByName" resultMap="BaseMap">
select *
from userinfo
where username like concat('%', #{
username}, '%');
</select>
Among them, concat
the function is to splice strings and support variable parameters.
6.1.4 Use resultMap to solve the mismatch between entity class parameters and database table fields
Sometimes, the parameter name in the entity class in our program may not match the field name in the database table, then MyBatis cannot correctly bind the query result to the entity class object, which can be solved by using in this case Mapper XML
.resultMap
For example, userinfo
the password field in the table is password
, and the attribute name in the entity class is called pwd
. At this time, getUserById
the user is queried through, and finally pwd
the attribute is found to be empty:
At this point, UserInfoMapper.xml
add a new resultMap
tag to the file:
Simple explanation:
-
<id>
Elements: Maps that define primary keys.column
The attribute specifies the column name of the database table, andproperty
the attribute specifies the attribute name of the entity class. In this example, the primary key column "id" of the database table is mapped to the attribute "id" of the entity class. -
<result>
Element: defines the mapping of common columns.column
The attribute specifies the column name of the database table, andproperty
the attribute specifies the attribute name of the entity class. In this example, the "username" column of the database table is mapped to the attribute "username" of the entity class, the "password" column is mapped to the attribute "pwd" of the entity class, and the "photo" column is mapped to the attribute "photo" of the entity class.
Then modify getUserById
the SQL corresponding to the method, and modify the returned result to be a dictionary mapping baseMap
:
<select id="getUserById" resultMap="baseMap">
select * from userinfo where id=${id}
</select>
Run the test code again to get the correct result:
password
Of course, you can also rename to in the SQL statement pwd
to solve this problem, for example:
<select id="getUserById" resultType="com.example.demo.entity.UserInfo">
select id, username, password as pwd, photo, createtime, updatetime, state
from userinfo where id=${id}
</select>
At this time, the correct result can also be obtained:
6.2 Multi-table query
6.2.1 Creation of VO class
When performing representative queries, it is usually necessary to create a value object (VO, Value Object) to contain information about multiple tables. The VO class is a Java class, usually used to encapsulate the attributes of multiple entity classes, so as to facilitate the transfer and processing of data in multiple table queries.
For example, at this time, you need to query the article details through the article id
, and the article details need to contain the user name, but articleInfo
there are only users in the table uid
, so you need to perform multi-table query. In order to facilitate the combination of user name and article information, an additional ArticleInfoVO
class needs to be created.
First create articleinfo
the entity class corresponding to the table ArticleInfo
:
Then inherit this class and vo
create a ArticleInfoVO
class under the directory:
6.2.2 Create Mapper interface and XML mapping file
1. Create a Mapper interface ArticleInfoVOMapper
:
2. Create an XML mapping file ArticleInfoVOMapper.xml
:
6.2.3 Query article details
1. ArticleInfoVOMapper
Create a method in the interface getDetial
:
// 通过文章 id 查询文章详情
ArticleInfoVO getDetial(Integer id);
2. ArticleInfoVOMapper.xml
Write the corresponding SQL statement in the file:
<select id="getDetial" resultType="com.example.demo.entity.vo.ArticleInfoVO">
select a.*, u.username from articleinfo a
left join userinfo u on a.uid = u.id
where a.id = #{id}
</select>
3. Write unit tests
@SpringBootTest
class ArticleInfoVOMapperTest {
@Autowired
private ArticleInfoVOMapper articleInfoVOMapper;
@Test
void getDetail() {
ArticleInfoVO detail = articleInfoVOMapper.getDetail(1);
System.out.println(detail);
}
}
Run the test code and find that the result can be found correctly:
7. The use of MyBatis dynamic SQL
MyBatis dynamic SQL refers to the process of dynamically generating SQL queries or update statements according to different conditions and parameters . It allows dynamic assembly of various parts of SQL statements according to business needs when writing SQL mapping files, thereby achieving more flexible database operations. Dynamic SQL is very useful in dealing with different query conditions, sorting, filtering, etc. It can avoid writing a large number of repeated SQL statements due to multiple situations, thereby improving development efficiency.
MyBatis provides a series of XML tags and syntax for building dynamic SQL. These tags can be used to include operations such as conditional judgment, loop traversal, and dynamic splicing of SQL fragments. Some commonly used dynamic SQL tags include <if>
, <choose>
, <when>
, <otherwise>
, <trim>
, <where>
, <set>
, <foreach>
etc. For details, please refer to MyBatis official website: Dynamic SQL .
In short, MyBatis dynamic SQL is a powerful mechanism that makes it more flexible and convenient to generate appropriate SQL statements according to different situations in the SQL mapping file. The following is a detailed introduction to some common dynamic SQL tags.
7.1 if tag
<if>
Labels are used to add conditional judgments in SQL statements, and dynamically generate SQL fragments according to the true or false conditions.
For example, when adding user information, photo
the content of the field may not be entered by the user. In this case, you need to use <if>
the tag to build dynamic SQL:
<insert id="addUser">
insert into userinfo(
username,
<if test="photo!=null and photo!=''">
photo,
</if>
password
)
values (
#{username},
<if test="photo!= null and photo!=''">
#{photo},
</if>
#{pwd}
)
</insert>
It should be noted that the attribute <if>
in the tag test
specifies the attribute of the object passed in, not the field in the database table.
In the unit test, only enter username
and password
, and the final SQL only has these two fields:
if you add an photo
attribute:
It can be found that there are three fields at this time.
7.2 trim label
If all the attributes entered are optional, then only using <if>
the tag cannot solve ,
the problem, because I don’t know ,
where it will appear, it can appear in the front, or it may appear in the back. If there is no input, it may be all does not appear. Therefore, to solve this problem, tags need to be introduced <trim>
.
<trim>
Label properties:
prefix
: Represents the entire statement block,prefix
prefixed with the value ofsuffix
: Indicates the entire statement block,suffix
suffixed with the value ofprefixOverrides
: Indicates the prefix to be removed from the entire statement blocksuffixOverrides
: Indicates the suffix to be removed from the entire statement block
username
For example, the three fields , password
, and photo
are optional when adding users :
<insert id="addUser">
insert into userinfo
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="username!=null and username!=''">
username,
</if>
<if test="photo!=null and photo!=''">
photo,
</if>
<if test="pwd!=null and pwd!=''">
password,
</if>
</trim>
values
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="username!=null and username!=''">
#{username},
</if>
<if test="photo!=null and photo!=''">
#{photo},
</if>
<if test="pwd!=null and pwd!=''">
#{pwd},
</if>
</trim>
</insert>
Among them, <trim>
the role of the label is to trim the inserted column name and value part, and redundant commas can be deleted at the beginning and end positions. prefix
Attributes represent what is added before the SQL fragment, suffix
attributes represent what is added after the SQL fragment, and suffixOverrides
attributes represent what is removed at the end of the SQL fragment.
7.3 where tag
<where>
Labels are used to add conditions to the WHERE clause of an SQL statement and handle the logic between the conditions.
For example, you can now query through id
the or of the article, where the content of and are optional inputs, and fuzzy matching is used.title
id
title
title
<select id="getListByIdOrTitle" resultType="com.example.demo.entity.vo.ArticleInfoVO">
select a.*, u.username from articleinfo a
left join userinfo u on a.uid = u.id
<where>
<if test="id != null and id > 0">
and a.id = #{
id}
</if>
<if test="title!=null and title!=null">
and a.title like concat('%', #{
title}, '%')
</if>
</where>
</select>
In addition, <where>
the label will automatically remove the prefix and
.
Of course, you can also use <trim>
the and <if>
tags to achieve this functionality:
<select id="getListByIdOrTitle" resultType="com.example.demo.entity.vo.ArticleInfoVO">
select a.*, u.username from articleinfo a
left join userinfo u on a.uid = u.id
<trim prefix="where" prefixOverrides="and">
<if test="id != null and id > 0">
and a.id = #{
id}
</if>
<if test="title!=null and title!=null">
and a.title like concat('%', #{
title}, '%')
</if>
</trim>
</select>
At this time, you need to use <trim>
tags to remove a prefix and
and add a prefix where
.
7.4 set tags
<set>
Labels are used to set the fields that need to be updated in the update statement, and dynamically generate the update statement according to the conditions.
For example, id
to modify null
the attributes of the user who is not by the user:
<update id="updateById">
update userinfo
<set>
<if test="username!=null and username!=''">
username=#{
username},
</if>
<if test="pwd!=null and pwd!=''">
password=#{
pwd},
</if>
<if test="photo!=null and photo!=''">
photo=#{
photo},
</if>
</set>
where id=#{
id}
</update>
<set>
tags and <where>
instead, it only strips the suffixed ones ,
.
7.5 foreach tag
<foreach>
Labels are used to iterate through a collection or array and add its elements to an SQL statement.
<foreach>
Tags have the following attributes:
collection
: The collection in the binding method parameter, such as List, Set, Map or array objectitem
: each object when traversingopen
: The string at the beginning of the statement blockclose
: The string at the end of the statement blockseparator
: A string of intervals between each traversal
For example, now you need to id
delete the corresponding article based on multiple articles:
1. ArticleInfoVOMapper
Add a method to the interface:
// 根据多个文章 `id`来删除对应的文章
int deleteByIds(List<Integer> ids);
2. When ArticleInfoVOMapper.xml
writing the corresponding SQL:
<delete id="deleteByIds">
delete from articleinfo where id in
<foreach collection="ids" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
</delete>
This code demonstrates an example of building a delete statement using MyBatis' dynamic SQL. DELETE
This delete statement will dynamically generate the clause in the statement according to the given ID list IN
, so as to delete records satisfying the condition in batches.
Simple explanation:
-
<delete>
Label: This label represents the definition of a delete statement. -
<foreach>
Label: This label is used to traverse the collection and add the elements in the collection to the SQL statement. In this example, it wouldids
add each element in the collection toIN
the clause, forming(id1, id2, id3)
a structure like .collection
Attribute: Specifies the collection to traverse.item
Attribute: Specifies the alias of each element during traversal.open
Attribute: Specify the character at the beginning of the traversal, here it is(
.close
Attribute: Specifies the character at the end of the traversal, here it is)
.separator
Attribute: Specifies the separator between elements, here is a comma,
.
In this way, dynamic SQL can be used to build bulk delete statements to delete corresponding records based on a given set of IDs.
3. Run unit tests:
@Transactional
@Test
void deleteByIds() {
List<Integer> ids = new ArrayList<>();
ids.add(1);
ids.add(2);
ids.add(3);
ids.add(4);
int res = articleInfoVOMapper.deleteByIds(ids);
System.out.println("影响行数:" + res);
}
Test passed: