SQL 中刪除超出時間限制的數據,並返回刪除數據信息(Mybatis+postgresql)

前言

前一陣子,接到一個活,主要內容是這樣的,數據庫中存在一些過期的日誌(可能是一天前的數據,或者是一個月前的數據,等等),將這些數據刪除掉,並且返回這些數據的信息(就是說我得知道自己到底刪了哪些數據呀?)。苦於在網上找了好久,終無果,於是清明小長假,便在自己的mac上,簡單的搭了個環境,試了一下,誰讓自己是初出茅廬的小菜鳥呢。因爲看到網上很多都是關於sql如何操作的,但是並沒有結合Mybatis的,所以在這裏記錄一下,方便自己日後使用,也希望可以幫到那些一直尋找的人。

正文

先給大家看一下我自擬的表結構:

-- ----------------------------
-- Table structure for eventLog
-- ----------------------------
DROP TABLE IF EXISTS "public"."eventLog";
CREATE TABLE "public"."eventLog" (
  "id" int4 NOT NULL DEFAULT nextval('"eventLog_id_seq"'::regclass),
  "start_time" timestamp(6),
  "log_detail" varchar(255) COLLATE "pg_catalog"."default"
)
;
ALTER TABLE "public"."eventLog" OWNER TO "harry";

-- ----------------------------
-- Primary Key structure for table eventLog
-- ----------------------------
ALTER TABLE "public"."eventLog" ADD CONSTRAINT "eventLog_pkey" PRIMARY KEY ("id");

表很簡單,一共有三個字段,id爲自增主鍵, start_time 爲需要看是否過期的字段,log_detail 爲這個日誌的詳細內容。

接下來貼出大家關心的 Mybatis 中的代碼:

<?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.example.harry.dao.EventLogMapper">
    <resultMap id="BaseMap" type="com.example.harry.entity.EventLog">
      <id column="id" property="id" jdbcType="INTEGER" javaType="java.lang.Integer"/>
      <result column="start_time" property="time" jdbcType="TIMESTAMP" javaType="java.sql.Timestamp"/>
      <result column="log_detail" property="logDetail" jdbcType="VARCHAR" javaType="java.lang.String"/>
    </resultMap>
        <insert id="insertEventLog"  parameterType="EventLog" useGeneratedKeys="true" keyProperty="id">
            insert into "eventLog" (start_time,log_detail) values (now(),#{logDetail});
        </insert>

        <select id="deleteOverdueLog" resultType="map">
            DELETE
            FROM "eventLog"
            <![CDATA[ WHERE start_time < now()::TIMESTAMP + '-${overdueDays} days']]>
            RETURNING id, start_time, log_detail;
        </select>
    
    </mapper>

最重要的就是哪個select方法,很多人就要問了,爲什麼是delete的語句,你卻要用select的標籤呢?
這個問題問的好,剛開始我也是用的delete,但是不管sql怎麼寫,返回的都是一個Integer,然後轉念一想,Mybatis是基於JDBC的,在JDBC中 增刪改執行的都是 executeUpdate方法,這個方法返回整數就是受影響的行數,所以如果想在刪除的同時,返回刪除行的信息,就一定要用select。
在這裏,我想要強調四點:
1.我這裏讓它返回的是個List>所以 使用的是

resultType="map"

如果想要裝載進EventLog的實體類中,我們可以使用

resultMap="BaseMap"

關於resultType和resultMap的區別,我就不在這裏贅述了,詳細的可以查看官網(贊一下官網,寫的真的很好)。
2. overdueDays是我傳遞進來的Integer的參數,代表的是具體的天數,可以配置在application.properties中,方便由於業務修改造成的變化。這裏使用的是 ${},而不是#{}。是因爲#{}會做防注入處理,把參數換爲 ‘?’,並且將參數自動的加上引號,而${} 就不會只是單純的做替換。
3. something 這裏可以把something換成任意語句,並且something的語句不會被轉義,因爲我們這裏用到了'<',' ' '(就是小於號和單引號),所以我們不希望它被轉義。
4. RETURNING 後面接的就是我們具體想要返回刪除行的哪些字段。

Tips:
SQL除了以上寫法,還有另一種寫法:

WITH deleteInfo AS (DELETE
            FROM "eventLog"
            <![CDATA[ WHERE start_time < now()::TIMESTAMP + '-${overdueDays} days']]>
            RETURNING id, start_time, log_detail)
SELECT * FROM deleteInfo;

後記

具體的項目我已經上傳到了 github上,如果有需要可以進行下載https://github.com/luckypoison/postgresBootLearn.git
謝謝大家

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章