Introduction to ResultMap of MyBatis, Associated Objects

Keywords: Attribute Mybatis Java Session

In MyBatis, when a query is select ed for mapping, the return type can be either resultType or resultMap, which is a direct representation of the return type, while resultMap is a reference to the external ResultMap, but resultType and resultMap cannot exist simultaneously. When MyBatis performs query mapping, in fact, each attribute queried is placed in a corresponding Map, where the key is the attribute name and the value is its corresponding value. When the provided return type attribute is resultType, MyBatis takes out the key-value pair in the Map and assigns the corresponding attribute to the object specified by resultType. So in fact, every query mapping of MyBatis is ResultMap, but when the return type attribute we provide is resultType, MyBatis automatically assigns the corresponding value to the attribute of the object specified by resultType. When the return type we provide is resultMap, because Map can not represent the domain model very well, we need ourselves. Further converting it into corresponding objects is often useful in complex queries.

There is such a Blog.java file

import java.util.List;

public class Blog {
    private int id;
    private String title;
    private String content;
    private String owner;
    private List<Comment> comments;

    //getter and setter methods
}

The corresponding database tables store id, title, Content, Owner attributes, so when we do the following query mapping

<typeAlias alias="Blog" type="com.tiantian.mybatis.model.Blog"/>
<select id="selectBlog" parameterType="int" resultType="Blog">
        select * from t_blog where id = #{id}
</select><!--Come from SQL Mapping file BlogMapper.xml-->

MyBatis automatically creates a ResultMap object, encapsulates the key-value pairs based on the attribute names found, and then sees that the return type is a Blog object, and assigns the key-value pairs corresponding to the Blog object from the ResultMap.

It is also very useful when the return type is directly a ResultMap, which is mainly used for complex joint queries, because simple queries are not necessary. Let's first look at a simple query with a return type of ResultMap, and then at the use of complex queries.

Writing of Simple Query

<resultMap type="Blog" id="BlogResult">
    <id column="id" property="id"/>
    <result column="title" property="title"/>
    <result column="content" property="content"/>
    <result column="owner" property="owner"/>
</resultMap>
<select id="selectBlog" parameterType="int" resultMap="BlogResult">
    select * from t_blog where id = #{id}
</select>

The value of resultMap in select mapping is the id of an external resultMap, indicating which resultMap the returned result maps to, and the type attribute of the external resultMap indicates what type the resultMap's result is. Here is the Blog type, MyBatis will take it out as a Blog object. The sub-node id of the resultMap node is used to identify the id of the object, while the result sub-node is used to identify some simple attributes, in which the Column attribute represents the attributes queried from the database, and the Property indicates which attributes the corresponding values of the queried attributes are assigned to the entity object. This is how a simple query resultMap is written. Next, let's look at a more complex query.

There is a Comment class, which has a reference to a Blog, indicating which Blog's Computing is, so when we query Comment, we will also find out the corresponding Blog and assign it the Blog property.

import java.util.Date;

public class Comment {

    private int id;
    private String content;
    private Date commentDate = new Date();
    private Blog blog;

    //getter and setter methods
}

This is how it is written.

<!--Come from CommentMapper.xml file   -->
<resultMap type="Comment" id="CommentResult">
    <association property="blog" select="selectBlog" column="blog" javaType="Blog"/>
</resultMap>

<select id="selectComment" parameterType="int" resultMap="CommentResult">
    select * from t_Comment where id = #{id}
</select>

<select id="selectBlog" parameterType="int" resultType="Blog">
    select * from t_Blog where id = #{id}
</select>

Its access situation is as follows: first, it requests a select mapping with id as selectComment, and then obtains a Result Map object with id as CommentResult. We can see that the return type of the corresponding Result Map is a Comment object, in which there is only one association node, instead of the id corresponding to the simple query mentioned above, the result sub-node, but it will still correspond. MyBatis has the function of automatic encapsulation. As long as you provide the return type, MyBatis will encapsulate the corresponding object according to its own judgment. So in the simple query, if you don't specify which field the id corresponds to and which field the title corresponds to in the resultMap, MyBatis will encapsulate the corresponding object according to its own judgment. MyBatis's own judgment is to compare the field of the query or its corresponding alias with the attributes of the returned object. If it matches and the type matches, MyBatis assigns the value to it.

In the corresponding resultMap above, a blog attribute is associated, and its corresponding JAVA type is Blog. In the above-mentioned writing, the related objects are related by sub-queries, and of course, they can also be related directly by association queries.

In the association subnode above

  • The Property attribute represents which association attribute of the resultMap return type, and for the example above, the blog attribute managed by Comment.
  • Select indicates which selection mapping is performed to map the corresponding associated attributes, that is to say, it requests the selection mapping whose id is the corresponding value of select to query the associated attribute objects.
  • Column represents the key-value pair corresponding to the current associated object in the resultMap with the id of CommentResult. The key-value pair will be used as a parameter for the sub-query of the associated object, that is, the value of the blog attribute queried in the selectComment will be passed as a parameter to the parameter of the sub-query selectBlog of the associated object blog.
  • javaType represents what type of current associated object is in JAVA.

The above is a one-to-one or one-to-many case, one-to-one related query. In practical applications, there is a relatively large number of applications that find out the corresponding many parties through one party, and when taking out the many parties, we should also associate one party. In the above example, when we take out the Blog object, we should take out all the corresponding Comments, and when we take out the Comment, we still need to take out the corresponding Blogs. This is the case. In JAVA, it is taken out by one request.
Written as follows:

<!-- Come from BlogMapper.xml file -->
<resultMap type="Blog" id="BlogResult">
    <id column="id" property="id"/>
    <collection property="comments" select="selectCommentsByBlog" column="id" ofType="Comment"></collection>
</resultMap>

<resultMap type="Comment" id="CommentResult">
    <association property="blog" javaType="Blog" column="blog" select="selectBlog"/>
</resultMap>

<select id="selectBlog" parameterType="int" resultMap="BlogResult">
    select * from t_blog where id = #{id}
</select>

<!--  adopt Blog Search for Comment  -->
<select id="selectCommentsByBlog" parameterType="int" resultMap="CommentResult">
    select * from t_Comment where blog = #{blogId}
</select>

The entry of the above request is a select map with ID as selectBlog, and the result is a result Map with ID as BlogResult. The type of ID as BlogResult is Blog, which specifies the attributes and fields of id, and specifying ID will play a very important role in the construction of MyBatis. There is a Comment object associated with it, because a blog can have many Comments, which are a collection, so it is mapped with a collection, in which select still indicates which sub-query to query the corresponding comments, column indicates which field value is passed as a parameter to the sub-query, and ofType also indicates the return type. The back type is the type inside the collection, and the reason for using ofType instead of type is MyBatis internal to distinguish it from association.

Test code:

    @Test
    public void selectCommentsByBlogTest() {
        SqlSession session = Util.getSqlSessionFactory().openSession();
        CommentMapper commentMapper = session.getMapper(CommentMapper.class);
        List<Comment> comments = commentMapper.selectCommentsByBlog(6);
        for (Comment comment : comments)
            System.out.println(comment);
        session.close();
    }

    /**
     * Query single record
     */
    @Test
    public void testSelectOne() {
        SqlSession session = Util.getSqlSessionFactory().openSession();
        BlogMapper blogMapper = session.getMapper(BlogMapper.class);
        Blog blog = blogMapper.selectBlog(6);
        List<Comment> comments = blog.getComments();
        if (comments != null) {
            System.out.println("--------------Comments Size------------" + comments.size());
            for (Comment comment : comments)
                System.out.println(comment);
        }
        session.close();
    }

Posted by regiemon on Sat, 23 Mar 2019 01:06:52 -0700