(8) MyBatis from entry to soil-the use of automatic mapping

This is the eighth article in mybatis series. If you haven't read the previous suggestions, first go to the [Java Tsukuba Fox] public account to view the previous text, which is convenient for understanding and grasping. In the previous article, we introduced some of the ways in which mybatis uses queries, especially one-to-one query and one-to-many query. Those who haven't seen it are recommended to go to the official account to check.

Today we introduce the automatic mapping that we have been using but did not have time to introduce too much.

What is automatic mapping?

Before introducing automatic mapping, let's take a look at manual mapping, as follows:

<resultMap id="orderModelMap1" type="com.zhonghu.chat08.demo7.model.OrderModel">
    <id column="id" property="id"/>
    <result column="userId" property="userId" />
    <result column="createTime" property="createTime" />
    <result column="upTime" property="upTime" />
</resultMap>
<select id="getById1" resultMap="orderModelMap1">
    <![CDATA[
    SELECT
        a.id,
        a.user_id userId,
        a.create_time createTime,
        a.up_time upTime
    FROM
        orders a
    WHERE
        a.id = #{value}
    ]]>
</select>

Note that there are 4 lines of configuration in the above resultMap element, as follows:

<id column="id" property="id"/>
<result column="userId" property="userId" />
<result column="createTime" property="createTime" />
<result column="upTime" property="upTime" />

These 4 lines of code are used to configure the mapping relationship between the columns of the sql result and the fields in the OrderModel object.

Have you noticed that the values ​​of the column and property elements in the mapping rules are the same. Mybatis supports automatic mapping configuration. When the automatic mapping is turned on, when the column name of sql is the same as the field name in the Model (not case sensitive Write), mybatis will automatically map internally, and we don’t need to manually write the above 4-line mapping rules.

Let's change the above example to the automatic mapping method, as follows:

<resultMap id="orderModelMap2" type="com.zhonghu.chat08.demo7.model.OrderModel" autoMapping="true">
</resultMap>
<select id="getById2" resultMap="orderModelMap2">
    <![CDATA[
    SELECT
        a.id,
        a.user_id userId,
        a.create_time createTime,
        a.up_time upTime
    FROM
        orders a
    WHERE
        a.id = #{value}
    ]]>
</select>

Pay attention to the autoMapping attribute in the resultMap above, whether to enable automatic mapping, we set it to true, so mybatis will automatically map and assign values ​​according to the column name and the field with the same name in the Model.

The final query results of the above two configurations are the same, and the values ​​of the four fields corresponding to the query results will be automatically assigned to the attributes of the same name in the OrderModel.

Automatic mapping switch

There are two main types of automatic mapping in mybatis. One is the global configuration, which is effective for all the resultMaps in the application. This is set in the mybatis configuration file; the other is configured through the autoMapping property of the resultMap.

When mybatis judges whether a resultMap is enabled for automatic mapping configuration, it will first look for its own autoMapping attribute. If this attribute is set, it will directly use the value of this attribute. If the autoMapping attribute of the resultMap element is not configured, it will be configured globally. Automatic mapping rules.

Let us explain in detail the content of this.

mybatis automatically maps global configuration

Add the following configuration in the mybatis global configuration file:

<settings>
    <setting name="autoMappingBehavior" value="自动映射规则"/>
</settings>

There are mainly the following:

  • NONE: Turn off the global mapping switch
  • PARTIAL: Map attributes other than the nested result mapping (that is, the connected attribute) defined internally, and this is also the default value.
  • FULL: Automatically map all attributes.

NONE

When the value of autoMappingBehavior is set to NONE in the global configuration of mybatis, it means that the global automatic mapping is turned off, which will cause SQL to actually return the result, but the result will not be automatically mapped when the result is mapped, so the return is empty

PARTIAL

Automatic mapping will be performed, but some complex query mappings will nest some mappings (such as association, collection) in the resultMap. When PARTIAL is used, if there are nested mappings, this nested mapping will not be automatically mapped. .

FULL

All attributes are automatically mapped.

autoMapping use

As we mentioned above, when the autoMapping attribute is specified in the resultMap, the automatic mapping of the resultMap is controlled by the autoMapping attribute, and has nothing to do with the global mapping configuration (autoMappingBehavior) behavior in mybatis.

Case 1

This core configuration is mainly in sqlmap, as follows:
<resultMap id="orderModelMap7" type="com.zhonghu.chat08.demo7.model.OrderModel" autoMapping="true">
    <association property="userModel" autoMapping="true">
        <id column="user_id" property="id"/>
    </association>
</resultMap>
<select id="getById7" resultMap="orderModelMap7">
    <![CDATA[
    SELECT
        a.id,
        a.user_id userId,
        a.create_time createTime,
        a.up_time upTime,
        b.id as user_id,
        b.name
    FROM
        orders a,user b
    WHERE
        a.user_id = b.id
        AND a.id = #{value}
    ]]>
</select>
Corresponding test case
com.zhonghu.chat08.demo7.Demo7Test#getById7
@Test
public void getById7() throws IOException {
    this.before("demo7/mybatis-config1.xml");
    try (SqlSession sqlSession = this.sqlSessionFactory.openSession(true);) {
        OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
        OrderModel orderModel = mapper.getById7(2);
        log.info("{}", orderModel);
    }
}
Run output
24:37.544 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById7 - ==>  Preparing: SELECT a.id, a.user_id userId, a.create_time createTime, a.up_time upTime, b.id as user_id, b.name FROM orders a,user b WHERE a.user_id = b.id AND a.id = ? 
24:37.589 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById7 - ==> Parameters: 2(Integer)
24:37.610 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById7 - <==      Total: 1
24:37.610 [main] INFO  c.j.chat05.demo7.Demo7Test - OrderModel(id=2, userId=1, createTime=1610803573, upTime=1610803573, userModel=UserModel(id=1, name=冢狐))

All attributes in OrderModel are automatically mapped successfully.

Auto-assembly is not so fun, and failure to play may bring some hidden dangers. Let's look at a case, see example 2 below.

Example 2

According to the order number, query the order information, and by the way, query the order detail list. For this we use the one-to-many query in mybatis.

OrderDetaiMapper.xml added
<select id="getListByOrderId1" resultType="com.zhonghu.chat08.demo7.model.OrderDetailModel">
    <![CDATA[
    SELECT
        a.id,
        a.order_id AS orderId,
        a.goods_id AS goodsId,
        a.num,
        a.total_price AS totalPrice
    FROM
        order_detail a
    WHERE
        a.order_id = #{value}
    ]]>
</select>

This can be based on the id of the order to query the detailed list associated with the order.

OrderMapper.xml join
<resultMap id="orderModelMap8" type="com.zhonghu.chat08.demo7.model.OrderModel" autoMapping="true">
    <collection property="orderDetailModelList" select="com.zhonghu.chat08.demo7.mapper.OrderDetailMapper.getListByOrderId1" column="id"/>
</resultMap>
<select id="getById8" resultMap="orderModelMap8">
    <![CDATA[
    SELECT
        a.id,
        a.user_id userId,
        a.create_time createTime,
        a.up_time upTime
    FROM
        orders a
    WHERE a.id = #{value}
    ]]>
</select>
Test case
com.zhonghu.chat08.demo7.Demo7Test#getById8
@Test
public void getById8() throws IOException {
    this.before("demo7/mybatis-config.xml");
    try (SqlSession sqlSession = this.sqlSessionFactory.openSession(true);) {
        OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
        OrderModel orderModel = mapper.getById8(1);
        log.info("{}", orderModel);
    }
}
Run output
11:06.193 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById8 - ==>  Preparing: SELECT a.id, a.user_id userId, a.create_time createTime, a.up_time upTime FROM orders a WHERE a.id = ? 
11:06.229 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById8 - ==> Parameters: 1(Integer)
11:06.250 [main] DEBUG c.j.c.d.m.O.getListByOrderId1 - ====>  Preparing: SELECT a.id, a.order_id AS orderId, a.goods_id AS goodsId, a.num, a.total_price AS totalPrice FROM t_order_detail a WHERE a.order_id = ? 
11:06.251 [main] DEBUG c.j.c.d.m.O.getListByOrderId1 - ====> Parameters: 1(Integer)
11:06.255 [main] DEBUG c.j.c.d.m.O.getListByOrderId1 - <====      Total: 2
11:06.256 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById8 - <==      Total: 1
11:06.256 [main] INFO  c.j.chat05.demo7.Demo7Test - OrderModel(id=null, userId=2, createTime=1610803573, upTime=1610803573, userModel=null, orderDetailModelList=[OrderDetailModel(id=1, orderId=1, goodsId=1, num=2, totalPrice=16.00), OrderDetailModel(id=2, orderId=1, goodsId=1, num=1, totalPrice=16.00)])

Pay attention to the id attribute of OrderModel in the output, how is it a null value? Mainly caused by the following line of configuration

<collection property="orderDetailModelList" select="com.zhonghu.chat08.demo7.mapper.OrderDetailMapper.getListByOrderId1" column="id"/>

There is a column attribute in the above configuration, which specifies id. At this time, mybatis thinks that you have manually specified the mapping relationship for the id field, so it skips the automatic mapping of the id field to the OrderModel.id attribute, which leads to the id of the OrderModel object. The attribute is not assigned. At this time, we need to manually specify the id mapping rule in orderModelMap8, as follows:

<resultMap id="orderModelMap8" type="com.zhonghu.chat08.demo7.model.OrderModel" autoMapping="true">
    <id column="id" property="id" />
    <collection property="orderDetailModelList" select="com.zhonghu.chat08.demo7.mapper.OrderDetailMapper.getListByOrderId1" column="id"/>
</resultMap>

Run the test case again and it will be normal.

in conclusion

For our development, automatic mapping can really help us save some code, but there are also some hidden dangers. We hope that the system developed by ourselves is robust. It is recommended that when you write mapper xml, you should take some time to give the mapping configuration. Write it up, this can eliminate some hidden dangers and make our system more stable.

At last

  • If you feel that you are rewarded after reading it, I hope to pay attention to it. By the way, give me a thumbs up. This will be the biggest motivation for my update. Thank you for your support.
  • Welcome everyone to pay attention to my public account [Java Fox], focusing on the basic knowledge of java and computer, I promise to let you get something after reading it, if you don’t believe me, hit me
  • Seek one-click triple connection: like, forward, and watching.
  • If you have different opinions or suggestions after reading, please comment and share with us. Thank you for your support and love.

——I am Chuhu, and I love programming as much as you.

Welcome to follow the public account "Java Fox" for the latest news

Guess you like

Origin blog.csdn.net/issunmingzhi/article/details/113872133