In-depth MyBatis: A full understanding of the "mapper"

This article is a summary note of the book "MyBatis in simple terms: Technical Principles and Practice".

The previous article summarizes the configuration of MyBatis and explains each configuration item in detail. It mentions the mapper, which is the most powerful tool of MyBatis and the most used tool.

Through the mapper, data addition, deletion, modification and query operations can be easily performed. We abstract the key points of these operations: passing query parameters, assembling query conditions in various scenarios, associating queries, and mapping query results to Java Bean objects or collection, etc. In addition, the performance of data query can be improved by lazy loading and caching.

This article summarizes this idea. First, it lists the main elements of the mapper, the configuration items and functions provided by each element, and then focuses on parameters, result mapping, lazy loading, caching, dynamic SQL and other functions.

The main elements of the mapper

The mapper is composed of a Java interface and an XML file (or annotation). The Java interface mainly defines the caller interface. The XML file is the core file for configuring the mapper, including the following elements:

  • select query statement, you can customize the parameters and return the result set;
  • insert Insert statement, return an integer, indicating the number of inserted bars;
  • update update statement, return an integer, indicating the number of updates;
  • delete Delete statement, return an integer, indicating the number of deleted items;
  • sql allows to define a part of SQL and then refer to it in various places;
  • resultMap is used to describe loading objects from the database result set, and can also configure associations;
  • cache cache configuration for the given namespace;

Add, delete, modify, check operations

find

Before executing the select statement, you need to define parameters. After execution, it also provides powerful mapping rules or automatic mapping to bind the returned result set to the java bean.

The select element has many configuration items, which are briefly described below:

  • paramterType: the incoming parameter type, which can be basic type, map, custom java bean;
  • resultType: the returned result type, which can be a basic type or a custom java bean;
  • resultMap: It is the most complex element, and can configure mapping rules, cascades, typeHandler, etc., and cannot exist at the same time as ResultType;
  • flushCache: After calling SQL, whether to clear the local cache and second-level cache queried before, mainly used to update the cache, the default is false;
  • useCache: the switch to start the second-level cache, only the first-level cache will be enabled by default;
  • timeout: Set the timeout parameter, and an exception will be thrown when it times out, the unit is seconds;
  • fetchSize: The total number of records to be obtained is set;

For example, to obtain user information based on the Mi Chat number:

<select id="findByMiliao" parameterType="string" resultType="User">
        select
        u.*
        from mxt_user u
        where u.miliao=#{miliao}
</select>

When the previous article introduced configuration, there is a setting item autoMappingBehavior, which defaults to automatic mapping of result sets that do not define nested result set mapping; there is also a setting item mapUnderscoreToCamelCase, when set to true, it will automatically map the database fields named with "underscore". name, which is automatically mapped to a POJO named in "CamelCase".

When passing multiple parameters, there are 3 ways:

  • Use the Map parameter;
  • Use annotations to pass;
  • use java beans;

Annotations are used as follows:

public List<Role> findRoleByNameAndNote(@Param("roleName") String rolename,
@Param("note") String note);

Using Map to pass parameters will lead to the loss of business readability, which will lead to inconvenient expansion and maintenance in the future. It is not recommended; if the number of parameters is <= 5, it is recommended to use annotations, because too many parameters will bring difficulties to the caller; If the number of parameters is greater than 5, it is recommended to use the JavaBean method;

Use resultMap to map the result set, which will be introduced separately later.

insert

Most of the attributes and select are the same, let's say the next 3 different attributes:

  • keyProperty: Specify which column is the primary key, if it is a joint primary key, it can be separated by commas;
  • keyColumn: Specifies which column is the primary key, which cannot be shared with keyProperty;
  • useGeneratedKeys: Whether to use automatic growth, the default is false;

When useGeneratedKeys is set to true, the id value of the Java Bean will be backfilled when inserting, and the primary key value can be obtained through the returned object.

If you want to set the value of the primary key according to some special relationship, you can use the selectKey tag in the insert tag. For example, if there is no record in t_role, you need to set it to 1, otherwise, take the maximum id and add 2:

<insert id="insertRole" useGeneratedKeys="true" keyProperty="id" >
    <selectKey keyProperty="id" resultType="int" order="before">
        select if(max(id) is null,1,max(id)+2) as newId from t_role
    </selectKey> 
</insert>
update和delete

It's relatively simple, so I won't go into too much detail.

parameter

Parameter passing has been introduced above, and you can specify the type of parameters to let the corresponding typeHandler handle them.

#{age , javaType=int , jdbcType=NUMERIC }

You can also set the storage precision for some numeric parameters.

#{price, javaType=double , jdbcType=NUMERIC , numericScale=2 }

Usually a string is passed, and the parameter #{name} is set. In most cases, a precompiled statement will be created, but sometimes the SQL statement itself is passed, not the required parameter, which can be represented by the $ symbol, such as passing parameter columns For "col1,col2,col3", it can be written as the following statement:

select ${columns} from t_tablename

But pay attention to the security of SQL to prevent SQL injection.

sql element

definition:

<sql id="role_columns">
    id,role_name,note
</sql>

use:

<include refid="role_columns">
    <property name="prefix" value="r" />
</include>

result mapping

Element introduction

resultMap is the most complex element in MyBatis. Its function is to define mapping rules, cascaded updates, and custom type converters.

Consists of the following elements:

<resultMap>
    <constructor> <!-- 配置构造方法 -->
        <idArg/>
        <arg/>
    </constructor>
    <id/> <!--指明哪一列是主键-->
    <result/> <!--配置映射规则-->
    <association/> <!--一对一-->
    <collection/> <!--一对多-->
    <discriminator> <!--鉴别器级联-->
        <case/>
    </discriminator>
</resultMap>

For some entities, there is no construction method without parameters, you need to use the constructor to configure the construction method with parameters:

<resultMap id="role" type="com.xiaomi.kfs.mcc.core.domain.Role">
    <constructor>
        <idArg column="id" javaType="int"/>
        <arg column="role_name" javaType="string"/>
    </constructor>
</resultMap>

id indicates the primary key column, and result configures the mapping rules for database fields and POJO attributes:

<resultMap id="role" type="com.xiaomi.kfs.mcc.core.domain.Role">
    <id property="id" column="id" />
    <result property="roleName" column="role_name" />
    <result property="note" column="note" />
</resultMap>

Association and collection are used to configure cascading relationships, which are one-to-one and one-to-many. In practice, many-to-many relationships are not used much. Because of their complexity, one-to-many relationships are used to decompose them into two-way relationships. .

The discriminator is used in such a scenario: for example, when we go to a physical examination, the physical examination items for men and women are different. It is unreasonable to ask men to check the gynecology item. The discriminator can return different objects according to gender.

There are many configurations of cascading relationships, which will not be demonstrated here. You can check the documentation for more information.

lazy loading

The advantage of cascading is that it can easily obtain data, but sometimes it is not necessary to obtain all data, which will execute several more SQLs and reduce performance. In order to solve this problem, lazy loading needs to be used. Send SQL to retrieve data.

There are two global parameters lazyLoadingEnabled and aggressiveLazyLoading in the configuration of MyBatis. The first one means whether to enable the lazy loading function, and the second one means calling any lazy loading property, which will make the lazy loading object fully loaded. Otherwise it will only be loaded on demand.

Then understand the aggressiveLazyLoading property. For example, the associated object of the student object is as follows:

In-depth MyBatis: A full understanding of the "mapper"

When accessing student information, the health status will also be found according to the discriminator; when accessing course grades, the student ID information will also be found, because by default, MyBatis is lazy loaded by level . But this is not what we need, and we don't want to load the student ID information when accessing the grades. We can set aggressiveLazyLoading to false to delay loading data as needed.

The above two attributes are global settings, and the attribute value fetchType can also be added to the association and collection elements. It has two values ​​eager and lazy.

cache

When the configuration cache is not displayed, only the first-level cache is enabled. The first-level cache is relative to the same SqlSession. When the parameters and SQL are exactly the same, using the same SqlSession object to call the same Mapper method will only Execute SQL once.

If it is a different SqlSession object, because different SqlSessions are isolated from each other, even if the same Mapper, parameters and methods are used, SQL will be sent to the database again for execution.

The second-level cache is at the SqlSessionFactory level and needs to be displayed and configured. When implementing the second-level cache, POJOs must be serializable, and only simple configuration is required:

<cache />

Many of these settings are default, and the following properties can be configured:

  • eviction: Represents the cache recovery strategy. The optional values ​​are LRU least used, FIFO first in first out, SOFT soft reference, and WEAK weak reference;
  • flushInterval: refresh interval, in milliseconds, if not configured, the cache will be refreshed when SQL is executed;
  • size: The number of references, which represents the maximum number of objects that the cache can store. It should not be set too large, as it will lead to memory overflow;
  • readOnly: read-only, meaning that the cached data can only be read and cannot be modified;

On large servers, a dedicated cache server may be used, such as Redis cache, which can be easily implemented by implementing the org.apache.ibatis.cache.Cache interface:

public interface Cache {
    String getId(); //缓存编号
    void putObject(Object var1, Object var2); //保存对象
    Object getObject(Object var1); //获取对象
    Object removeObject(Object var1); //移除对象
    void clear(); //清空缓存
    int getSize(); //获取缓存对象大小
    ReadWriteLock getReadWriteLock(); //获取缓存的读写锁
}

Dynamic SQL

In many cases, query conditions need to be assembled according to different scenarios. MyBatis provides the ability to dynamically assemble SQL statements.

Mainly provide the following elements:

  • if: judgment statement, but conditional branch judgment;
  • choose (when, otherwise): multi-conditional branch judgment;
  • trim (where, set): deal with some SQL assembly problems;
  • foreach: loop statement, commonly used in enumerating conditions such as in statement;
  • bind: Customize a context variable through an OGNL expression, which is convenient to use;

trim can handle and and comma splicing, for example:

<select id="findRoles" parameterType="string" >
  select id,role_name,note from t_role
  <trim prefix="where" prefixOverrides="and">
      <if test="roleName!=null and roleName!=''">
        and role_name like concat('%',#{roleName},'%')
      </if>
  </trim>
</select>

Alternatively, the updated field list can be set using the set element:

<update id="updateRole" parameterType="role">
    update t_role
    <set>
        <if test="roleName!=null and roleName!=''">
            role_name=#{roleName},
        </if>
        <if test="note!=null and note!=''">
            note=#{note}
        </if>
    </set>
    where id=#{id}
</update>

The next article will introduce the analysis and operation principle of MyBatis.

Welcome to scan the QR code below and follow my personal WeChat public account~

love story

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325255977&siteId=291194637