The mapper is the most complex and important component of MyBatis. It is also based on the development of MyBatis application, which accounts for a relatively large workload, and can even reach 80%. The mapper consists of a Mapper interface and XML or annotations. In the mapper, parameters, various SQL statements, stored procedures, caches, cascades and other complex processes can be configured, and data is mapped to the specified POJO or its objects through simple mapping rules. This is also the core operation logic of MyBatis.
The choice between XML and annotations is actually very obvious. On the one hand, when facing complex SQL, especially longer SQL, annotations will appear weak; on the other hand, the annotations are poorly readable, especially for those SQL that require complex configurations; on the other hand, the annotations do not have the advantage of referencing each other with XML contexts. On the other hand, the annotations do not have the advantage of referencing each other with XML contexts.
MyBatis mapper configurable elements
The MyBatis mapper configuration file can contain the following main elements that define various operations and related configurations that interact with the database:
-
<select>
: Representative SQLSELECT
Statement, used to query data from the database, can set properties such asid
(Uniquely identify the query),parameterType
(Full-qualified class name or alias for passed parameters)resultType
orresultMap
(Specify the mapping type of query result or the referenced result map). Can be passedfetchSize
、timeout
etc. attributes control query behavior and useflushCache
、useCache
etc. -
<insert>
: Used to executeINSERT
Statement inserts data into the database. Configuration properties includeid
、parameterType
(Type of insert data object). Can be setuseGeneratedKeys
andkeyProperty
(orkeyColumn
) to enable automatic growth of primary keys and map their values to specified Java properties.statementType
Attributes can specify statement types, such asSTATEMENT
、PREPARED
orCALLABLE
。 -
<update>
:definitionUPDATE
Statement, used to update records in the database. Also hasid
、parameterType
Properties, specifying the unique identifier and incoming parameter type for the update operation. Can be setflushCache
The attribute determines whether to refresh the secondary cache. -
<delete>
:definitionDELETE
Statement, delete data in the database. Includeid
、parameterType
Attributes represent the parameter types corresponding to the operation identifier and deletion conditions, respectively. Usually also supportedflushCache
Properties to control cache refresh. -
<sql>
: Define reusable SQL fragments where SQL statements can be used by other elements (such as<select>
、<insert>
etc.) Passinclude
Attribute reference. Helps reduce duplication of writing the same SQL clauses and improves code reusability. -
<resultMap>
: Define the result set mapping rules and associate the query results with the properties of the Java object. includeid
(Uniquely identify the result map),type
(Full-qualified class name or alias for the result object). Can be passed<id>
、<result>
、<association>
、<collection>
The sub-elements of the etc. describe in detail how to map the columns of the query result to the object's properties, nested objects, or collection properties. -
<parameterMap>
:Note: In newer versions of MyBatis, it is no longer recommended<parameterMap>
, but use it directlyparameterType
property. The mapping rules used in the old version to define input parameters, and<resultMap>
Similar, but mainly used to deal with complex parameter structures. It is usually used directly in new versionsparameterType
The attribute specifies the parameter type. -
<cache>
: Define the secondary cache configuration, and you can set the cache type, size, timeout policy, clear policy and other attributes. Suitable for scenarios where the query results are relatively stable and you want to share the results between multiple requests. -
<cache-ref>
: References to cache configurations defined in other namespaces to avoid duplicate definitions. passnamespace
The property specifies the namespace where the cache configuration to be referenced resides. These elements form the basic building block of the MyBatis mapper, through which they can flexibly configure various database operations and accurately control details such as the execution of SQL statements, parameter passing, result mapping, and cache policies. In actual use, appropriate element combinations can be selected according to business needs to achieve efficient database access
Select element
<select>
Elements are used in the MyBatis mapper configuration file to define SQL SELECT query statements and their related properties. The following is<select>
Common attributes of elements and their detailed explanations:
-
id
:Required attribute, which is unique in combination with the Mapper namespace, forms a unique identifier for MyBatis to call, for example: -
parameterType
: Optional attribute, used to specify the parameter type of the incoming query statement, which can be a fully qualified class name or a type alias, but it must be a built-in alias or a custom alias for MyBatis. When a query needs to accept parameters, use this attribute to declare the parameter type. The parameters can be a simple type (such as int, String), a complex type (such as a custom Java Bean), or a Map type. If you use a type alias, you need to define it in advance in the global configuration file or the current mapping file. -
resultType
: Optional attribute to specify the expected type of query result.
Format: Fully qualified class name or type alias. When automatic matching is allowed, the result set will be mapped through the Java Bean's canonical parameters, or defined as int, double, float, map, etc.; when the query result is a record mapped to a single object, use this property to specify the object type. MyBatis will automatically map each row of data from the query result to an object instance of the specified type. If you use type alias, you need to define it in advance in the global configuration file or the current mapping file (cannot be combined withresultMap
Used simultaneously) -
resultMap
: Optional attribute, its function is to refer to defined<resultMap>
, used to customize more complex query result mapping rules, should be combined with<resultMap>
Elementalid
Attribute value matching; when the query results require fine column-to-property mapping, or involve complex situations such as nested result sets, joint queries, automatic associations, etc., use this property instead of resultType, and the specified one must be predefined in the same mapping file. -
flushCache
: Optional attribute, its function is to control whether MyBatis is required to clear the local cache and secondary cache queried before after calling SQL. The default value is false (by default, the query will not refresh the cache) -
useCache
: Optional property indicating whether Level 2 cache is enabled for query results. Default value: true (by default, query results will be cached) -
timeout
: Optional property, set the timeout time (unit: seconds) of the query statement. The default value is determined by defaultStatementTimeout in JDBC-driven or global configuration. -
fetchSize
: Optional property, set the size of the prefetched result set for JDBC Statement, and the default value is determined by JDBC driver. -
statementType
: Less used, used to specify how to execute SQL statements. The default value: PREPARED (precompiled statement) has 3 options: STATEMENT: Static SQL (non-precompiled), PREPARED: Precompiled statements (recommended), CALLABLE: Stored procedure call -
resultOrdered
: Less used, its function is to indicate whether MyBatis should keep the order of the result set consistent with the order specified by the ORDER BY clause in SQL. Default: false (by default, MyBatis does not guarantee that the order of result sets is exactly the same as that of ORDER BY) -
resultSetType
: Use less frequently. Its purpose is to specify the type of the ResultSet (meaning only when using the STATEMENT statement type) Default value: FORWARD_ONLY (by default, use only cursor), options include: FORWARD_ONLY: only cursor (not rollback), SCROLL_SENSITIVE: sensitive scroll cursor (rollback, but may not see the latest changes to other transactions), SCROLL_INSENSITIVE: insensitive scroll cursor (rollback, and not affected by other transaction changes) -
resultSets
:: is rarely used, and its purpose is to use this property to specify the name or index of the result set when the query statement returns multiple result sets or cursors.
To sum up,<select>
The main attributes of the element are used to define the execution characteristics of the query statement, the input parameter type, the output result mapping method, the cache policy, the query timeout, the prefetch size and other execution characteristics. These properties help developers to fine-grained control of query behavior and ensure efficient and flexible interaction with databases. In practical applications, the most commonly used attributes areid
、parameterType
、resultType
orresultMap
、flushCache
anduseCache
Other attributes may work in specific scenarios, but are not commonly used.
Select element instance single parameter
<select parameterType="string" resultType="int"> select count(*) total from t_user where user_name like concat ('%',#{firstName, jdbcType=VARCHAR, javaType=String},'%') </select>
SQL is easy to understand. The elements inside can be understood by referring to the explanation and understanding of each item above. With SQL, the corresponding Mapper interface and method are required (that is, Dao Data Access Object)public Integer countUserByFirstName(String firstName)
In the settings element of MyBatis configuration file, there are two configurable options: autoMappingBehavior and mapUnderscoreToCamelCase. They are switches that control automatic mapping and camel mapping. Generally speaking, automatic mapping will be used more, so that SQL aliasing mechanism can be used, and the camel mapping requirements are stricter; there are 3 options for autoMappingBehavior configuration item, NONE means no automatic mapping, PARTIAL is the default value, which means only automatic mapping for unnested result sets, FULL means automatic mapping for all result sets, including nested result sets, usually by default
Suppose we have the following POJO
package ; import ; @Alias("role") public class Role{ private int id; private String roleName; private String note; /** setters and getters */ }
There are three attribute id, roleName, and note in this POJO. If the SQL column name and attribute name are consistent in the Mapper, it will form an automatic mapping, for example,
<select parameterType="int" resultType="role"> select id, role_name as roleName, note from t_role where id = #{id} </select>
The column name role_name is replaced by the alias roleName, which is consistent with the attribute name on POJO. In this way, MyBatis can correspond to the query result set and the attributes of POJO one by one, and automatically complete the mapping without any configuration.
If you strictly follow the camel nomenclature, such as the database field is role_name, the POJO attribute is roleName, the database field is user_name, and the POJO attribute is userName, then just set mapUnderscoreToCamelCase to true in the configuration item. If so, then SQL can be written as
select id, role_name, note from t_role where id = #{id}
MyBatis will be automatically mapped strictly according to the camel naming method, but this requires that the data field and the POJO attribute name are strictly corresponding.
Automatic mapping and camel mapping are both based on the mapping relationship between SQL column names and POJO attribute names, which will be more complicated in actual use. For example, some fields may have cascade relationships between master and slave tables, and for example, the conversion rules of typeHandler are complex. At this time, the resultType element cannot meet these needs. Need to consider using resultMap.
Select element instance Pass multiple parameters using Map
Suppose there is a Mapper interface definition that passes multiple parameters through key-value pairs
public List<Role> findRolesByMap(Map<String, Object>parameterMap);
At this time, a Map object passed to the mapper, and use it to set the corresponding parameters in SQL, as shown below
<select parameterType="map" resultType="role"> select id, role_name as roleName, note from t_role where role_name like concat('%', #{roleName}, '%') and note like concat('%', #{note},'%') </select>
Here, two database fields are used to perform a fuzzy query. The method of passing parameters is to use map, and the code is executed as follows
RoleDao roleDao = (); Map<String, Object>parameterMap = new HashMap<>(); ("roleName", "1"); ("note","1"); List<Role> roleList = (parameterMap);
Strictly speaking, Map is suitable for almost all scenarios, but its readability is relatively poor and cannot limit the data type it passes.
Select element instance pass multiple parameters using annotations
MyBatis provides @Param(), which can define the parameter name of the mapper, as shown in the following code
public List<Role> findRolesByAnnotation(@Param("roleName") String roleName, @Param("note") String note);
The Mapper file is as follows
<select "resultType="role"> select id, role_name as roleName, note from t_role where role_name like concat('%', #{roleName}, '%') and note like concat('%', #{note},'%') </select>
Select element instance Pass multiple parameters using JavaBean
Define a POJO first
package ; public class RoleParams{ private String roleName; private String note; /** setter and getter */ }
Define the Mapper interface as
public List<Role> findRolesByBean(RoleParams roleParam);
The Mapper file is as follows
<select "resultType="role" parameterType=""> select id, role_name as roleName, note from t_role where role_name like concat('%', #{roleName}, '%') and note like concat('%', #{note},'%') </select>
Execute the code as follows
sqlSession = (); RoleDao roleDao = (); RoleParams roleParams = new RoleParams(); ("1"); ("1"); List<Role>roleList = (roleParams);
It will also be used in some scenarios, such as querying roles through role names and notes, and it is also necessary to support pagination
The POJO of pagination is defined as follows
package ; public class PageParams{ private int start; private int limit; /** setters and getters */ }
The Mapper interface is as follows
public List<Role> findByMix(@Param("params") RoleParams roleParams, @Param("page") PageParams PageParam);
The following way to write a Mapper file
<select "resultType="role"> select id, role_name as roleName, note from t_role where role_name like concat('%', #{}, '%') and note like concat('%', #{},'%') limit #{}, #{} </select>
MyBatis provides EL (intermediate language) support for JavaBean parameters such as params and pages, which brings a lot of convenience to programming.
ResultMap resultMap
Automatic mapping and camel mapping rules are relatively simple, and it is impossible to define more attributes and meet complex scenarios. For example, enumeration requires typeHandler, data cascade, etc. Therefore, the select element provides the resultMap attribute, which is used to specify the specific resultMap as the mapping rules, as shown in the following definition.
<result Map type="role"> <id property="id" column="id"/> <result property="roleName" column="role_name"/> <result property="note" column="ntoe"/> </resultMap> <select parameterType="int" resultMap="roleMap"> select id, role_name, note from t_role where id = #{id} </select>
<!-- Define the result map,Used to map data in the database intoRoleObject --> <resultMap type=""> <id property="userid" column="userid"/> <!-- Primary key mapping --> <result property="username" column="username"/> <!-- Role name mapping --> <result property="password" column="password"/> <!-- Note Mapping --> <result property="sex" column="sex"/> <result property="phone" column="phone"/> <result property="email" column="email"/> <result property="phonenumber" column="phonenumber"/> <result property="comment" column="comment"/> </resultMap>
<!-- Define the result map,Used to map data in the database intoRoleObject --> <resultMap type=""> <id property="id" column="id"/> <!-- Primary key mapping --> <result property="roleName" column="roleName"/> <!-- Role name mapping --> <result property="note" column="note" typeHandler=""/> <!-- Note Mapping --> </resultMap>
Pagination parameters RowBounds
MyBatis not only supports paging, but also has a built-in class RowBounds that specializes in paging, as shown in the following code
/** * The RowBounds class is used to set the offset of SQL query and limit the size of the result set. */ package ; public class RowBounds { // No offset, unlimited number of rows public static final int NO_ROW_OFFSET = 0; // Maximum integer 2147483647 public static final int NO_ROW_LIMIT = Integer.MAX_VALUE; // Default RowBounds instance, no offset, no limit public static final RowBounds DEFAULT = new RowBounds(); private final int offset; // Offset, starting from which line private final int limit; // Limit the number of rows returned /** * Constructor, the default offset is 0, and the number of rows limited is the maximum integer value. */ public RowBounds() { = 0; = Integer.MAX_VALUE; } /** * Constructor, sets custom offsets and limits row counts. * * @param offset The offset of the query result, that is, which row it starts from. * @param limit Returns the maximum number of rows in the result set. */ public RowBounds(int offset, int limit) { = offset; = limit; } /** * Get the offset. * * @return Offset, starting from which line. */ public int getOffset() { return ; } /** * Get the number of rows that are limited. * * @return Returns the maximum number of rows in the result set. */ public int getLimit() { return ; } }
The Mapper interface is defined as follows
public List<Role> findByRowBounds(@Param("roleName") String rolename, @Param("note") String note, RowBounds rowBounds);
The Mapper mapping file is as follows
<select resultType="role"> select id, role_name as roleName, note from t_role where role_name like concat('%', #{roleName}, '%') and note like concat('%', #{note}, '%') </select>
There is no information about the RowBounds parameter in the mapping code, MyBatis itself will automatically recognize and enable it
Execute the code as follows
Logger log = (); SqlSession sqlsession = null; try{ sqlsession = (); RoleDao roleDao = (); List<Role> roleList = ("role", "note", new RownBounds(0,20)); (()); }finally{ if(sqlSession!=null){ (); } }
RowBounds paging is generally only suitable for paging with a small amount of data. The principle is that after executing SQL queries, the result will be returned based on the offset and limiting number of pieces. Therefore, the performance of querying large amounts of data will be relatively poor.
insert element
In the MyBatis framework,<insert>
Tags are used to define SQL insert statements. The following are its commonly used properties and descriptions:
- id: As a unique identifier in the namespace, it corresponds to the method name in the Mapper interface, and is used to find the corresponding SQL statement when MyBatis is executed.
<insert ...>
, In the XML file of the same Mapper, the id attribute value must be unique, otherwise MyBatis will throw an exception when parsing. - parameterType: Specifies the parameter type of the incoming SQL statement, usually a fully qualified name of a Java class (such as package name plus class name) or an alias. Supports complex data types such as basic data types, JavaBean objects, Map, etc.
<insert parameterType="" ...>
, MyBatis can be automatically mapped to placeholders (such as ${} or #{}) in SQL statements based on the attribute name of the parameter object, without manually specifying each parameter. - useGeneratedKeys: Indicates whether to enable JDBC's getGeneratedKeys method to obtain the primary key automatically generated by the database. The default value is false.
<insert useGeneratedKeys="true" ...>
, When the database table has a self-increment primary key or other automatically generated primary key, setting to true allows MyBatis to automatically obtain and return the generated primary key value. This requires that the database driver and the database itself support this feature. - keyProperty: when
useGeneratedKeys="true"
When this property specifies which property the primary key value generated after insertion should be assigned to the incoming parameter object (the object specified by parameterType). If the primary key is a compound primary key, multiple attribute names can be separated by commas.<insert keyProperty="id" ...> or <insert keyProperty="primaryKey1, primaryKey2" ...>
, keyProperty will only take effect when useGeneratedKeys="true" and the database supports it. Otherwise, even if this property is specified, there will be no effect. - statementType: Specifies the execution type of the statement. Optional values include STATEMENT, PREPARED (default), and CALLABLE. The Statement, PreparedStatement and CallableStatement are used respectively.
<insert statementType="PREPARED" ...>
, usually, keep the default PREPARED, because it can prevent SQL injection attacks and allow precompiled SQL statements to improve performance. This property is not required unless there is a specific requirement. - flushCache: Controls whether to refresh the MyBatis first-level cache (local Session cache) after performing the insert operation. The default value is true, which means that the cache is cleared after each insertion.
<insert flushCache="false" ...>
, if you want to retain the cache after insertion to optimize subsequent queries, you can set it to false. But please note that this may affect data consistency, especially in multi-transaction concurrency environments, and needs to be used with caution. - timeout: Sets the timeout time (unit: seconds) of the execution statement. MyBatis will throw an exception when the database response is not received after this time.
<insert timeout="30" ...>
Note: Set it reasonably according to the actual time consumption of database operations and the system's requirements for response time. Too short may cause normal operation to fail due to timeout, and too long may cause application response to slow. - keyColumn: It is only useful for insert and update. The column names in the table are set by the generated key values. These settings are only necessary in some databases such as PG. When the primary key column is not the first column in the table, it is necessary to set it. If it is a compound primary key, no name needs to be separated by a comma.
- Others: parameterMap, databaseId
Insert element instance auto-increment primary key scenario
<!-- Insert a new oneRoleRecord --> <insert parameterType="" databaseId="mysql" > INSERT INTO t_role(roleName, note) VALUES (#{roleName}, #{note}) </insert>
This statement is very simple, because the id of the table only increases the primary key, so when inserting data, nothing is done for the field, and the database will automatically complete it. However, a record is often inserted during the actual development process, and the association table needs to be processed according to the primary key value of the current table. In MyBatis, it can be passedgetGeneratedKeys
The method obtains the primary key generated by the database. By default, it is false, which means that the primary key value will not be returned. When this switch is turned on, it also needs to configure its properties.keyProperty
orkeyColumn
, thus telling the system to put the generated primary key into the corresponding attribute of POJO. If there are multiple primary keys, they should be separated by commas.
<!-- Insert a new oneRoleRecord parameter: - parameterType: 指定插入操作时使用的parameter类型,here it is ,Indicates the inserted role object。 - databaseId: Specify thisSQLWhich database does the statement apply to,here it is mysql。 - useGeneratedKeys: Specifies whether to use the database to automatically generate key values。If true,It means using automatically generated key values。 - keyProperty: Specifies which attribute the generated key value should be set to,here it is id。 Return value: 无Return value,Perform insert only。 --> <insert parameterType="" databaseId="mysql" useGeneratedKeys="true" keyProperty="id" > INSERT INTO t_role(roleName, note) VALUES (#{roleName}, #{note}) </insert>
In this way, configure useGeneratedKeys to true to indicate that the getGeneratedKeys method of the Statement object using JDBC returns the primary key, and keyProperty represents which POJO attribute is used to match the primary key. In this example, the id means that it will use the primary key generated by the data to assign value to the attribute id of the POJO.
insert element instance custom primary key scenario
Sometimes the primary key may not be self-incremented, but depends on certain rules, such as canceling the id of the role table, changing its rule to 1 when the role table record is empty, and when the role table record is not empty, the id is set to the current id plus 3. For such a special rule, MyBatis also provides support. It mainly relies on the selectKey element to allow custom key value generation rules.
<!-- Insert a new oneRoleRecord parameter: - parameterType: 指定插入操作时use的parameter类型,here it is,Represents the inserted role object。 - databaseId: Specify thisSQLWhich database is suitable for,here it ismysql。 - useGeneratedKeys: Specifies whether to use the primary key value generated by the database。Iftrue,MyBatisThe generated primary key value will be automatically retrieved and set to the object。 - keyProperty: Specifies which attribute will receive the generated primary key value,here it isid。 Return value: After the insertion operation is successful,Return value为插入的Record的主键ID。 --> <insert parameterType="" databaseId="mysql" useGeneratedKeys="true" keyProperty="id" > <!-- useselectKeyTags to dynamically generate primary keysID。在插入新Record之前执行,Query the largest in the current role tableIDvalue,If it does not exist, the default is1,If it exists, it is at the maximumIDAdd3,To ensureIDUniqueness。 --> <selectKey keyProperty="id" resultType="int" order="BEFORE"> select if (max(id) = null, 1, max(id) + 3) from t_role </selectKey> <!-- Insert newRoleRecord,#{id}, #{roleName}, #{note} represents the role's ID, role name and note information respectively. These values are taken from the incoming Role object. --> INSERT INTO t_role(id, roleName, note) VALUES (#{id}, #{roleName}, #{note}) </insert>
The others are easy to understand. Only this order, set to BEFORE, means that it will be executed before the currently defined SQL, that is, it will generate SQL with the primary key before inserting data. If there are still some actions that need to be executed after SQL, for example, there may be an embedded index call inside the insert statement, so it can be set to AFTER, and the task will be completed after the insertion is executed.
Update element and delete element
<!-- renewRoleInformation --> <!-- Function-level comments:该标签用于renewRole表中Information。 parameter: - roleName: Character name,Type isString,用于renewRole的名称。 - note: Notes information,Type isString,用于renewRole的备注。 - id: RoleID,Type isInteger,用于指定要renew的Role。 Return value:无Return value。 --> <update parameterType=""> UPDATE t_role SET roleName = #{roleName}, note = #{note} WHERE id = #{id} </update> <!-- Function-level block comments: According to the providedIDDelete specific databaseRoleRecord。 parameter: id - Need to be deletedRoleRecord的ID,Type isint。 Return value: 无Return value。 --> <delete parameterType="int"> DELETE FROM t_role WHERE id = #{id} </delete>
sql element
In the actual development process, many tables often have a lot of columns. When writing code, repeating the column names is a boring thing. Even though the compiler provides many methods, it is still very troublesome. MyBatis provides sql elements, simplifying the encoding work in this scenario
<!-- Define the column name to be returned when querying role information --> <sql id = "roleCols"> id, roleName, note </sql> <!-- according toIDQueryRoleinformation,returnRoleObject。该Query针对Oracledatabase。 --> <select parameterType="int" resultMap="roleMap" databaseId="oracle"> SELECT <include ref/>FROM t_role WHERE id = #{id} </select> <!-- Insert newRoleinformation。Before insertion,passselectKeyFor newRoleGenerate a uniqueID。 --> <insert parameterType=""> <selectKey keyProperty="id" resultType="int" order="BEFORE" statementType="PREPARED"> select if (max(id) = null, 1, max(id)+3) from t_role </selectKey> insert into t_role(<include ref/>) values(#{id}, #{roleName}, #{note}) </insert>
SQL elements also support variable passing
<!-- Define aSQLFragment,Used to query the role tableid、roleNameandnoteList --> <!-- By passing in(alias)Dynamic splicingSQLTable name prefix in statement --> <sql id ="roleCols2"> ${alias}.id, ${alias}.roleName, ${alias}.note} </sql> <!-- according toIDQueryRoleinformation,returnRoleObject。该Query针对Oracledatabase。 --> <select parameterType="int" resultMap="roleMap" databaseId="oracle"> SELECT <include ref> <property name="alias" value="r"/> </include> FROM t_role r WHERE id = #{id} </select>
A variable of "alias" is defined in the include element, whose value is the alias "r" of the table t_role in SQL. The SQL element can refer to this variable through EL
This is all about this article about the easy-to-understand MyBatis mapper. For more related contents of MyBatis mapper, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!