1. 程式人生 > >mybatis中批量操作的彙總整理

mybatis中批量操作的彙總整理

在我們實際開發過程中,免不了會碰到要批量操作資料的情況,如果在程式碼中進行迴圈操作的話,由於跟資料庫連線次數過多會導致效率低下,影響效能,這個時候應用mybatis進行批量操作就很重要了,這篇文章的目的主要為了對mybatis中的批量操作做一個整理,包括刪除,更新,插入。

目錄

  1.批量刪除,插入

  2.批量更新


測試建表,插入資料如下:

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for ins_orbit_point
-- ----------------------------
DROP TABLE IF EXISTS `ins_orbit_point`;
CREATE TABLE `ins_orbit_point`  (
  `point_id` bigint(20) NOT NULL COMMENT '巡查點id',
  `orbit_id` bigint(20) NOT NULL COMMENT '巡查軌跡id',
  `point_type` int(2) NOT NULL COMMENT '巡查點型別(1開始點,2中間點,3結束點)',
  `point_sort` int(10) NOT NULL COMMENT '巡查點在軌跡中的實際順序'
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '巡查軌跡與巡查點關聯表' ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of ins_orbit_point
-- ----------------------------
INSERT INTO `ins_orbit_point` VALUES (359, 1, 1, 1);
INSERT INTO `ins_orbit_point` VALUES (360, 1, 2, 2);
INSERT INTO `ins_orbit_point` VALUES (361, 1, 3, 3);
INSERT INTO `ins_orbit_point` VALUES (362, 2, 1, 1);
INSERT INTO `ins_orbit_point` VALUES (363, 2, 2, 2);
INSERT INTO `ins_orbit_point` VALUES (364, 2, 2, 3);
INSERT INTO `ins_orbit_point` VALUES (366, 2, 2, 4);
INSERT INTO `ins_orbit_point` VALUES (366, 2, 3, 5);
INSERT INTO `ins_orbit_point` VALUES (359, 11, 3, 1);

SET FOREIGN_KEY_CHECKS = 1;
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for ins_orbit
-- ----------------------------
DROP TABLE IF EXISTS `ins_orbit`;
CREATE TABLE `ins_orbit`  (
  `orbit_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵,自增',
  `start_point_id` bigint(20) NOT NULL COMMENT '軌跡開始點id',
  `end_point_id` bigint(20) NULL DEFAULT NULL COMMENT '軌跡結束點id',
  `is_end` int(2) NOT NULL COMMENT '是否結束(1是,0否)',
  `ins_date` date NOT NULL COMMENT '巡查日期',
  `insor_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '巡查人id',
  `ins_orb_distance` decimal(5, 3) NULL DEFAULT NULL COMMENT '里程,單位km',
  `ins_orb_spending` decimal(5, 3) NULL DEFAULT NULL COMMENT '花費時間,單位小時',
  `ins_orb_speed` decimal(5, 3) NULL DEFAULT NULL COMMENT '速度,單位km/h',
  `start_time` timestamp(0) NULL DEFAULT NULL COMMENT '開始時間',
  `end_time` timestamp(0) NULL DEFAULT NULL COMMENT '結束時間',
  `park_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '專案id',
  `dept_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '部門id',
  PRIMARY KEY (`orbit_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '巡查軌跡表' ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of ins_orbit
-- ----------------------------
INSERT INTO `ins_orbit` VALUES (1, 359, 361, 1, '2018-11-09', '2e636fc47624493aa1056c6ed9e8f168', 10.000, 6.000, 1.650, '2018-11-08 09:22:54', '2018-11-08 15:23:11', 'af98a32c9b4d490297cadc2d85faf797', '74c6071187dd44d68eac5b7a295f65fd');
INSERT INTO `ins_orbit` VALUES (2, 362, 366, 0, '2018-11-09', '2e636fc47624493aa1056c6ed9e8f168', 10.000, 7.000, 2.000, '2018-11-08 08:25:26', '2018-11-08 15:25:35', 'af98a32c9b4d490297cadc2d85faf797', '74c6071187dd44d68eac5b7a295f65fd');
INSERT INTO `ins_orbit` VALUES (11, 359, 359, 0, '2018-11-09', '11111', 12.000, 22.000, 22.000, '2018-11-09 15:44:44', '2018-11-09 15:44:47', '111', '1111');

SET FOREIGN_KEY_CHECKS = 1;

        1.批量刪除,插入

批量插入跟批量插入的原理是一樣的,主要用到的就是foreach迴圈處理。

foreach的主要用在構建in條件中,它可以在SQL語句中進行迭代一個集合。foreach元素的屬性主要有item,index,collection,open,separator,close。item表示集合中每一個元素進行迭代時的別名,index指 定一個名字,用於表示在迭代過程中,每次迭代到的位置,open表示該語句以什麼開始,separator表示在每次進行迭代之間以什麼符號作為分隔 符,close表示以什麼結束,在使用foreach的時候最關鍵的也是最容易出錯的就是collection屬性,該屬性是必須指定的,但是在不同情況 下,該屬性的值是不一樣的,主要有一下3種情況: 
1. 如果傳入的是單引數且引數型別是一個List的時候,collection屬性值為list 
2. 如果傳入的是單引數且引數型別是一個array陣列的時候,collection的屬性值為array 
3. 如果傳入的引數是多個的時候,我們就需要把它們封裝成一個Map了,當然單引數也可以封裝成map,實際上如果你在傳入引數的時候,在breast裡面也 是會把它封裝成一個Map的,map的key就是引數名,所以這個時候collection屬性值就是傳入的List或array物件在自己封裝的map 裡面的key

以上面的軌跡表為例,批量刪除跟插入的程式碼如下:

批量插入:

​
 <insert id="insert" parameterType="com.pcos.inspection.insorbit.entity.InsOrbit">
        insert into ins_orbit (orbit_id, start_point_id, end_point_id,
        is_end, ins_date, insor_id,
        ins_orb_distance, ins_orb_spending, ins_orb_speed,
        start_time, end_time, park_id, dept_id
        )
        values
        <foreach collection="list" item="item" separator=",">
            (
            #{item.orbitId,jdbcType=BIGINT},
            #{item.startPointId,jdbcType=BIGINT},
            #{item.endPointId,jdbcType=BIGINT},
            #{item.isEnd,jdbcType=INTEGER},
            #{item.insDate,jdbcType=DATE},
            #{item.insorId,jdbcType=VARCHAR},
            #{item.insOrbDistance,jdbcType=DECIMAL},
            #{item.insOrbSpending,jdbcType=DECIMAL},
            #{item.insOrbSpeed,jdbcType=DECIMAL},
            #{item.startTime,jdbcType=TIMESTAMP},
            #{item.endTime,jdbcType=TIMESTAMP},
            #{item.parkId,jdbcType=VARCHAR},
            #{item.deptId,jdbcType=VARCHAR}
            )
        </foreach>
    </insert>

​

轉換為sql如下:

INSERT INTO ins_orbit ( 
						orbit_id, 
						start_point_id, end_point_id, 
						is_end, ins_date, insor_id, ins_orb_distance,
						ins_orb_spending, ins_orb_speed, start_time,
						end_time, park_id, dept_id )
VALUES
	( ?,?,?,?,?,?,?,?,?,?,?,?,? ),
	( ?,?,?,?,?,?,?,?,?,?,?,?,? ),
	( ?,?,?,?,?,?,?,?,?,?,?,?,? )

 可以看到,實際上mybatis就是做了字串的拼接。批量刪除跟插入的程式碼差不多,就是將插入語句改成了刪除語句而已

 在瞭解了批量插入後,我們可以反過來推斷批量刪除的mybatis寫法。

首先,如果要我們在資料庫中一次刪除多條資料我們會怎麼寫呢?為了方便,我們以主鍵為基準進行刪除,sql如下:

	DELETE from ins_orbit where orbit_id in (2,1,11);

現在問題就很簡單了,只要用foreach拼接成in後面這個字串就行了,很明顯字首open = "(",字尾close=")",分隔符=","

如下:

<delete id="deleteBatch">
        delete from ins_orbit where
        orbit_id
        in
        <foreach collection="list" separator="," open="(" close=")" item="item">
            #{item}
        </foreach>
    </delete>

  2.批量更新

  由於作者這裡表資料比較複雜,推薦一個批量更新連結https://blog.csdn.net/xyjawq1/article/details/74129316

批量更新比插入及刪除要稍微麻煩一些,這裡我先將需求說一下,還是上面那兩站表,我需要批量更新資料,將ins_prbit中is_end為0的資料改為1,同時需要將ins_orbit_point表中對應資料(一條軌跡上會有多個點),也就是軌跡上的最後一個點置為結束點(point_type = 3)。

批量更新軌跡表(ins_orbit)如下:

<update id="updateBatch">
        update ins_orbit
        set
        is_end = 1
        where orbit_id in
        <foreach collection="list" item="item" separator="," open="(" close=")">
            #{item.orbitId,jdbcType=BIGINT}
        </foreach>
    </update>

批量更新軌跡途徑點表如下:

  <update id="updateBatch">
        update ins_orbit_point t1
        set
        point_type = 3
        <where>
            t1.orbit_id in
            <foreach collection="list" item="item" separator="," open="(" close=")">
                #{item.orbitId,jdbcType=BIGINT}
            </foreach>
            and
            <foreach collection="list" item="item" separator="  " open="case orbit_id" close="end">
                when #{item.orbitId,jdbcType=BIGINT}
                then t1.point_id = #{item.pointId,jdbcType=BIGINT}
            </foreach>
            and
            <foreach collection="list" item="item" separator="  " open="case orbit_id" close="end">
                when #{item.orbitId,jdbcType=BIGINT}
                then t1.point_sort = (select t3.sort from
                (select max(point_sort) as sort from ins_orbit_point t2 where t2.orbit_id = #{item.orbitId,jdbcType=BIGINT})
                t3)
            </foreach>
        </where>
    </update>

dao層程式碼如下:

public interface InsOrbitPointDao  {

    /**
     * 批量更新
     *
     * @param insOrbitPoints
     */
    void updateBatch(List<InsOrbitPoint> insOrbitPoints);
}
public interface InsOrbitDao extends OVUBaseDao<InsOrbit, Long> {

    /**
     * 批量更新
     *
     * @param list
     */
    void updateBatch(List<InsOrbit> list);
}

實體類如下:

public class InsOrbit {
    /**
     * 主鍵,自增
     */
    private Long orbitId;

    /**
     * 軌跡開始點id
     */
    private Long startPointId;

    /**
     * 軌跡結束點id
     */
    private Long endPointId;

    /**
     * 是否結束(1是,0否)
     */
    private Integer isEnd;

    /**
     * 巡查日期
     */
    private Date insDate;

    /**
     * 巡查人id
     */
    private String insorId;

    /**
     * 里程,單位km
     */
    private BigDecimal insOrbDistance;

    /**
     * 花費時間,單位小時
     */
    private BigDecimal insOrbSpending;

    /**
     * 速度,單位km/h
     */
    private BigDecimal insOrbSpeed;

    /**
     * 開始時間
     */
    private Date startTime;

    /**
     * 結束時間
     */
    private Date endTime;

    /**
     * 專案id
     */
    private String parkId;

    /**
     * 部門id
     */
    private String deptId;

    public String getDeptId() {
        return deptId;
    }

    public void setDeptId(String deptId) {
        this.deptId = deptId;
    }

    public Long getOrbitId() {
        return orbitId;
    }

    public void setOrbitId(Long orbitId) {
        this.orbitId = orbitId;
    }

    public Long getStartPointId() {
        return startPointId;
    }

    public void setStartPointId(Long startPointId) {
        this.startPointId = startPointId;
    }

    public Long getEndPointId() {
        return endPointId;
    }

    public void setEndPointId(Long endPointId) {
        this.endPointId = endPointId;
    }

    public Integer getIsEnd() {
        return isEnd;
    }

    public void setIsEnd(Integer isEnd) {
        this.isEnd = isEnd;
    }

    public Date getInsDate() {
        return insDate;
    }

    public void setInsDate(Date insDate) {
        this.insDate = insDate;
    }

    public String getInsorId() {
        return insorId;
    }

    public void setInsorId(String insorId) {
        this.insorId = insorId;
    }

    public BigDecimal getInsOrbDistance() {
        return insOrbDistance;
    }

    public void setInsOrbDistance(BigDecimal insOrbDistance) {
        this.insOrbDistance = insOrbDistance;
    }

    public BigDecimal getInsOrbSpending() {
        return insOrbSpending;
    }

    public void setInsOrbSpending(BigDecimal insOrbSpending) {
        this.insOrbSpending = insOrbSpending;
    }

    public BigDecimal getInsOrbSpeed() {
        return insOrbSpeed;
    }

    public void setInsOrbSpeed(BigDecimal insOrbSpeed) {
        this.insOrbSpeed = insOrbSpeed;
    }

    public Date getStartTime() {
        return startTime;
    }

    public void setStartTime(Date startTime) {
        this.startTime = startTime;
    }

    public Date getEndTime() {
        return endTime;
    }

    public void setEndTime(Date endTime) {
        this.endTime = endTime;
    }

    public String getParkId() {
        return parkId;
    }

    public void setParkId(String parkId) {
        this.parkId = parkId;
    }
}
public class InsOrbitPoint {
    /**
     * 巡查點id
     */
    private Long pointId;

    /**
     * 巡查軌跡id
     */
    private Long orbitId;

    /**
     * 巡查點型別(1開始點,2中間點,3結束點)
     */
    private Integer pointType;

    /**
     * 巡查點在軌跡中的實際順序
     */
    private Integer pointSort;



    public Long getPointId() {
        return pointId;
    }

    public void setPointId(Long pointId) {
        this.pointId = pointId;
    }

    public Long getOrbitId() {
        return orbitId;
    }

    public void setOrbitId(Long orbitId) {
        this.orbitId = orbitId;
    }

    public Integer getPointType() {
        return pointType;
    }

    public void setPointType(Integer pointType) {
        this.pointType = pointType;
    }

    public Integer getPointSort() {
        return pointSort;
    }

    public void setPointSort(Integer pointSort) {
        this.pointSort = pointSort;
    }

}