Stop writing loops! mybatis inserts data in batches and updates the collection list in batches. Isn't it fragrant?

Firstly, the mybatis framework encapsulates sql statements and executes them through tag and attribute parsing in the form of xml. We know that the sql statements inserted into the table are:

INSERT INTO table name (column 1, column 2,...) VALUES (value 1, value 2,...)

During the insertion process, the database will add transactions by default, that is, batch insertion is atomic. There are batch inserts, but there are no sql statements that support batch updates. Only one qualified record is updated:

UPDATE table name SET column name = new value WHERE column name = a value

In mysql, we can use the replace into keyword to achieve the effect of batch update. The principle is to delete an original record (if any) and insert a new record to replace the original record. The common syntax is as follows:

REPLACE INTO table name (column 1, column 2,...) VALUES (value 1, value 2), (value 3, value 4),... (value x, value y)

It should be noted that the table into which data is inserted must have a primary key or a unique index. Otherwise, replace into will directly insert data, which will lead to duplicate data in the table. This is well understood because it is essentially an "upgrade" of insert into.

After knowing the update statement, there are two simple and convenient batch update methods in mybatis:

First:

xxxMapper.java

public interface xxxMapper {
	int updateBatch(@Param("list") List<yourClass> yourListName);
}

xxxMapping.xml

<update id="updateBatch" parameterType="java.util.List" >
    <foreach collection="list" item="item" index="index" open="" close="" separator=";">
      update Table name
      <set >
        <if test="item.Field 1 != null" >
          Field 1 = #{item. Field 1,jdbcType=INTEGER},
        </if>
        <if test="item.stepid != null" >
          Field 2 = #{item. Field 2,jdbcType=VARCHAR},
        </if>
      	......
      </set>
      where id = #{item.id,jdbcType=INTEGER}
    </foreach>
  </update>

The first is to use the foreach tag provided by mybatis to cycle the update statement to realize batch update. There are several attributes in the foreach tag,

item,index,collection,open,separator,close

In the update operation, we only need to focus on the collection attribute and item attribute. Let's look at a section of mybatis source code:

private Object wrapCollection(Object object) {
	DefaultSqlSession.StrictMap map;
    // If the passed in parameter is a collection
    if (object instanceof Collection) {
      //Create 1 Map
       map = new DefaultSqlSession.StrictMap();
       map.put("collection", object);
            //Note that if the parameter is list
          	if (object instanceof List) {
                //Then, the default writing method of collection is collection="list"
                map.put("list", object);
            }
            return map;
        } else if (object != null && object.getClass().isArray()) {
            map = new DefaultSqlSession.StrictMap();
            //The default writing method of array is collection="array"
            map.put("array", object);
            return map;
      } else {
        return object;
 	}
}

It can be seen that when the incoming parameter is a collection, the default value of collection is list. When the incoming parameter is an array, the default value of collection is array. If there are multiple parameters, it is necessary to encapsulate a key as the parameter name and value as the map of the parameter object. Therefore, the default value of collection here is list. In mapper, you can pass in the parameter with @ param("list") annotation.
The item attribute represents the alias of each element in the incoming collection during iteration, which is equivalent to the alias in sql.

It should be noted that don't forget to use alias Attribute! Otherwise, the field exception will not be found!

Second:

<insert id="updateBatch" useGeneratedKeys="true" keyProperty="id" parameterType="java.util.List" >
    replace into Table name
    (id,Field 2,Field 3,Field 4,...,field N)
    VALUES
    <foreach collection="list" item="item" separator=",">
      (#{item.id}, #{item.Field 2},#{item.Field 3},#{item.Field 4},...,#{item. Field N})
    </foreach>
</insert>

Because replace into is deleted and then inserted, it is equivalent to updating. Therefore, it should be noted that the table must have a primary key and be self incremented. Otherwise, it will be inserted directly in batch to form duplicate records.

It's not easy to create. If it's helpful to you, please praise it~

Keywords: MySQL SQL Server Mybatis Spring Boot SQL

Added by webtailor on Thu, 30 Dec 2021 14:31:58 +0200