Collection! The most complete XML Mapping File tag analysis + example in MyBatis!

Posted by jamiel on Thu, 03 Feb 2022 01:47:34 +0100

preface

The strength of MyBatis lies in its mapper file, which is the magic of MyBatis. For any user of MyBatis, the mapping file of MyBatis must be mastered.

Mapper file label

One of Mapper provides nine top-level tags. We don't need to know about one that has expired. The other eight must be mastered. As long as we master the use of tags, we can use MyBatis like a duck to water. Next, let's analyze the use of these labels one by one.

select

Select is used to map query statements. It is the most used tag and the most complex tag. For example, the following is a simple use of the select tag:

<select id="listUserByUserName" parameterType="String" resultType="lwUser">
        select user_id,user_name from lw_user where user_name=#{userName}
</select>

Some secondary tags are provided in the select tag. All secondary tags are listed below:

<select
id="selectPerson"
parameterType="int"
parameterMap="deprecated"
resultType="hashmap"
resultMap="personResultMap"
flushCache="false"
useCache="true"
timeout="10000"
fetchSize="256"
statementType="PREPARED"
resultSetType="FORWARD_ONLY"
databaseId="mysql"
resultOrdered="false"
resultSets="xxx,xxx"
lang="">

id

Required label. If the unique identifier in the same namespace needs to be called by an external interface, it needs to be consistent with the method name in Mapper interface.

parameterType

Optional labels. The fully qualified name or alias of the parameter class. The above example indicates that the parameter we passed in is a String type (if you are not clear about the alias, you can click here). If this attribute is not written, MyBatis will default to unset when parsing the xml file, and then infer the parameter type according to the TypeHandler. If there are multiple parameters, it is recommended not to write this parameter, otherwise the parameter type conversion error may occur

parameterMap

This is an expired attribute and we won't discuss it.

resultType

Optional label. Note that the reason why it is not selected here is that resultType and resultMap cannot coexist. You can and can only select one of them. It is mainly used to define the fully qualified name or alias of an object that returns a result set. If the receiving parameter is a collection, the types that can be included in the collection are defined here, not the collection itself. For example, the writing method in the example is applicable to the following two statements in the Mapper interface:

LwUser listUserByUserName(@Param("userName") String userName);
List<LwUser> listUserByUserName(@Param("userName") String userName);

resultMap

Optional label. Note that the reason why it is not selected here is that resultType and resultMap cannot coexist. You can and can only select one of them. resultMap type result set mapping is the most powerful feature of MyBatis. We won't expand it here. There will be a separate article on MyBatis in two days. This attribute will be introduced separately when complex queries such as one-to-one and one to many are used. Those who are interested can pay attention to me first and pay attention to the following articles.

flushCache

Optional labels. When set to true, whenever a statement is called, the local cache and L2 cache will be emptied. The default value is false.

useCache

Optional labels. When set to true, the result of this statement will be cached by the secondary cache. The default value for select tag statements is true, and the default value for insert,delete,update and other statements is false.

timeout

Optional labels. This setting is the number of seconds the driver waits for the database to return the requested result before throwing an exception. The default value is unset.

fetchSize

Optional labels. This is an attempt to affect the number of result lines returned by the driver in each batch, which is equal to this setting value. The default value is unset. Note that this is just an attempt. If the fetchSize is set to 100000 and the database driver only supports up to 5w, only 5w data will be returned

statementType

Optional labels. You can choose one of state, PREPARED or CALLABLE, which will make MyBatis use statement, PreparedStatement or CallableStatement respectively. The default value is PREPARED, that is, use precompiled PreparedStatement statements.

resultSetType

Optional labels. You can select one of the following three types. The default is unset.

  • FORWARD_ONLY: only cursor forward access is allowed

  • SCROLL_SENSITIVE: the cursor is allowed to scroll in both directions, but the data will not be updated in time. That is, if the data in the database is modified, it will not be reflected in the resultSet

  • SCROLL_ Independent: allows the cursor to scroll in both directions. If the data in the database is modified, it will be updated to the resultSet in time

Some people may still not understand the above explanation. Let's take a look at a section of JDBC reading result set:

MyBatis just encapsulates these operations. The bottom layer is actually this operation. rs.next() cursor rolls forward. In fact, there is another rs.previous() that indicates that the cursor can roll back. So FORWARD_ONLY only allows you to roll forward, and the accessed data will free up memory, which can improve performance in some scenarios. The latter two allow two-way scrolling, so even if the accessed data, the memory cannot be released. The difference between the two is that one is sensitive to data and the other is not sensitive to data.

  • Not sensitive to data, that is, after we query the results, we will cache the whole result set in memory. If a piece of data has not been read (still in the while loop) and another thread has modified the data, when we read the data later, we will still read the data before modification.

  • Being sensitive to data means that when we query the result, we will only cache one rowid, not the whole data. If there is a piece of data that has not been read (still in the while loop) and another thread has modified the data, then when we read the data later, we will query the data according to the rowid, and the queried data is the latest data. However, it should be noted that when deleting, the data is still there, only marked. Therefore, if a piece of data is delete d, it cannot be reflected. Similarly, insert does not affect, because the queried data does not contain the rowid of the inserted data.

If the MVCC mechanism of MySQL's InnoDB engine is used, the data will certainly not be sensitive, because other transactions can't be seen even if the current transaction is changed.

databaseId

Optional labels.

resultOrdered

Optional labels. This setting applies only to nested result select statements. If true, it is assumed that nested result sets or groups are included. In this way, when a main result row is returned, there will be no reference to the previous result set. This makes it possible to get nested result sets without running out of memory. Default: false.

resultSets

Optional labels. This setting is only applicable to the case of multiple result sets. It will list the result sets returned after the statement is executed and give each result set a name, which is separated by commas.

lang

I haven't used custom language, so I won't introduce it

insert

Insert is used to map insert statements. The following are all secondary tags of an insert tag:

<insert
id="insertLwUser"
parameterType="lwUser"
parameterMap="deprecated"
flushCache="true"
statementType="PREPARED"
keyProperty=""
keyColumn=""
useGeneratedKeys=""
timeout="20"
databaseId="mysql"
lang="">

Some tags and select statements are repeated, so I won't repeat the introduction. I'll mainly focus on other tags.

useGeneratedKeys

Optional labels. When the configuration is true, MyBatis will use the getGeneratedKeys method of JDBC to retrieve the primary key generated inside the database (such as the auto increment field of relational database management systems such as MySQL and SQL Server). The default value is false.

keyProperty

Optional labels. If an attribute is uniquely marked, MyBatis will set its key value through the return value of getGeneratedKeys or through the selectKey sub element of the insert statement. The default value is unset. If you want to get more than one generated column, it can also be a comma separated list of attribute names

keyColumn

Set the column name in the table through the generated key value. This setting is only necessary in some databases (such as PostgreSQL). It needs to be set when the primary key column is not the first column in the table. If you want to get more than one generated column, it can also be a comma separated list of attribute names

Get self incrementing primary key

Get the self incrementing primary key. You can define an entity class through keyProperty mapping:

package com.lonelyWolf.mybatis.model;

public class UserAddress {
    private int id;
    private String address;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

Define a useraddressmapper Java interface:

package com.lonelyWolf.mybatis.mapper;

import com.lonelyWolf.mybatis.model.UserAddress;
import org.apache.ibatis.annotations.Param;

public interface UserAddressMapper {
    int insert(UserAddress userAddress);
}

Note: if there is only one parameter here, you can not use @ Param annotation, so you can directly use the attribute name in JavaBean in xml file. If @ Param annotation is used, it is as follows:

int insert(@Param("userAddress") UserAddress userAddress);

Then you can use #{userAddress. Attribute name} in the xml file to obtain the attributes in the JavaBean

Define a useraddressmapper XML Mapping file (keyProperty="id" indicates setting the value of the primary key to the property ID in the parameter UserAddress class):

<?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.lonelyWolf.mybatis.mapper.UserAddressMapper">

   <insert id="insert" parameterType="com.lonelyWolf.mybatis.model.UserAddress" useGeneratedKeys="true" keyProperty="id">
       insert into lw_user_address (address) values (#{address})
   </insert>
</mapper>

mybatis-config. To add a mapper mapping file configuration in XML:

<mappers>
        <mapper resource="com/lonelyWolf/mybatis/mapping/UserAddressMapper.xml"/>
    </mappers>

Then write a test class:

package com.lonelyWolf.mybatis;

import com.lonelyWolf.mybatis.mapper.UserAddressMapper;
import com.lonelyWolf.mybatis.model.UserAddress;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;

public class TestMyBatisInsert {
    public static void main(String[] args) throws IOException {
        String resource = "mybatis-config.xml";
        //Read mybatis config configuration file
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //Create SqlSessionFactory object
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //Create SqlSession object
        SqlSession session = sqlSessionFactory.openSession();

        try {
            UserAddress userAddress = new UserAddress();
            userAddress.setAddress("Shenzhen, Guangdong");
            UserAddressMapper userAddressMapper = session.getMapper(UserAddressMapper.class);
            int i = userAddressMapper.insert(userAddress);
            session.commit();
            System.out.println("Number of successful inserts:" + i);
            System.out.println("The primary key of the inserted data is:" + userAddress.getId());
        }finally {
            session.close();
        }
    }
}

Output result (successfully obtained the primary key of the inserted data):

Number of successful inserts: 1
 The primary key of the inserted data is: 1

Get custom columns through selectKey

If some databases do not support self incrementing primary keys, or if we want to insert a custom primary key without writing logic in the business code, we can obtain it through MyBatis's selectKey. UserAddressMapper. Create a new method in Java:

int insert2(UserAddress userAddress);

Then in useraddressmapper An insert2 statement is added in XML:

<insert id="insert2"  useGeneratedKeys="true" keyProperty="address">
    <selectKey keyProperty="address" resultType="String" order="BEFORE">
        select uuid() from lw_user_address
    </selectKey>
        insert into lw_user_address (address) values (#{address})
    </insert>

Then modify the test class:

try {
            UserAddress userAddress = new UserAddress();
            UserAddressMapper userAddressMapper = session.getMapper(UserAddressMapper.class);
            int i = userAddressMapper.insert2(userAddress);
            session.commit();
            System.out.println("Number of successful inserts:" + i);
            System.out.println("To insert data address For:" + userAddress.getAddress());
        }finally {
            session.close();
        }

The output results are as follows. We have successfully obtained our customized address:

Number of successful inserts: 1
 To insert data address Is: 097 dfc8b-f043-11ea-97c4-00163e12524a

The order attribute in the selectKey has two choices: BEFORE and AFTER.

  • BEFORE: means to execute the statement of selectKey first, then set the queried value to the corresponding attribute of JavaBean, and then execute the insert statement.

  • AFTER: it means that AFTER statement is executed first, then selectKey statement is executed, and the value obtained by selectKey is set to the property in JavaBean. In the above example, if it is changed to AFTER, the inserted address will be null, but there will be a value in the returned JavaBean attribute.

PS: the value returned in the selectKey can only have one piece of data. If there are multiple pieces of data that meet the conditions, an error will be reported. Therefore, it is generally used to generate the primary key to ensure uniqueness, or add conditions to the statements after the selectKey to ensure uniqueness

update

insert is used to map update statements. The following are all secondary tags of an undate tag:

<update
id="UpdateLwUser"
parameterType="lwUser"
parameterMap="deprecated"
flushCache="true"
statementType="PREPARED"
keyProperty=""
keyColumn=""
useGeneratedKeys=""
timeout="20"
databaseId="mysql"
lang="">

This label is basically the same as insert, so there is no need to explain it again.

delete

Delete is used to map delete statements. The following are all secondary tags of a delete tag:

<delete
id="insertLwUser"
parameterType="lwUser"
parameterMap="deprecated"
flushCache="true"
statementType="PREPARED"
timeout="20"
databaseId="mysql"
lang="">

The tags here are the same as insert and update except for the three tags useGeneratedKeys, keyProperty and keyColumn.

sql

This element can be used to define reusable SQL snippets that can be included in other statements. The following is the simplest example:

 <select id="selectUserAddress" resultType="com.lonelyWolf.mybatis.model.UserAddress">
        select <include refid="myCloumn"></include> from lw_user_address
    </select>

    <sql id="myCloumn" >
        id,address
    </sql>

If we need to define an association statement now, and the columns come from two different tables, how should we implement it? This can be achieved by setting parameters:

 <select id="selectUserAddress" resultType="com.lonelyWolf.mybatis.model.UserAddress">
        select
        <include refid="myCloumn1">
            <property name="prefix1" value="u"/>
            <property name="prefix2" value="j"/>
        </include>
        from lw_user u inner join  lw_user_job j on u.user_id=j.user_id
    </select>

    <sql id="myCloumn1" >
        ${prefix1}.user_id,${prefix2}.id
    </sql>

The printed sql statement is as follows:

select u.user_id,j.id from lw_user u inner join lw_user_job j on u.user_id=j.user_id

cache

MyBatis includes a very powerful query caching feature, which can be easily configured and customized. However, by default, only the L1 cache is enabled, that is, the local session cache. If you want to enable the L2 cache. Then you need to use the cache tag

<cache
type="com.lonelyWolf.xxx"
eviction="FIFO"
flushInterval="60000"
readOnly="true"
size="512"/>

PS: these attributes have default values, so they can be used directly under normal circumstances:

</cache>

For the default value, please continue to read....

type

If we have customized the cache, we can configure the fully qualified name or alias of the custom cache class here. If there is no custom cache, there is no need to configure the type attribute.

About the principles of caching and how to customize caching, there will be an article devoted to caching later. This article mainly introduces the use of tags, and will not involve too many underlying principles.

eviction

For cache recycling strategy, more in MyBatis provides the following strategies to choose from:

  • LRU: least recently used algorithm (default algorithm). Remove objects that have not been used for the longest time

  • FIFO: first in first out algorithm. Remove objects in the order they enter the cache

  • SOFT: SOFT reference. Remove objects based on garbage collector status and SOFT reference rules.

  • WEAK: WEAK reference. More actively remove objects based on garbage collector state and WEAK reference rules

flushInterval

Refresh interval in milliseconds. Can be set to any positive integer. The default is not set, that is, the cache will not be refreshed actively (it will be refreshed only when waiting for the sql to be executed).

readOnly

Read only. The property can be set to true or false. If set to true, the read-only cache returns the same example of the cache object to all callers because the cache cannot be modified. This can improve performance to some extent. The default is false, that is, the cache can be modified. When reading the cache, the copy of the cache object will be returned by serialization. Although it will be slower, it is safe. Therefore, it will be set to false by default to allow modification of the cache.

size

Number of references. The popular point is the number that can be cached. The default value is 1024. When the setting value is exceeded, the above algorithm will be used for coverage

cache-ref

If we have configured the cache in one Mapper and want to share it with other mappers, we can use the cache ref element to reference another cache in this case, so there is no need to configure it repeatedly. For example:

<cache-ref namespace="com.lonelyWolf.mybatis.mapper.UserMapper"/>

In this way, the current Mapper can share the same cache in the UserMapper file.

resultMap

When introducing the select tag above, it is mentioned that the return result of the select tag can use the resultMap, but once we use the resultMap, we must define a resultMap ourselves. As follows, we define a resultMap:

 <resultMap id="JobResultMap" type="lwUser">
        <result column="user_id" property="userId" jdbcType="VARCHAR" />
        <result column="user_name" property="userName" jdbcType="VARCHAR" /> 

In this case, the select statement can reference:

<select id="selectUserAndJob" resultMap="JobResultMap">
        select * from lw_user
    </select>

As you can see, resultMap can be defined freely, so it can accept very complex queries and return result sets.

parameterMap

This parameter has expired and will not be discussed. You can forget to have this parameter

summary

This paper mainly introduces the mapper. File in MyBatis The use of some tags in XML files can be regarded as the most complete analysis of XML Mapping file tags in MyBatis. Of course, this does not involve how to complete the spelling of dynamic sql statements. Dynamic sql is also a very important function point of MyBatis. However, considering that it will be very boring to write sql statements and the use of dynamic tags only through one article, so the mapping of dynamic sql will not be written through a separate article. Although this is the case, some relevant knowledge points will still be used to introduce the use of dynamic tags, For example, how to return one to many and many to many result sets in MyBatis will involve some tags, such as where,if,set,choose, etc. later, batch operation will be introduced, as well as the use of foreach and other tags.

Author: Twin lone wolf

last

Here comes the interview question document, with a lot of content, 485 pages!

Because there are too many contents in the notes, we can't show them all. Only some contents are intercepted below. Friends who want to get the full version of notes, Click here to get it for free after you like it

1111 interview questions for Java engineers

MyBatis 27 questions + ZooKeeper 25 questions + Dubbo 30 questions:

Elasticsearch 24 questions + Memcached + Redis 40 questions:

Spring 26 questions + micro service 27 questions + Linux 45 questions:

Java interview questions collection:

Batch operation will also involve the use of foreach and other labels.

Author: Twin lone wolf

last

Here comes the interview question document, with a lot of content, 485 pages!

Because there are too many contents in the notes, we can't show them all. Only some contents are intercepted below. Friends who want to get the full version of notes, Click here to get it for free after you like it

1111 interview questions for Java engineers

[external chain picture transferring... (img-t4pTFUsU-1623621674033)]

MyBatis 27 questions + ZooKeeper 25 questions + Dubbo 30 questions:

[external chain picture transferring... (img-Xe38iH4y-1623621674034)]

Elasticsearch 24 questions + Memcached + Redis 40 questions:

[external chain picture transferring... (IMG nmdyagjz-1623621674035)]

Spring 26 questions + micro service 27 questions + Linux 45 questions:

[external chain picture transferring... (IMG grehlwjf-1623621674036)]

Java interview questions collection:

Topics: Java Interview Programmer