XML and annotation mapping in mybatis, so easy

Time:2021-4-14

Focus on “Java back end technology stack”

Reply to “interview” for full interview information

MyBatisXML configuration and annotation configuration are provided. Today, let’s talk about how these two ways are realized.

MyBatisIts real power lies in its statement mapping, which is its magic. Because of its extraordinary power, the XML file of mapper is relatively simple. If you take it with the same functionJDBCCode comparison, you will immediately find that nearly 95% of the code is saved.MyBatisCommitted to reduce the cost of use, so that users can be more focusedSQLcode.

From the official website.

MybatisMap nine top-level elements:

XML and annotation mapping in mybatis, so easy

  • Mapper: the root node of the mapping file. It has only one attribute, namespace. Its functions are as follows:
  • It is used to distinguish different mappers and is globally unique.
  • bindingDAOInterface, that is, interface oriented programming. When binding an interface, you don’t need to write the implementation class of the interface. You will find the corresponding mapper configuration through the fully qualified name of the interface to executeSQLStatement, so,namespaceMust write the fully qualified name of the interface.
  • Cache: configure the cache for a given namespace.
  • Cache Ref: refers to the cache configuration from another namespace.
  • resultMap: used to describe the corresponding relationship between database result set and object.
  • sql: ReusableSQLBlock, which can also be referenced by other statements. Usually, it stores some public productsSQL
  • Insert: map the insert statement.
  • Update: update the mapping statement.
  • Delete: delete the mapping statement.
  • Select: mapping query statements.

XML and annotation mapping in mybatis, so easy

XML mode

Nine top level mapping elements correspond to labels:

`<mapper namespace="com.tian.mybatis.mapper.UserMapper">`
 `<resultMap id="" type=""></resultMap>`
 `<sql id=""></sql>`
 `<cache blocking="" ></cache>`
 `<cache-ref namespace=""></cache-ref>`
 `<select id="selectUserById"></select>`
 `<insert id="insert" ></insert>`
 `<update id=""></update>`
 `<delete id=""></delete>`
`</mapper>`

Details of select

XML and annotation mapping in mybatis, so easy

It can be seen that there are quite a lot of options in the back. The following is the explanation of each item on the official website.

XML and annotation mapping in mybatis, so easy

Use cases of select

`<?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.tian.mybatis.mapper.UserMapper">`
 `<select id="selectUserById"  resultType="com.tian.mybatis.entity.User" parameterType="int" >`
 `select * from m_user where id = #{id}`
 `</select>`
`</mapper>`
  • The ID must be unique in the mapper and can be used to refer to the statement. The ID must correspond to only theXxxMapper.javaThe method in must be one-to-one correspondence.
  • Return type: user type,resultType: the query statement returns the fully qualified name or alias of the result type. Alias usage andparameterTypeIt’s the same.
  • Parameter: shaping, indicating the type and fully qualified name or alias of the parameter passed in the query statement. Support basic data type and complex data type.

{parameter name}: tellMyBatisGeneratedPreparedStatementParameters, relative toIn JDBC, the parameter is marked as’? ‘.

The types of alias and parameter mapping are as follows:

XML and annotation mapping in mybatis, so easy

For the use of alias in return type, please note:

If it’s our entity class, thenresultTypeCan’t use alias, can only useresultMapTo use an alias.

`<?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.tian.mybatis.mapper.UserMapper">`
 `<resultMap id="User" type="com.tian.mybatis.entity.User"/>`
 `<select id="selectUserById"  resultMap="User" parameterType="int" >`
 `select * from m_user where id = #{id}`
 `</select>`
`</mapper>`

However, if you use the above mapping table, you can also use aliases directly.

There are two pieces of data in the database

XML and annotation mapping in mybatis, so easy

UserMapper.xml

`<?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.tian.mybatis.mapper.UserMapper">`
 `<select id="countUser" resultType="int">`
 `select count(1) from m_user`
 `</select>`
`</mapper>`

UserMapper.java

`import com.tian.mybatis.entity.User;`
`public interface UserMapper {`
 `int countUser();`
`}`

Test category:

`public class MybatisApplication {`
 `public static final String URL = "jdbc:mysql://localhost.com:3306/mblog?useUnicode=true";`
 `public static final String USER = "root";`
 `public static final String PASSWORD = "123456";`
 `public static void main(String[] args) {`
 `String resource = "mybatis-config.xml";`
 `InputStream inputStream = null;`
 `SqlSession sqlSession = null;`
 `try {`
 `inputStream = Resources.getResourceAsStream(resource);`
 `//Factory model`
 `SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);`
 `//Get SQL operation session`
 `sqlSession = sqlSessionFactory.openSession();`
 `//Constructing objects (this is special. The way of constructing objects will be shared later)`
 `UserMapper userMapper =  sqlSession.getMapper(UserMapper.class);`
 `//Query statistics`
 `System.out.println(userMapper.countUser());`
 `} catch (Exception e) {`
 `e.printStackTrace();`
 `} finally {`
 `try {`
 `inputStream.close();`
 `} catch (IOException e) {`
 `e.printStackTrace();`
 `}`
 `sqlSession.close();`
 `}`
 `}`
`}`

Output: 2

When the field name in the database table is inconsistent with the field name in our entity, what should we do?

In the actual development, this kind of common is inevitable. We can solve this problem in the following way.

Entity class user

`public class User {`
 `private Integer id;`
 `private String userName;`
 `private Integer age;` 
 `//The set get toString method is not pasted here`
`}`

UserMapper.xmlContents of the document:

`<?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.tian.mybatis.mapper.UserMapper">`
 `<resultMap id="User" type="com.tian.mybatis.entity.User">`
 `<id column="id" property="id"/>`
 `<result column="name" property="userName"/>`
 `</resultMap>`
 `<select id="selectUserById"  resultMap="User" parameterType="int" >`
 `select * from m_user where id = #{id}`
 `</select>`
`</mapper>`

XML and annotation mapping in mybatis, so easy

  • Type: corresponding to our entity class, full pathname.
  • ID: can be understood as an alias.

XML and annotation mapping in mybatis, so easy

  • ID: unique identification, which is used for the select elementresultMapProperty.
  • Corresponding field name in our database: column.
  • Property: corresponding to the properties of our entity class, such as the property username in user, which should be consistent with the database table M\_ The name in user corresponds to.
  • Result: identify some simple properties, in which the column property represents the field name of the database, and the property represents the mapping of the queried field name to a property of the entity class.

Continue to test with our previous test class:

`UserMapper userMapper =  sqlSession.getMapper(UserMapper.class);`
`System.out.println(userMapper.selectUserById(1));`

Output:User{id=1, userName='tian', age=22}

Note: theget setandtoString()Method here to omit, I hope you are using the use of shortcut keys is very simple to get done.

It was mentioned aboveresultTypeandresultMapSo what’s the difference between them?

What is the difference between resulttype and resultmap?

  • resultType: directly represents the return type, including basic data type and complex data type.
  • resultMap: externalresultMapDefine the reference through the corresponding externalresultMapWhich ID does the result map toresultMapOn the other hand, it is generally used when the field name and attribute name are inconsistent, or complex joint query is needed to control the mapping result freely.
The connection between the two

When querying, each field will be put in a map. When the attribute returned by the query element isresultTypeThe key value pair will be assigned to the specified attribute. actuallyMyBatisThe return type of each query mapping of isresultMapOnly when we useresultTypeThe corresponding value is automatically assigned to the specified object property when theresultMapAt this time, because map is not a good representation of the domain, we further convert it into the corresponding entity object.resultMapIt mainly works on complex union queries.

resultMapThe default value of partial settings can also be changed automatically at the mapping level.

be carefulresultTypeandresultMapThe essence is the same, both are map data structure, but they can not exist at the same time.

Cases of addition, deletion and modification

insert

XML and annotation mapping in mybatis, so easy

It can be seen from here that there is no return value type for us to specify about adding insert. By default, it returns the int type.

`<insert id="insert" parameterType="com.tian.mybatis.entity.User">`
 ``INSERT INTO m_user(`name`,age) VALUES ( #{userName},#{age})``
`</insert>`

Corresponding methods in mapper

`int insert(User user);`

In addition, update is similar to delete, so there is no need to demonstrate them one by one.

Annotation method

The nine top-level mapping elements correspond to annotations

XML and annotation mapping in mybatis, so easy

The rest of the annotations are used with nine annotations.

Select annotation

Take the local UserMapper.xml Delete it and change itmybatis-config.xmlAnd put the UserMapper.xml Comment it out. add to

`<mapper class="com.tian.mybatis.mapper.UserMapper"/>`

UserMapper.java adding annotations

`public interface UserMapper {`
 `@Select("select * from m_user where id = #{id}")`
 `User selectUserById(Integer id);`
`}`

Test again

`User user = sqlSession.selectOne("com.tian.mybatis.mapper.UserMapper.selectUserById", 1);`
`System.out.println(user);`

Output:

User{id=1, userName='null', age=22}

From the output content, we can see that the username is null, which is also caused by the inconsistency with the field name in the database table collection. So how to deal with it?

In this way, add a note:

`public interface UserMapper {`
 `@Select("select * from m_user where id = #{id}")`
 `@Results( @Result(column = "name",property = "userName"))`
 `User selectUserById(Integer id);`
`}`

Output:

User{id=1, userName='tian', age=22}

This is the way to deal with the problem that the entity attribute name is different from the database table field name when using annotations.

Insert, update and delete can also be done with annotations.

@Insert, @ update, @ delete with corresponding SQL statements.

Can annotations and XML coexist?

 `<update id="updateAuthorIfNecessary">`
 `update m_user`
 `<trim prefix="SET" suffixOverrides=",">`
 `<if test="userName != null and userName != ''">`
 `` `name` = #{userName},``
 `</if>`
 `<if test="gender != null and gender != 0">`
 `gender = #{gender},`
 `</if>`
 `<if test="age != null and age != 0">`
 `age = #{age},`
 `</if>`
 `</trim>`
 `where id=#{id}`
 `</update>`

At the same time UserMapper.java Add comments to methods in

``@Update("update m_user set  `name` = #{userName},gender = #{gender},age = #{age} where id=#{id}")``
`int updateAuthorIfNecessary(User user);`

The return of neutron star is abnormal again

`nested exception is java.lang.IllegalArgumentException:`
`Mapped Statements collection already contains value for com.tian.mybatis.mapper.UserMapper.updateAuthorIfNecessary.` 
`please check file [D:\workspace\my_code\mybatis\target\classes\mapper\UserMapper.xml] and com/tian/mybatis/mapper/UserMapper.java (best guess)`

In other words, it already exists, that is, XML and annotations cannot be used at the same time. Choose one of the two.

XML can be used in combination with annotation, but it must be ensured that XML and annotation cannot exist in the same method at the same time.

proposal

Simple SQL processing can use annotations, and complex SQL can use XML. But the actual work still depends on whether the project you are waiting for is standardized.

There are only three kinds of projects

1. All must use XML.

2. All must be annotated.

3. XML and annotation can be used at the same time.

Advanced mapping

association

Map toJavaBeanIt only deals with one-to-one association.

`<resultMap type="com.tian.mybatis.entity.User" id="userMapRole">`
 `<id column="id" property="id" />`
 `<result column="name" property="userName" />`
 `<result column="age" property="age" />`
 `<association property="role" javaType="UserRole">`
 `<id column="id" property="id" />`
 `<result column="roleName" property="roleName" />`
 `</association>`
`</resultMap>`

Attribute node of association:

  • Property: the entity object property name of the mapped database column.
  • javaType: completejavaClass name and qualified name. The type of the property mapped by property.

Subelement

  • ID: it is usually a mapped primary key, which can improve the performance.
  • result:
  • Column: the field name of the mapped database.
  • Property: the entity object property corresponding to the mapped data column.

collection

It is mapped to a complex “data type” attribute of JavaBean, which is a collection list and deals with one to many relationships.

`<resultMap type="com.tian.mybatis.entity.User" id="userMapAddress">`
 `<id column="id" property="id"/>`
 `<result column="name" property="userName"/>`
 `<collection property="lists" ofType="UserAddress">` 
 `<id column = "id" property = "id">`
 `<result column="addressDesc" property="addressDesc"/>`
 `</collection>`
 `</resultMap>`

ofType: complete Java class name and qualified name. The type of the property mapped by property.

The rest are basically the same as association.

Both collection and association have the function of loading delay.

Delayed loading: first query from a single table, and then query the associated table when necessary, which greatly improves the performance of the database, because relatively speaking, single table query is faster than multi table query.

The relationship between XML and annotation

We have talked about the implementation of the two methods above. Let’s compare the relationship between the two methods

XML mode

There has to be one XxxMapper.xml Correspondingly, the method name corresponds to the ID in the XML, and the method input parameter and method output parameter must be corresponding, which is easy to cause problems. When we are developing, some can be generated by code generator, but some must be handwritten by ourselves, and some companies also require handwritten, so we need to pay attention here.

Annotation method

unwantedXxxMapper.xmlFile, just in the correspondingXxxMapper.javaIt’s OK to add notes to the method in, but there are holes here. After all, we put SQL into our java code.

Advantages and disadvantages

XML mode: XML file is added, which is troublesome to modify, uncertain (if else judgment), error prone, and special escape characters such as greater than or less than.

Annotation method: complex SQL is not easy to use, collecting SQL is not convenient, management is not convenient, modification needs to be recompiled

summary

This article describes theMybatisTwo mapping methods, as well as some attention points, some relations and differences.

When the entity attribute name is different from the database table field name, how to deal with XML and annotation. The difference between resulttype and resultmap.

Recommended reading

More than 6000 words | second kill system design considerations [theory]

Interviewer: tell me about your understanding of Java exceptions