The xml and annotation mapping in Mybatis is so easy

MyBatis # provides XML configuration and annotation configuration. Today, let's figure out how these two methods are realized.

MyBatis The real power of is its statement mapping, which is its magic. Because of its extraordinary power, the XML file of the mapper is relatively simple. If you take it with the same function JDBC Code comparison, you will immediately find that nearly 95% of the code is omitted. MyBatis Committed to reducing the use cost, so that users can focus more on   SQL Code.

From the official website.

Mybatis maps nine top-level elements:

 

 

  • 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 mapper s, which are globally unique.
  • Bind DAO interface, that is, interface oriented programming. When binding an interface, you do not 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 execute SQL statements. Therefore, the naming of namespace must write the fully qualified name of the interface.
  • Cache: configure the cache of the given namespace.
  • Cache Ref: references the cache configuration from other namespaces.
  • resultMap: used to describe the corresponding relationship between database result set and object.
  • SQL: SQL blocks that can be reused or referenced by other statements. Usually, some public SQL is stored.
  • Insert: map insert statements.
  • Update: update the mapping statement.
  • delete: deletes the mapping statement.
  • select: map query statements.

 

 

xml mode

Corresponding labels of nine top-level mapping elements:

<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>

select details

 

 

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

 

 

select use case

<?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 this Mapper and can be used to reference this statement. This id must only correspond to xxxmapper Methods in Java must be one-to-one correspondence.
  • Return type: User type, resultType: the fully qualified name or alias of the result type returned by the query statement. Alias is used in the same way as parameterType.
  • Parameter: integer, indicating the type and fully qualified name or alias of the parameter passed in by the query statement. Basic data types and complex data types are supported.

#{parameter name}: tell MyBatis that the PreparedStatement parameter generated is marked as'? 'relative to JDBC.

Alias and parameter mapping types are as follows:

 

 

Use of alias in return type. Note:

If it is our entity class, the resultType cannot use the alias. The alias can only be used by using resultMap.

<?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 the above mapping table is used, the alias can also be used directly.

There are two pieces of data in the database:

 

 

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 class:

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 mode
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            //Get sql operation session
            sqlSession = sqlSessionFactory.openSession();
            //Constructing objects (this is special, and the methods of constructing objects here 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

What happens when the field names in the database table are inconsistent with those in our entity?

In 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 posted here
}

UserMapper.xml file content:

<?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>

 

 

  • type: corresponds to our entity class, full pathname.
  • id: can be understood as alias.

 

 

  • id: unique identification. This id value is used for the reference of the resultMap attribute of the select element.
  • column: corresponds to the field name in our database table.
  • Property: the property corresponding to our entity class, such as the property userName in User, which should be consistent with the database table m_ name in User corresponds to.
  • result: identify some simple attributes, where column attribute represents the field name of the database, and property represents that the queried field name is mapped 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: entity class get set And The toString() method is omitted here. I hope you can use it easily by using shortcut keys.

The resultType and resultMap mentioned above, so 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: a reference defined by an external resultMap. It indicates which resultMap the result is mapped to through the id of the corresponding external resultMap. It is generally used when the field name and attribute name are inconsistent, or complex joint query is required to freely control the mapping result.

The relationship between the two

When querying, each field queried will be placed in a map. When the attribute returned by the query element is resultType, the key value pair will be taken out and assigned to the specified attribute. In fact, the return type of each query mapping of MyBatis is resultMap, but when we use resultType, the corresponding value will be automatically assigned to the specified object attribute. When using resultMap, because the map does not represent the domain well, we will further convert it into the corresponding entity object. resultMap is mainly used for complex joint queries.

Automatic mapping level of resultMap: the default level is PARTIAL. You can also change the value in settings.

be careful: resultType and resultMap is essentially the same. Both are Map data structures, but they cannot exist at the same time.

Cases of addition, deletion and modification

insert

 

 

From here, we can know that there is no return value type for us to specify about adding insert. The default return type is int.

<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 it one by one.

Annotation method

Corresponding annotation of nine top-level mapping elements:

 

 

Other annotations are used in conjunction with nine annotations.

select annotation

Put the local usermapper Delete the XML and change it to mybatis config XML, and put usermapper Comment out the XML. add to

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

UserMapper. Add annotations to Java

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

Retest

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, we can see that the userName is null, which is also caused by the inconsistency with the field name in the database table. So how to deal with it?

In this way, add another 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 difference between entity attribute names and database table field names when using annotations.

You can also use annotations to insert, update and delete.

@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, in usermapper Adding annotations to methods in Java

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

When the neutron star returns abnormally 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)

The general meaning is that 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 annotations, but it must be ensured that xml and annotations cannot exist in the same method at the same time.

proposal

Annotations can be used for simple sql processing, and xml can be used for complex sql. However, the actual work depends on whether this is standardized in the project you are waiting for.

In the project, there are only three types:

1. All must be in xml mode.

2. All must be annotated.

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

Advanced mapping

association

Mapping to a complex "data type" attribute of JavaBean 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 property name of the entity object that maps the database column.
  • javaType: complete java class name and qualified name. The type of property mapped by property.

Child element

  • id: it is generally a mapped primary key, which can improve 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. This attribute is a collection list that handles 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: full Java class name and qualified name. The type of property mapped by property.

The rest are basically consistent with the association.

Both association and collection have the function of delayed loading.

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

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 must be an xxmapper xml corresponds to it, the method name corresponds to the id in xml, and the method input and method output parameters must correspond to each other, which is easy to cause problems. When developing, we can use code generator to generate some, but some must be handwritten by ourselves, and some companies also require handwritten, so we need to pay attention here.

Annotation method

Xxmapper. Is not required XML file, which only needs to be in the corresponding xxxmapper It's OK to add annotations to the methods in Java, but there are holes here. After all, we put sql into our java code.

Advantages and disadvantages

xml method: xml files are added, which are troublesome to modify, uncertain conditions (ifelse judgment), error prone, and special escape characters, such as greater than or less than.

Annotation method: complex sql is not easy to use, it is inconvenient to collect sql, it is inconvenient to manage, and the modification needs to be recompiled

summary

This article describes the two mapping methods of Mybatis, as well as some points for attention, some relations and differences.

When the entity attribute name is different from the database table field name, how to deal with xml and annotation respectively. The difference between resultType and resultMap.

Tags: Java Mybatis entity

Posted by astribuncio on Mon, 02 May 2022 14:17:26 +0300