Initial MyBatis, the word w will take you to solve MyBatis

Table of contents

1. What is mybatis

The concept of mybatis

Advantages of mybatis

2. Compared with JDBC, what does the framework do for us?

3. Practice the program containing mybatis

1. Create a project

2. Modify the configuration file

3. Prepare database related content

4. Prepare the corresponding xml file and the corresponding mapper interface

5. Define the corresponding sql statement

6. Prepare the corresponding java class

4. Placeholder

Five. Multi-table query

one-to-many mapping

We introduce the specific logical relationship between front-end and back-end interactions:

One-to-one mapping:

 one-to-many mapping

Six. Dynamic sql


1. What is mybatis

The concept of mybatis

MyBatis is an excellent persistence layer framework that supports custom SQL, stored procedures, and advanced mapping. 1. Mybatis is a semi-ORM (object-relational mapping) framework. The bottom layer encapsulates JDBC. Programmers only need to pay attention to the SQL statement itself during development, and do not need to spend energy to deal with complicated processes such as loading drivers, creating connections, and creating statements. . Allows programmers to spend more energy on business development. In addition, programmers directly write original ecological sql, strictly control sql execution performance, and have high flexibility. 2. MyBatis can use simple XML files or annotations to configure and map native information, and map POJOs to records in the database, avoiding almost all JDBC codes and manually setting parameters and obtaining result sets. 3. Configure the various statements to be executed through xml files or annotations, and generate the final executed sql statement through mapping between the java object and the dynamic parameters of sql in the statement, and finally the mybatis framework executes sql and maps the result to java object and return it. (The process from executing sql to returning result).

Advantages of mybatis

1. Mybatis is programmed based on sql. By writing sql statements into the xml file, it will not have any impact on the design of our current application and database; at the same time, writing sql into the xml file removes the coupling between sql and program code , which is convenient for the unified management of the program, and provides xml tags at the same time, allowing the realization of dynamic sql, thus improving the reusability of sql

2. Compared with JDBC, the amount of code is reduced by more than 50%, eliminating a lot of redundant code, so that we can focus more on the design of SQL

3. Provide mapping tags, provide ORM field mapping of java objects and database fields.

4. Good compatibility with various databases (because MyBatis uses JDBC to connect to the database, so as long as the JDBC-supported database MyBatis supports it)

5. Can be well integrated with Spring;

2. Compared with JDBC, what does the framework do for us?

By comparing the code of JDBC for database operations, we compare JDBC and MyBatis

 public static Blog selectById(Long id){
        //检查id的有效性
        if (LongUtil.isValid(id)){
            return null;
        }
        Connection connection=null;
        PreparedStatement statement=null;
        ResultSet resultSet=null;


        //数据有效,进行数据查询
        //建立连接
        try {
            connection = DBUtil.getConnection();
            //定义sql语句
            String sql="select id,title,content,createTime,userId from blog where id=?";
            //创建执行对象并填充参数
            statement = connection.prepareStatement(sql);
            //填充参数
            statement.setLong(1,id);
            //执行语句
            resultSet = statement.executeQuery();
            //处理运行结果
            if (resultSet.next()){
                //创建新对象返回
                Blog blog = new Blog();
                blog.setId(resultSet.getLong("id"));
                blog.setTitle(resultSet.getString("title"));
                blog.setContent(resultSet.getString("content"));
                blog.setCreateTime(resultSet.getTimestamp("createTime"));
                blog.setUserId(resultSet.getLong("userId"));
                return blog;

            }else {
                //如果结果为空
                return null;
            }


        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            //断开连接
            DBUtil.close(resultSet, statement, connection);
        }
    }

We can summarize the following seven steps from it: ① Establish connection ② Define sql statement ③ Pre-execute ④ Supplementary parameters ⑤ Execute sql statement ⑥ Return and process the result ⑦ Disconnect

Compared with it, mybatis is much simplified. By setting the relevant parameters of the database connection in the configuration file, there is no need to manually call the api to connect to the database, nor to manually call the api to execute the sql statement (inner api). The processing result is directly mapped to the java class through the return value of the method corresponding to the mapper interface, and there is no need to manually disconnect the connection with the database. To sum up: we only need to perform the mapping operation and Writing sql statements greatly improves the efficiency of our code development, and also reduces the amount of code to a large extent.

In addition, we only identified the namespace and method mapping in the interface of the mapper and the corresponding xml file, and the actual mapping work is done by the mybatis framework for us (the mybatis framework encapsulates jdbc and passes Other configurations do some work automatically)

3. Practice the program containing mybatis

1. Create a project

 choose to depend

Configure codeset

 

 Disable JMX and configure hot deployment

2. Modify the configuration file

If we do not configure the corresponding driver source, url, user name and password when the project starts, the following error will be reported:

The reason is as follows: springboot introduces the mybatis framework dependency package, and some resources will be loaded by default when the project starts. If these resources cannot be found in the configuration file, an error will be reported 

# 设置mysql数据源驱动
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 设置url
spring.datasource.url=jdbc:mysql://localhost:3307/java23characterEncoding=utf8&useSSL=false
# 设置用户名
spring.datasource.username=root
# 设置密码
spring.datasource.password=abc123
# 定义mapper文件的配置
mybatis.mapper-locations=classpath:mapper/**Mapper.xml

3. Prepare database related content

The table creation statement is as follows:

-- 创建数据库
drop database if exists java23;
create database java23 DEFAULT CHARACTER SET utf8;

-- 使用数据数据
use java23;

-- 创建表[用户表]
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 datetime default now(),
 updatetime datetime,
 `state` int default 1
);

-- 创建文章表
drop table if exists  articleinfo;
create table articleinfo(
                            id int primary key auto_increment,
                            title varchar(100) not null,
                            content text not null,
                            createtime datetime default now(),
                            updatetime datetime,
                            uid int not null,
                            rcount int not null default 1,
                            `state` int default 1
);

-- 创建视频表
drop table if exists videoinfo;
create table videoinfo(
                          vid int primary key,
                          `title` varchar(250),
                          `url` varchar(1000),
                          createtime datetime default now(),
                          updatetime datetime,
                          uid int
);

-- 添加一个用户信息
INSERT INTO `userinfo` (`id`, `username`, `password`, `photo`, `createtime`, `updatetime`, `state`) VALUES
    (1, 'admin', 'admin', '', '2021-12-06 17:10:48', '2021-12-06 17:10:48', 1);
INSERT INTO `userinfo` (`id`, `username`, `password`, `photo`, `createtime`, `updatetime`, `state`) VALUES
    (2, 'abc', '123', '', '2021-12-06 17:10:48', '2021-12-06 17:10:48', 1);

-- 文章添加测试数据
insert into articleinfo(title,content,uid,createtime) values('Java','Java正文',1,'2023-05-05 19:09');
insert into articleinfo(title,content,uid,createtime) values('C++','C++正文',1,'2023-05-04 19:09');
insert into articleinfo(title,content,uid,createtime) values('#C','#C正文',1,'2023-05-03 19:09');
insert into articleinfo(title,content,uid,createtime) values('Python','Python正文',2,'2023-05-03 19:09');

4. Prepare the corresponding xml file and the corresponding mapper interface

Set mapper interface

source code:

import com.ljl.mybatis_study.model.ArticleInfo;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

/**
 * @author tongchen
 * @create 2023-05-05 15:15
 */
@Mapper
public interface ArticleMapper {
    List<ArticleInfo> listAll();
    List<ArticleInfo >listOne(Integer id);
    Integer add(ArticleInfo info);
    Integer del(Integer id);
    List<ArticleInfo>order(String column ,String orders);
    List<ArticleInfo>likeName(String name);

}

 Set the corresponding xml file

The source code is as follows:

<?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.ljl.mybatis_study.mapper.ArticleMapper">
    <select id="listAll" resultType="com.ljl.mybatis_study.model.ArticleInfo">
        select *from articleinfo
    </select>


</mapper>

5. Define the corresponding sql statement

Write the corresponding sql statement in the corresponding label

Here is to write the corresponding sql statement in the select tag

select *from articleinfo

6. Prepare the corresponding java class

The select statement returns a specific sql object. After being transmitted from the database in the form of a string in our program, it needs to be mapped to a specific java class, and this class needs to correspond to the specific entity class in our program.

We give the source code of the entity class:

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.util.Date;

/**
 * @author tongchen
 * @create 2023-05-05 15:24
 */
@Setter
@Getter
@ToString
public class ArticleInfo {
    private Integer id;
    private String title;
    private String content;
    private Date createtime;
    private Date updatetime;
    private Integer uid;
    private Integer rcount;
    private Integer state;
    private Userinfo userinfo;
}

4. Placeholder

There are two types of placeholders in mybatis: #{corresponding variable name} and ${corresponding variable name}: the difference between the two is as follows: #{} corresponds to a single quote in the specific sql statement, that is It is a 'variable name', and its characteristics also reflect its application scenario: storing a specific value in a variable. Its implementation principle is as follows: through jdbc preprocessing, the position corresponding to the variable name is first used? Make a placeholder, and then call preparedStatement.setxxx to replace it

The variable corresponding to ${} does not have single quotes in the sql statement, so its application scenarios are generally as follows: for example, order by variable name traversal order, its implementation principle is string splicing: but string splicing has a relatively serious problem Potential safety hazard: sql injection, and preprocessing can just solve this problem. The way of preprocessing to solve the problem is as follows: escape ''

Let's use the like statement as an example: 

Five. Multi-table query

In the process of front-end and back-end transmission, the mapping process from objects in sql to objects in java classes corresponds to the specific object types in java classes. In addition to the java class, there are other additional fields. How can we map from sql objects to java objects?

answer: Use resultMap (result mapping) : resultMap is the most powerful element of Mybatis, which can map complex data queried (such as querying data in several tables) to a result set. Use resultType for output mapping. Only when the queried column name is consistent with the attribute name in pojo (entity bean), the column can be successfully mapped. To put it simply, your database field and the field name in JavaBean must be the same to map successfully. So when the field names in our JavaBean are different from the database field names, or when multi-table queries are made, resultMap is generally used

The role and significance of resultMap:  The resultMap element is the most important and powerful element in MyBatis. It's what keeps you away from 90% of the JDBC code that needs to fetch data from a result set, and in some cases allows you to do things that JDBC doesn't support. In fact, writing something like the equivalent of union-mapping complex statements can span perhaps thousands of lines of code. The design of ResultMap is that simple statements do not require explicit result mapping, but many complex statements do need to describe their relationship.

The general fields of resultMap are as follows:

id Mapped primary key information
property Field names mapped to javaBean
column The column name corresponding to the query result returned by the sql statement

The basic result mapping is as follows:

 When mapping, it should be noted that the data variable names corresponding to the property and the column must correspond, that is, the property name in the java class and the variable name corresponding to the property should be exactly the same, and the column and the corresponding variable name and the field name corresponding to the object returned by the SQL statement should also be consistent.

Mapped class names do not match:


one-to-one mapping

The one-to-one mapping and one-to-many mapping performed here really involve multi-table queries

Here comes the association union:

  Union elements are used to handle "one-to-one" relationships. You need to specify the attributes of the mapped Java entity class, and the javaType of the attribute (usually MyBatis will recognize it by itself).

 type: the class in java corresponding to resultMap

In addition to the corresponding relationship of the corresponding attributes shown in the above example, an association is required to map additional relationships (extra fields other than the fields corresponding to a specific java class)

    <resultMap id="BaseMap" type="com.ljl.mybatis_study.model.ArticleInfo">
        <id column="id" property="id"/>
        <result column="title" property="title"/>
        <result column="content" property="content"/>
        <result column="createtime" property="createtime"/>
        <result column="updatetime" property="updatetime"/>
        <result column="uid" property="uid"/>
        <result column="rcount" property="rcount"/>
        <result column="state" property="state"/>
        <association property="userinfo" resultMap="UserMap" columnPrefix="u_"/>

    </resultMap>

In addition, you need to add corresponding fields to the main class corresponding to the return value type:

The source code is as follows:

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.util.Date;

/**
 * @author tongchen
 * @create 2023-05-05 15:24
 */
@Setter
@Getter
@ToString
public class ArticleInfo {
    private Integer id;
    private String title;
    private String content;
    private Date createtime;
    private Date updatetime;
    private Integer uid;
    private Integer rcount;
    private Integer state;
    private Userinfo userinfo;
}

one-to-many mapping

Since it is one-to-many, collection aggregation is introduced here:

  Aggregation elements are used to handle "one-to-many" relationships. It is necessary to specify the attribute of the mapped Java entity class, the javaType of the attribute (usually ArrayList); the type ofType (Java entity class) of the object in the list.

Similarly, type represents the java class corresponding to the resultmap

<resultMap id="UserMap" type="com.ljl.mybatis_study.model.Userinfo">
        <id column="id" property="id"/>
        <result column="username" property="username" />
        <result column="password" property="password" />
        <result column="photo" property="photo" />
        <result column="createtime" property="createtime" />
        <result column="updatetime" property="updatetime" />
        <result column="state" property="state" />
        <collection property="articleInfos" resultMap="BaseMap"
                    columnPrefix="a_"/>
    </resultMap>

We introduce the specific logical relationship between front-end and back-end interactions:

One-to-one mapping:
 

 one-to-many mapping

 

Six. Dynamic sql

<if> tag

Grammar rules: <if test="conditional statement">

The if tag is usually used in combination with the trim tag, and the dynamic sql statement conforms to the grammatical rules of SQL

Example:

 <insert id="dynamicInsert">
        insert into userinfo <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test="id!=null">
            id,
        </if>
        <if test="username!=null">
            username,
        </if>
        <if test="password!=null">
            password,
        </if>
        <if test="photo!=null">
            photo,
        </if>
    </trim>
            values
                <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test="id!=null">
            #{id},
        </if>
        <if test="username!=null">
            #{username},
        </if>
        <if test="password!=null">
            #{password},
        </if>
        <if test="photo!=null">
            #{photo},
        </if>
                </trim>
    </insert>

<trim> tag

Grammar rules:
 

prefix : Indicates the entire statement block, prefixed with the value of prefix
suffix : Indicates the entire statement block, with the value of suffix as the suffix
prefixOverrides : Indicates the prefix to be removed from the entire statement block
suffixOverrides : Indicates the suffix to be removed from the entire statement block
Function: add or delete the content of some sql statements, make the sql statements conform to the grammatical rules, and improve efficiency
 <insert id="dynamicInsert">
        insert into userinfo <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test="id!=null">
            id,
        </if>
        <if test="username!=null">
            username,
        </if>
        <if test="password!=null">
            password,
        </if>
        <if test="photo!=null">
            photo,
        </if>
    </trim>
            values
                <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test="id!=null">
            #{id},
        </if>
        <if test="username!=null">
            #{username},
        </if>
        <if test="password!=null">
            #{password},
        </if>
        <if test="photo!=null">
            #{photo},
        </if>
                </trim>
    </insert>

<where> tag

Conditionally limit the dynamic sql statement, and remove the first and symbol in the where condition

Functionally equivalent to:  <trim prefix="where" prefixOverrides="and">

Specific use:

 <select id="dynamicSelect" resultMap="UserMap">
        select *from userinfo
        <where>
            <if test="id!=null">
              and  id=#{id}
            </if>
            <if test="username!=null">
              and  username=#{username}
            </if>
        </where>
    </select>

<set> tag

It is used in the update statement in the sql statement, and the last comma can be removed

The set tag can also be replaced with <trim prefix="set" suffixOverrides=","> .

The specific use is as follows:

  <update id="dynamicUpdate">
        update userinfo
        <set >
            <if test="photo!=null">
                photo=#{photo},
            </if>
            <if test="username!=null">
                username=#{username},
            </if>
        </set>
            where id=#{id}
    </update>

<foreach> tag

Use this label when traversing the collection

  • collection : the collection in the bound method parameter, such as List , Set , Map or array object
  • item : each object when traversing
  • open : the string at the beginning of the statement block
  • close : the string at the end of the statement block
  • separator : the string for the interval between each traversal

For the elements traversed by foreach, it is generally divided into two types, the basic data type in the collection or its wrapper class, and the other is a custom data type. For storing basic data types in the collection, we generally need Add the @RequestParam annotation to the method parameter corresponding to the Controller layer. If the data that is not transmitted is processed as an ordinary element, an error will be reported. The error message is as follows: Request processing failed; nested exception is java.lang.IllegalStateException: No primary or single unique constructor found for interface java.util.List
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-5.3.27.jar:5.3.27]
at org.springframework.web .servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.27.jar:5.3.27]

i.e. there is no unique constructor

For our custom methods, we generally use the @RequestBody annotation. At this time, the data transmitted by the front end is usually of type json

We traverse a simple type and a complex type separately:
simple type:

complex type:

  <insert id="dynamicInsertMore">
    insert into userinfo (username ,password ,photo)
    values
    <foreach collection="list" item="userinfo"  separator=",">
        (#{userinfo.username},#{userinfo.password},#{userinfo.photo})
    </foreach>

Guess you like

Origin blog.csdn.net/m0_65431718/article/details/130506304