SoFunction
Updated on 2025-05-12

Java development can be used to provide detailed explanations of @Mapper annotations

Preface

Recently, when I was learning Java programming, I encountered a super powerful "little assistant" called @Mapper annotation. You know that when I am fiddling with those projects, it is a headache to deal with databases. All kinds of complex operations are so stinky and long that I write. But since I used the @Mapper annotation, hey, it was like I had a cheat on my programming path, the code became concise and clear, the development efficiency was rising rapidly, and I felt much more relaxed. And I told you that when I went to the internship, I found that when I was learning industry information, most of the large and small companies used this annotation in Java development projects. If we master it, whether we look for a job in the future or want to get a job in the company, we will have more advantages. It is like holding a golden key to open the door to the workplace, so everyone has to study hard with me.

What is @Mapper, let me know what to do with my family

(I) Popular explanation

Let’s talk about what @Mapper annotation is in simple terms. You just think of it as a super courier. The Java code we write is like senders and recipients, and the database is the big warehouse. This @Mapper annotation courier runs around between Java code and database, passing data. For example, we need to store the information of a new user in the database, or find out the information of a certain user from the database. As long as we issue instructions to the courier, that is, use the @Mapper annotation in the code, it can handle data storage and querying things smoothly, so that we don’t have to worry about those complicated underlying operations and easily realize the functions we want. Isn’t it amazing?

(II) Professional analysis

To go deeper, from a professional perspective, @Mapper annotation is a key role in the MyBatis framework. What is MyBatis? It is a super easy-to-use persistence layer framework that can help us connect Java programs and databases firmly. And the @Mapper annotation plays an important role in this connection process. It allows us to define interfaces and write various methods in the interface. These methods can be one by one correspond to SQL statements written in XML files or written directly with annotations to achieve accurate database interaction. For example, we define a method to find users in the interface, then use @Mapper annotation to mark this interface, and then match it with the corresponding SQL statement. When we call this interface method in Java code, MyBatis knows which SQL statement to execute in the database and retrieve the data we want. Do you think the design behind this is exquisite?

Start hands-on, start the code

(I) Environmental construction preparation

Just talking about it and not practicing fake moves, let’s start practicing it now. The first step is to build a development environment, just like building a house requires laying the foundation first. Let’s create a Maven project first. If you don’t know what Maven is, it is like a caring butler, helping us manage all the library files needed by the project in an orderly manner. Among our commonly used development tools, such as Intellij IDEA, after opening it, follow the wizard to fill in the basic information of the project step by step, such as "Group" (usually written in the company domain name upside down, we can just practice it by ourselves, like ""), "Artifact" (project name, just make a favorite one yourself, like "demo-project"). Then, in the project file, you have to add MyBatis and the database driver dependencies we want to connect to. For example, if we connect to the MySQL database, we have to add these:

<dependency>
    <groupId></groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.0</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.23</version>
</dependency>

Here, ":mybatis-spring-boot-starter" is the launcher of MyBatis in the Spring Boot project. It integrates MyBatis-related things for us to use; "mysql:mysql-connector-java" is the driver that connects to MySQL. Add these dependencies well, and even if our development environment is set up, we can start the next step.

(II) Define entity classes

The environment is ready, let’s define the entity class. Taking user information as an example, we create a User entity class in the "" directory of the project (if there is no such directory, create a new one). The code is as follows:

package ;

public class User {
    private Long id;
    // User ID, unique identity for each user    private String name;
    // User name    private String email;
    // User email
    // Here you have to generate get and set methods to facilitate MyBatis access to data    public Long getId() {
        return id;
    }

    public void setId(Long id) {
         = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
         = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
         = email;
    }
}

This User entity class is like a small box containing user information. The properties inside correspond to the fields of the user table in the database. Through the get and set methods, MyBatis can easily fetch the data and put it in. Isn't it easy to understand?

(III) Create a Mapper interface

With the entity class, we then create the Mapper interface. In the "" directory (again, if not, create a new one), create a UserMapper interface with the following code:

package ;

import ;
import ;
import ;
import ;
import ;
import ;

import ;

@Mapper
public interface UserMapper {
    @Insert("INSERT INTO user (name, email) VALUES (#{name}, #{email})")
    void insertUser(User user);

    @Delete("DELETE FROM user WHERE id = #{id}")
    void deleteUserById(Long id);

    @Update("UPDATE user SET name = #{name}, email = #{email} WHERE id = #{id}")
    void updateUser(User user);

    @Select("SELECT * FROM user WHERE id = #{id}")
    User selectUserById(Long id);

    @Select("SELECT * FROM user")
    List<User> selectAllUsers();
}

The @Mapper annotation here is like putting a special label on this interface, telling MyBatis that the interface is very important and should be paid attention to. Each method in the interface corresponds to an SQL operation, such as inserting user information, deleting users, updating user information, finding users based on IDs, and finding all users. We use the corresponding @Insert, @Delete, @Update, and @Select annotations to write SQL statements on the method, and pay attention to the #{parameter name} in these SQL statements, which can automatically extract the corresponding attribute values ​​in the User entity class we passed in. Is it super intelligent when using SQL statements?

(IV) Write SQL statements

We have just written some simple SQL statements in the Mapper interface, but sometimes our needs are a little more complicated. For example, we need to vaguely query users based on the user's name and email address, and then we can use dynamic SQL. In the UserMapper interface, let's add another method:

@Select("<script>" +
            "SELECT * FROM user " +
            "<where>" +
                "<if test='name!= null'>" +
                    "AND name LIKE '%${name}%'" +
                "</if>" +
                "<if test='email!= null'>" +
                    "AND email LIKE '%${email}%'" +
                "</if>" +
            "</where>" +
        "</script>")
List<User> selectUsersByNameAndEmail(User user);

Here we use the <if> tag to determine whether the incoming user name and email address are empty. If it is not empty, it will be spliced ​​into SQL statements to implement fuzzy query. Isn’t it very flexible? Also note that the parameter name is used here, which is a bit different from the parameter name. {parameter name} directly splices the parameter values ​​into SQL statements, which is suitable for this kind of fuzzy query scenario. However, you should pay attention to prevent SQL injection, we will talk about it in detail later.

(V) Improved configuration files

The code is almost done, and we have to improve the configuration file. In Spring Boot projects, database connection information is usually set in or in files. For example, in the file, we have to write these:

=jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC
=root
=123456
-class-name=

Here "" is the connection address of the database, "localhost” means the local database, "3306" is the default port of MySQL, "mydb" is the database name, and the following parameter "useSSL=false" means that you do not use SSL to encrypt the connection (it can be done in local testing, the formal environment may need to be adjusted according to the situation), "serverTimezone=UTC" is to set the time zone to avoid some time problems; "" and "" are the username and password for logging in to the database, which must be filled in according to what we set when installing the database ourselves; "-class-name" is to specify the database driver class, which is the MySQL driver. Writing these configurations is like specifying the location of the data warehouse to our program, and it can find the database smoothly and start working.

(VI) Test and verification function

Finally, we have to test and verify whether the code we wrote works well. In the test class of the project, for example, in the "" directory (if not, create a new one), we create a UserMapperTest class, the code is as follows:

package ;

import ;
import ;
import ;
import ;
import ;

import ;

@SpringBootTest
public class UserMapperTest {
    @Autowired
    private UserMapper userMapper;

    @Test
    public void testInsertUser() {
        User user = new User();
        ("Zhang San");
        ("zhangsan@");
        (user);
    }

    @Test
    public void testSelectUserById() {
        Long id = 1L;
        User user = (id);
        assert user!= null;
        ("User Name:" + () + ", Mail:" + ());
    }

    @Test
    public void testSelectAllUsers() {
        List&lt;User&gt; userList = ();
        for (User user : userList) {
            ("User Name:" + () + ", Mail:" + ());
        }
    }
}

Here we use the Spring Boot test framework, and the UserMapper interface we wrote before is injected into the @Autowired annotation. Then, in each test method, we call the methods of inserting users, searching users based on ID, and finding all users, and use assertions to verify the results. For example, when searching for users, the user found is not empty, so that we can ensure that our code can work normally, just like checking the answer after the exam, and we feel much more at ease.

In-depth exploration, advanced gameplay reveals

(I) Dynamic SQL statement application

We just briefly introduced dynamic SQL, and now we will talk about it in-depth. In addition to the <if> tags I just used, there are also tags such as <choose> and <where> that are also very commonly used. For example, we need to implement a complex query to find users according to different conditions, sometimes by name, sometimes by email, and sometimes by age range. At this time, we can use the <choose> tag, the code is as follows:

@Select("<script>" +
            "SELECT * FROM user " +
            "<where>" +
                "<choose>" +
                    "<when test='name!= null'>" +
                        "AND name LIKE '%${name}%'" +
                    "</when>" +
                    "<when test='email!= null'>" +
                        "AND email LIKE '%${email}%'" +
                    "</when>" +
                    "<when test='age!= null'>" +
                        "AND age BETWEEN #{} AND #{}" +
                    "</when>" +
                "</choose>" +
            "</where>" +
        "</script>")
List<User> selectUsersByCondition(User user, AgeRange age);

Here we assume that we have an AgeRange class to represent the age range. Through the <choose> tag, we can flexibly generate different SQL statements according to different conditions passed in to meet various complex query needs. Isn’t it very powerful?

(II) Associative query and result mapping

Let’s talk about related query. For example, our project has a user table and an order table. A user may have multiple orders. Sometimes we need to query the user and his order information. At this time, we can use @Results and @ResultMap annotations. First, we have to define a method in the UserMapper interface:

@Select("SELECT u.*, o.* FROM user u LEFT JOIN order o ON  = o.user_id")
@Results(id = "userWithOrdersResult", value = {
    @Result(property = "id", column = ""),
    @Result(property = "name", column = ""),
    @Result(property = "email", column = ""),
    @Result(property = "orders", javaType = , many = @Many(select = "")),
})
User getUserWithOrders(Long id);

The @Select annotation here writes SQL statements for the associated query, and connects the user table and the order table through LEFT JOIN. The @Results annotation is used to define the result map, and correctly map the query results to the User entity class and its associated order list. The @Result annotation corresponds to the mapping of each attribute. For the order list, we use the many attribute of @Result to specify a subquery. By calling the selectOrdersByUserId method of the OrderMapper interface, we obtain the user's order information. Isn't it very clever?

Frequently Asked Questions

(I) Annotation failure problem

When using @Mapper annotation, sometimes you will encounter the problem of annotation failure. For example, we clearly wrote the @Mapper annotation, but it seems that MyBatis did not see it, and the interface method call will report an error. This may be because we did not configure MyBatis correctly to scan to our Mapper interface. In Spring Boot project, if we use annotation driver method, we must ensure that the @MapperScan annotation is added to the startup class and specify the package where the Mapper interface is located, such as:

package ;

import ;
import ;
import ;
import ;

@SpringBootApplication
@MapperScan("")
public class DemoApplication {
    public static void main(String[] args) {
        (, args);
    }
}

@MapperScan ("") here tells Spring Boot to scan all Mapper interfaces under the "" package, so that the annotation failure problem can be solved.

(II) SQL syntax error check

Another common problem is SQL syntax errors. When we write SQL statements, we accidentally write them wrong, such as writing less quotation marks or spelling the keywords incorrectly, the program will report an error when it runs. In this case, we have to learn to quickly locate the problem from the error message. Generally speaking, MyBatis will give more detailed error reporting information, telling us which SQL statement has made an error and where it is. Based on this information, we carefully check the SQL statement to find the error and correct it. For example, if the error message says "near 'FROM user WHERE id = #{id}': syntax error", we will know that there is a syntax error in the statement "FROM user WHERE id = #{id}". It may be that there is a missing space or the keyword is written incorrectly. After careful reading, it turns out that "DELETE" is written as "DELET", and there will be no problem after correction.

Summarize

This is the end of this article about the detailed explanation of @Mapper annotation in Java. For more information about @Mapper annotation related to Java, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!