MyBatis query database

Table of contents

1. What is MyBatis?

2. Configure MyBatis environment

3. MyBatis model development

4. Unit testing

5. Add, delete, check and modify


1. What is MyBatis?

        MyBatis is an open source Java-based persistence layer framework, which can help Java developers simplify database operations, map Java objects to corresponding database tables through XML configuration files or annotations, and realize mutual conversion between object relationships and data relationships , so that Java applications can more easily operate and read the database .

Compared with other ORM frameworks, the biggest feature of MyBatis is that it provides excellent SQL writing and debugging mechanisms. Through MyBatis, we can directly write native SQL statements, and through some tools of MyBatis, such as parameter mapping, result set mapping and other mechanisms, the query results are automatically mapped into data formats such as Java objects or List/Map. At the same time, MyBatis also provides advanced features such as lazy loading, caching and transactions, which can support various complex business scenarios.

main idea

         Map the data in the JavaBean and the data in the SQL statement. Therefore, when using MyBatis, we need to define a Mapper interface, and then describe the SQL statement corresponding to each method in this interface in XML, and specify the parameters and return value Type, finally, let MyBatis automatically generate the implementation class of the Mapper interface, so that the database can be easily operated.

persistence layer

        In Java program development, data is usually stored in relational or non-relational databases, and the persistence layer is the technical level used to process and manage these data access operations. The role of the persistence layer is to convert the objects in the application into a storable form, and then store them in the data storage medium, and also be responsible for obtaining data from the data storage medium and converting it into the objects required by the application In this way, data storage and data access are separated, which improves the maintainability and scalability of the program.

Persistence layer technology usually includes the following aspects:

  • Object-relational mapping (ORM): ORM maps Java objects and relational databases, so that Java objects can operate databases like memory, simplifying development.
  • Data Access Layer (DAO): defines the interface for data access, encapsulates the details of data access, so that the upper layer business logic does not need to pay attention to the specific implementation of data access.
  • Persistence framework: used to simplify database access, improve performance, reduce development difficulty, and provide advanced functions, such as caching, batch processing, distributed sharing, etc.

Disadvantages of JDBC programming

  1. Complicated code writing: JDBC requires developers to manually write a large number of codes such as result set mapping and exception handling, which is prone to repeated codes and errors.

  2. It is easy to cause resource leaks: using JDBC needs to explicitly open and close objects such as connections, Statements, and ResultSets. If not handled carefully, it may cause resource leaks, thereby affecting the performance and stability of the application.

  3. Hard coding of SQL statements: JDBC needs to write SQL statements directly in Java code, so hard coding is easy to occur, and it is not convenient to modify and maintain SQL statements.

  4. Difficult to deal with complex business scenarios: If an application has complex business logic requirements, such as multi-table association query, paging query, transaction control, etc., it may be difficult to implement it using JDBC, and a large amount of complex code needs to be written.

MyBatis can solve these problems. The ORM framework can automatically map Java objects and database tables, and provides a more elegant and efficient API, allowing developers to focus on business logic rather than cumbersome data access codes. At the same time, the ORM framework can also provide advanced features such as caching, lazy loading, and batch processing, thereby further improving the performance and maintainability of the program.

MyBatis and JDBC

MyBatis is implemented based on JDBC. Although MyBatis has great similarities with JDBC, it encapsulates the details of JDBC so that developers can perform database operations more conveniently and efficiently.

When using MyBatis for data access, the program still needs to use the JDBC API to obtain connection objects, create Statement objects, execute SQL statements, and process query results. However, MyBatis simplifies and encapsulates JDBC, provides an object-oriented way to access the database, configures SQL statements through XML or annotations, and provides some advanced features, such as caching, dynamic SQL and object-relational mapping (ORM).

The advantage of MyBatis over JDBC is that MyBatis is easier to use and improves development efficiency; at the same time, MyBatis also provides more functions, such as automatic mapping, dynamic SQL and secondary cache, etc., which can improve the performance and reliability of applications. maintainability.

Therefore, MyBatis is an advanced data access framework based on JDBC. It encapsulates the underlying details of JDBC, provides an advanced, object-oriented way to access the database, and provides a variety of advanced features to facilitate developers. Implement data access and business logic.

ORM framework

ORM is the abbreviation of Object-Relational Mapping (Object-Relational Mapping), which is a technology for converting and mapping object models and relational database models. Through the ORM framework, Java objects can be mapped to rows in relational database tables, thereby operating the database in an object-oriented manner without writing a large number of SQL statements.

What is the mapping of Java classes, objects, and object attributes to the ORM framework

Class mapping: In MyBatis, Java classes are mapped to a table in the database

Object mapping: In MyBatis, Java objects are mapped to data rows in the database

Attribute mapping: There is a one-to-one correspondence between the attributes of the Java object and the columns of the database table

2. Configure MyBatis environment

1. Add MyBatis framework support

It will report an error after running

2. Set MyBatis configuration information

1. Set database connection related information

2. Configure xml save path, xml naming rules 

classpath

        Indicates the class path, which is the path pointed to by the CLASSPATH environment variable of the application, and is used to instruct the MyBatis framework to look for configuration files under the class path.

/mybatis/

        is a directory path, indicating that the MyBatis framework will look for *Mapper.xml configuration files in mybatisthe directory .

*Mapper.xml

        *is a wildcard, indicating that all files Mapper.xmlending should be parsed and loaded by the MyBatis framework.

Taken together, classpath:/mybatis/*Mapper.xmlit is used to instruct the MyBatis framework to search for all configuration files ending with in mybatisthe directory Mapper.xml, and parse them into MyBatis Mapper mapping files.

For example, suppose we have a directory mybatisnamed , which contains two MyBatis mapping files: UserMapper.xmland OrderMapper.xml. Then, using classpath:/mybatis/*Mapper.xmlthis path expression, the MyBatis framework will automatically parse the two mapping files, and bind their configuration information to the corresponding Java interface or class, so as to realize the data access operation with the database.

At this point, the configuration environment is complete

3. MyBatis model development

First insert some data into the database

First, create an entity class UserEntity, which contains the above attributes and must correspond.

Next, declare the method to operate on the UserEntity table in the Mapper interface:

Mapper is a concept in the MyBatis framework, which is used to describe a set of rules for mapping Java objects to SQL statements. Usually, Mapper will contain a set of interfaces and configuration files to define the mapping relationship between Java objects and database tables.

Then, in the Mapper.xml file, implement these interface methods

<?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.UserMapper">
    <select id="getAll" resultType="com.example.demo.entity.UserEntity">
        select * from userinfo
    </select>
</mapper>

id corresponds to the method name in the interface

namesapce: implement the interface (package name plus class name)

Layer according to the standard, and then create a Service layer to access Mapper 

The Service layer processes business logic and provides external service interfaces

Create the Controller layer

Controller layer: responsible for receiving user requests, calling the Service layer to process the requests, and presenting the processing results through the view

Start the project and successfully visit 

Insert a piece of data into the table

After refresh, update the new data inserted in the database

The above is the simplest query operation

4. Unit testing

 Here is an introduction to the concept of unit testing

SpringBoot has built-in unit test dependencies, no need to add support

spring-boot-starter-testIt is a test starter provided by Spring Boot, which aims to provide various common testing tools and frameworks, making it easier for developers to write, run, and manage unit tests and integration tests for Spring Boot applications

Contains the following main components:

  1. JUnit: A widely used Java unit testing framework that can help developers quickly build unit test cases and automatically execute these test cases; ()JUit5 we use here)
  2. Spring Test: A test framework specially designed for Spring applications, which can help developers quickly build a Spring container environment, execute test cases in the container environment, and verify the correctness of the application;
  3. AssertJ: An excellent assertion library that can help developers write concise, easy-to-understand, and easy-to-extend assertion statements;
  4. Hamcrest: Another popular assertion library that also provides various assertion methods similar to AssertJ;
  5. Mockito: A powerful Java simulation framework that can help developers quickly create mock objects and perform various tests;
  6. JsonPath: A library for processing JSON paths, which can help developers quickly filter and extract JSON data.

The main advantages are as follows:

  1. Improve testing efficiency: With  spring-boot-starter-test various testing tools and frameworks provided by Starter, developers can write, run, and manage unit tests and integration tests more easily, thereby greatly improving testing efficiency;
  2. Convenient integration of Spring Boot: spring-boot-starter-test Starter is perfectly integrated with Spring Boot, and can directly use Spring Boot's automatic configuration mechanism and dependency injection mechanism, making unit testing and actual application development more seamless;
  3. Simplify code writing: With the help of  spring-boot-starter-test various testing tools and frameworks provided by Starter, developers do not need to write a lot of test framework code, but only need to focus on writing business logic and test cases;
  4. Diversified test support: spring-boot-starter-test Starter supports various types of tests: unit test, integration test, end-to-end test, etc.;
  5. Good community support and updates: spring-boot-starter-test Starter is one of the core components of the Spring Boot community. It has a large user base and an active maintainer team, which can update and fix problems in various testing tools and frameworks in a timely manner.

Unit test implementation steps

1. Right-click Generate on the class to be tested

will generate test classes

Write test information. Don't forget to add annotations!!

Start the test class

This is the creation of the test class. When adding a test to the test class, an error will be reported

 

It means that this test class already exists, whether to add a test to it, click Ok directly

Unit testing is easy to understand here

5. Add, delete, check and modify

Let's look at the problem of passing parameters

When the parameter names in these two places are inconsistent, what should be written in xml

An error will be reported when starting the test class, and the parameter id is not found

 Modify the xml file

At this point the unit test runs successfully.

 Therefore, the parameter name of the xml file must be consistent with @Param("uid"). If this annotation is not added, it must be the same as the original parameter name

 Annotations are added, and what takes effect is the parameter naming in the annotations

There are two ways for Mybatis to obtain dynamic parameters:

1.${key}

${key} is a placeholder syntax, known as string replacement, used to replace the parameter placeholder in the SQL statement with the actual value. Using the ${} syntax directly replaces the parameter with an SQL string, rather than passing the parameter through a prepared statement. Improper handling of input parameters when using ${key} can lead to SQL injection attacks.

You can print out the executed generated SQL statement, and you can see the effect

Need to configure it first

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mycnblog?characterEncoding=utf8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#配置mybatis xml 的文件路径,在resources/mapper 创建的所有表的 xml 文件
mybatis.mapper-locations=classpath:/mybatis/*Mapper.xml


#日志打印sql
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#日志打印级别(默认是info,需要设置位debug,才能显示)
logging.level.com.example.demo=debug

then execute the test

You can see that this is directly replacing the parameters with SQL strings 

2.#{key}

In MyBatis, #{key} is a placeholder syntax, called a parameter placeholder, which is used to replace the parameter placeholder in the SQL statement with the actual value. It can help us use parameters in SQL statements, making SQL statements more flexible and versatile

Specifically, when the application calls the method of the DAO layer, some parameters will be passed to the corresponding SQL statement, and these parameters can be referenced by the #{} placeholder. MyBatis will automatically precompile the parameter values ​​in #{} to ensure the security of input data, and insert them into SQL statements in a safe manner, and then send them to the database for execution, thereby preventing security such as SQL injection attacks question

Start unit tests

Here #{uid} is a placeholder, which means that the position needs to be dynamically replaced with a specific parameter value. When executing SQL, MyBatis will automatically replace #{uid} with the value of the uid parameter actually passed in, and precompile it to ensure the security of the SQL query statement.

What you see in the log printing is not the sql statement, but the content is filled through the placeholder mode

The data here is of type int, we try to use String type data instead

result:

When #{} is replaced by ${}, execute it again. An error is reported 

Reason: ${} is a direct replacement string, what you enter is completely replaced

'${username}', no error will be reported, and there will be problems in SQL statements without single quotation marks

This can only guarantee that no error will be reported, but there will be security problems

For example, in the login scenario: sql injection problem

 In order to return only one piece of data, first delete the data in the table

mysql> select*from userinfo;
+----+----------+----------+-------+---------------------+---------------------+-------+
| id | username | password | photo | createtime          | updatetime          | state |
+----+----------+----------+-------+---------------------+---------------------+-------+
|  2 | lisi     | lisi     |       | 2022-12-06 17:10:48 | 2022-12-06 18:10:48 |     1 |
+----+----------+----------+-------+---------------------+---------------------+-------+
1 row in set (0.00 sec)

normal behavior: 

 

The attacker sends the following input:

mysql> select 1 = '1';
+---------+
| 1 = '1' |
+---------+
|       1 |
+---------+
1 row in set (0.00 sec)

Then the SQL query statement will be replaced with:

SELECT * FROM users WHERE username = '' or '1'='1' AND password = '' or '1'='1'

Use non-existing username and non-existing password to find user information

This is the sql injection attack when using ${key}.

Replace ${key} with #{key}

placeholder, there will be no security issues 

${} also has advantages in certain scenarios

At this time, using #{key} will be incorrectly parsed as a string: 

SELECT * FROM userinfo ORDER BY id "desc"

Even if the value of the ord parameter is set to ASC or DESC, the string cannot be replaced correctly

The SQL statement needs to be changed to the following form for direct replacement:

SELECT * FROM userinfo ORDER BY id ${ord}

Summarize:

1. ${key} is mainly used for string replacement , which can easily replace parameters with SQL statements

        When using ${key}, you need to pay attention to security issues, and you should avoid potential SQL injection attacks

2. #{key} is mainly used for preprocessing SQL statements, which can effectively prevent SQL injection attacks

#{key} underlying principle:

In MyBatis, #{} uses PreparedStatement in the underlying implementation for parameter preprocessing and type conversion.

When MyBatis executes a SQL statement, it will replace the #{} placeholder in the SQL statement with a JDBC Placeholder (such as ?), and then generate a precompiled SQL statement. This precompiled SQL statement will be passed to DriverManager, and a PreparedStatement object will be created by DriverManager.

Then, MyBatis will set the value of the query parameter to the parameter position of the PreparedStatement according to the JDBC specification, then execute the query operation of the PreparedStatement object, and finally map the query result into a Java object and return it to the caller.

The use of prepared statements can improve the efficiency of SQL execution, avoid security issues such as SQL injection, and can automatically perform type conversion, allowing developers to focus more on the implementation of business logic.

It should be noted that SQL statements cannot be dynamically constructed at runtime because prepared statements must be variable-bound between compilation and execution. If you need to dynamically build SQL statements at runtime, you need to use ${} to implement string replacement, and you need to pay attention to preventing SQL injection attacks.

PreparedStatement is an interface provided by JDBC to improve the performance and security of executing SQL. Features of PreparedStatement:

  1. Pre-compilation: When the PreparedStatement object is created, the SQL statement will be compiled into an executable statement, which can improve the execution efficiency of SQL.

  2. Parameter binding: PreparedStatement can set parameters before execution, and placeholders (?) or named parameters (:param) can be used to replace actual parameter values, thereby avoiding SQL injection attacks.

  3. Batch processing: PreparedStatement supports batch processing, and can submit multiple SQL statements to the database for execution at one time, thereby improving the efficiency of database processing.

  4. Prepared statement cache: Precompiled statements can be cached. When the same SQL statement is executed again, the compiled statement can be directly obtained from the cache, avoiding recompiling SQL every time, thereby improving SQL execution efficiency.

change Password 

run unit tests

modified successfully 

mysql> select*from userinfo ;
+----+----------+----------+-------+---------------------+---------------------+-------+
| id | username | password | photo | createtime          | updatetime          | state |
+----+----------+----------+-------+---------------------+---------------------+-------+
|  2 | lisi     | 123456   |       | 2022-12-06 17:10:48 | 2022-12-06 18:10:48 |     1 |
+----+----------+----------+-------+---------------------+---------------------+-------+
1 row in set (0.00 sec)

 In the case of unit testing, we are unwilling to change the database, that is, not to pollute the database

By default, changes to the database are persisted

The @Transactional annotation is used here

Execute normally, but do not pollute the database, start the transaction during execution, and perform a rollback operation after execution, so that the database will not be polluted

Look at the database, there is no change, indicating that a rollback has been performed... and the program has been successfully verified, and the modification is returned: 1

mysql> select*from userinfo ;
+----+----------+----------+-------+---------------------+---------------------+-------+
| id | username | password | photo | createtime          | updatetime          | state |
+----+----------+----------+-------+---------------------+---------------------+-------+
|  2 | lisi     | 123456   |       | 2022-12-06 17:10:48 | 2022-12-06 18:10:48 |     1 |
+----+----------+----------+-------+---------------------+---------------------+-------+
1 row in set (0.00 sec)

 Come down to learn the delete operation

//删除用户,返回受影响行数
    int deleteById(@Param("id")Integer id);


<delete id="deleteById">
<!--        默认返回受影响的行数-->
        delete from userinfo where id = #{id}
    </delete>

@Transactional
    @Test
    void deleteById() {
        int result = userMapper.deleteById(2);
        System.out.println("删除: "+result);
    }

Results of the

Because the transaction is set, the test is rolled back after the test is completed, and the database will not be polluted

It is common to add modules, here we do not roll back, let the data be inserted into the database

//添加用户
    int addUser(UserEntity user);


<insert id="addUser">
        <!--        默认返回受影响的行数-->
        insert into userinfo(username,password) values(#{username},#{password})
    </insert>


@Test
    void addUser() {
        UserEntity user = new UserEntity();
        user.setUsername("zhangsan");
        user.setPassword("123456");
        int result = userMapper.addUser(user);
        System.out.println(result);
    }

The execution result returns the number of affected rows: 1. A new piece of data is added to the database

==>  Preparing: insert into userinfo(username,password) values(?,?)
==> Parameters: zhangsan(String), 123456(String)
<==    Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3e4e4c1]
1
mysql> select*from userinfo ;
+----+----------+----------+-------+---------------------+---------------------+-------+
| id | username | password | photo | createtime          | updatetime          | state |
+----+----------+----------+-------+---------------------+---------------------+-------+
|  2 | lisi     | 123456   |       | 2022-12-06 17:10:48 | 2022-12-06 18:10:48 |     1 |
|  3 | zhangsan | 123456   |       | 2023-05-18 17:21:49 | 2023-05-18 17:21:49 |     1 |
+----+----------+----------+-------+---------------------+---------------------+-------+
2 rows in set (0.00 sec)

Add user to get id

//添加用户得到ID
    int addUserGetId(UserEntity user);


<insert id="addUserGetId" useGeneratedKeys="true" keyProperty="id">
        <!--返回受影响的行数  和  id-->
        <!--useGeneratedKeys="true"keyProperty="id"是否自动生成id,拿到id放到id字段中-->

        insert into userinfo(username,password) values(#{username},#{password})
    </insert>


@Test
    void addUserGetId() {
        UserEntity user = new UserEntity();
        user.setUsername("wangwu");
        user.setPassword("123456");
        int result = userMapper.addUserGetId(user);
        System.out.println("ID: "+user.getId());
    }

Results of the

JDBC Connection [HikariProxyConnection@1775046789 wrapping com.mysql.cj.jdbc.ConnectionImpl@60bb7995] will not be managed by Spring
==>  Preparing: insert into userinfo(username,password) values(?,?)
==> Parameters: wangwu(String), 123456(String)
<==    Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@ef60710]
ID: 4
mysql> select*from userinfo ;
+----+----------+----------+-------+---------------------+---------------------+-------+
| id | username | password | photo | createtime          | updatetime          | state |
+----+----------+----------+-------+---------------------+---------------------+-------+
|  2 | lisi     | 123456   |       | 2022-12-06 17:10:48 | 2022-12-06 18:10:48 |     1 |
|  3 | zhangsan | 123456   |       | 2023-05-18 17:21:49 | 2023-05-18 17:21:49 |     1 |
|  4 | wangwu   | 123456   |       | 2023-05-18 17:36:28 | 2023-05-18 17:36:28 |     1 |
+----+----------+----------+-------+---------------------+---------------------+-------+
3 rows in set (0.00 sec)

Fuzzy query-concat

 The query result using #{key} method will report an error

Because the passed parameter is a string type, it will be parsed as a string by #{}, so '' will be automatically added, then the placeholder will become

'%'li'%'

mysql> select*from userinfo where username like '%'li'%';
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'li'%'' at line 1

Need to use concat to splicing

mysql>  select concat ('%','li','%');
+-----------------------+
| concat ('%','li','%') |
+-----------------------+
| %li%                  |
+-----------------------+
1 row in set (0.00 sec)

Results of the 

JDBC Connection [HikariProxyConnection@1622899093 wrapping com.mysql.cj.jdbc.ConnectionImpl@40fa8766] will not be managed by Spring
==>  Preparing: select * from userinfo where username like concat('%',?,'%')
==> Parameters: li(String)
<==    Columns: id, username, password, photo, createtime, updatetime, state
<==        Row: 2, lisi, 123456, , 2022-12-06 17:10:48, 2022-12-06 18:10:48, 1
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@56399b9e]
UserEntity(id=2, username=lisi, password=123456, photo=, createtime=2022-12-06T17:10:48, updatetime=2022-12-06T18:10:48, state=1)

 Wrong fuzzy match query can lead to index invalidation

1.like 'zhang%'

2.like '%zhang'

3.like '%zhang%'

Only the first type of query will use the index, and the latter two will not use the index, and the index will fail

Due to the different code styles of DBAs and back-end developers, incompatibility issues may arise, such as

Then we execute this unit test

We found that JDBC was executed successfully, but the value of pwd is empty because the password cannot be mapped to pwd

At this time, resultType="com.example.demo.entity.UserEntity" is invalid, because the fields in the table and the attributes of the class are different, and it cannot be directly mapped one-to-one.

Solution --<resultMap>

<resultMap> is a label used in MyBatis to map query result sets. It can solve the following two problems:

  1. Solve the problem of inconsistency between column names and attribute names: In the database, some column names may not conform to the naming conventions of attributes in Java objects. At this time, you can map the column names in the query result set to the attributes in Java objects The name is mapped so that the result set and the object can be correctly matched.

  2. Solve the problem of multi-table association query: when performing multi-table association query, the query result set usually contains columns in multiple tables. At this time, <resultMap> can be used to map the columns in different tables to different Java object properties , so as to complete the mapping transformation of the result set.

The first step is to set the mapping relationship

    <resultMap id="BaseMap" type="com.example.demo.entity.UserEntity">
    <!--设置主键   property:属性,类中的  column:字段,数据库表中的     -->
        <id property="id" column="id"></id>
    <!--设置普通参数-->
        <result property="pwd" column="password"></result>
        <result property="username" column="username"></result>
        <result property="createtime" column="createtime"></result>
        <result property="photo" column="photo"></result>
        <result property="updatetime" column="updatetime"></result>
        <result property="state" column="state"></result>
    </resultMap>

The second step, modify the return type

    <select id="getUserById" resultMap="BaseMap">
        select * from userinfo where id = #{uid}
    </select>

Results of the

There is also a relatively simple way, setting the rename in the sql statement can also be successfully mapped

<select id="getUserByName" resultType="com.example.demo.entity.UserEntity">
        select id,username,password as pwd from userinfo where username = '${username}'
    </select>

Multi-table joint query

mysql> update userinfo set id = 1 where username = 'lisi';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
文章信息表
mysql> select*from articleinfo;
+----+-------+----------+---------------------+---------------------+-----+--------+-------+
| id | title | content  | createtime          | updatetime          | uid | rcount | state |
+----+-------+----------+---------------------+---------------------+-----+--------+-------+
|  1 | Java  | Java正文 | 2023-05-15 09:12:59 | 2023-05-15 09:12:59 |   1 |      1 |     1 |
+----+-------+----------+---------------------+---------------------+-----+--------+-------+
1 row in set (0.01 sec)

In order to correspond, change the id of lisi to 1

mysql> update userinfo set id = 1 where username = 'lisi';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select*from userinfo;
+----+----------+----------+-------+---------------------+---------------------+-------+
| id | username | password | photo | createtime          | updatetime          | state |
+----+----------+----------+-------+---------------------+---------------------+-------+
|  1 | lisi     | 123456   |       | 2022-12-06 17:10:48 | 2022-12-06 18:10:48 |     1 |
|  3 | zhangsan | 123456   |       | 2023-05-18 17:21:49 | 2023-05-18 17:21:49 |     1 |
|  4 | wangwu   | 123456   |       | 2023-05-18 17:36:28 | 2023-05-18 17:36:28 |     1 |
+----+----------+----------+-------+---------------------+---------------------+-------+
3 rows in set (0.00 sec)

Create an article table entity class

@Data
public class ArticleInfo {
    private int id;
    private String title;
    private String content;
    private LocalDateTime createtime;
    private LocalDateTime updatrtime;
    private int uid;
    private int rcount;
    private int state;
}

extension class

package com.example.demo.entity.vo;
import com.example.demo.entity.ArticleInfo;
import lombok.Data;
@Data
public class ArticleInfoVO extends ArticleInfo {
    private String username;
}

Create an interface in Mapper

package com.example.demo.mapper;

import com.example.demo.entity.vo.ArticleInfoVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

@Mapper
public interface ArticleMapper {
    //查询文章详情
    ArticleInfoVO getDetail(@Param("id")Integer id);
}

Create an xml file under the mybatis package

<?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.ArticleMapper">
    <select id="getDetail" resultType="com.example.demo.entity.vo.ArticleInfoVO">
        select a.*,u.username from articleinfo a
        left join userinfo u on u.id = a.uid
        where a.id = #{id}
    </select>
</mapper>

Create test class

@SpringBootTest
class ArticleMapperTest {

    @Autowired
    private ArticleMapper articleMapper;
    @Test
    void getDetail() {
        ArticleInfoVO articleInfoVO = articleMapper.getDetail(1);
        System.out.println(articleInfoVO);
    }
}

Execute unit tests

The JDBC execution is correct, but only the username is returned, and the properties of the parent class are not queried

In fact, there is a problem with lombok, and the properties of the parent class are not included when printing.

Solution: Manually set toString

public class ArticleInfoVO extends ArticleInfo {
    private String username;

    @Override
    public String toString() {
        return "ArticleInfoVO{" +
                "username='" + username + '\'' +
                "} " + super.toString();
    }
}

view bytecode

 execute again 

JDBC Connection [HikariProxyConnection@166022233 wrapping com.mysql.cj.jdbc.ConnectionImpl@5dbb50f3] will not be managed by Spring
==>  Preparing: select a.*,u.username from articleinfo a left join userinfo u on u.id = a.uid where a.id = ?
==> Parameters: 1(Integer)
<==    Columns: id, title, content, createtime, updatetime, uid, rcount, state, username
<==        Row: 1, Java, <<BLOB>>, 2023-05-15 09:12:59, 2023-05-15 09:12:59, 1, 1, 1, lisi
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3662bdff]
ArticleInfoVO{username='lisi'} ArticleInfo(id=1, title=Java, content=Java正文, createtime=2023-05-15T09:12:59, updatrtime=null, uid=1, rcount=1, state=1)

Query all articles of a user

First insert an article record

mysql> select*from articleinfo;
+----+-------+-----------+---------------------+---------------------+-----+--------+-------+
| id | title | content   | createtime          | updatetime          | uid | rcount | state |
+----+-------+-----------+---------------------+---------------------+-----+--------+-------+
|  1 | Java  | Java正文  | 2023-05-15 09:12:59 | 2023-05-15 09:12:59 |   1 |      1 |     1 |
|  2 | mysql | mysql正文 | 2023-05-19 11:14:49 | 2023-05-19 11:14:49 |   1 |      1 |     1 |
+----+-------+-----------+---------------------+---------------------+-----+--------+-------+
2 rows in set (0.00 sec)

other code

//查询一个用户所有文章
    List<ArticleInfoVO> getListByUid(@Param("uid")Integer uid);

<select id="getListByUid" resultType="com.example.demo.entity.vo.ArticleInfoVO">
        select a.*,u.username from articleinfo a
        left join userinfo u on u.id = a.uid
        where a.uid = #{uid}
    </select>

@Test
    void getListByUid() {
        Integer uid =1;
        List<ArticleInfoVO> list = articleMapper.getListByUid(uid);
        //使用多线程的方式,顺序可能会不同
        list.stream().parallel().forEach(System.out::println);
    }

implement

Guess you like

Origin blog.csdn.net/chenchenchencl/article/details/130676703