Spring boot+Mybatisplus用AR模式實現邏輯刪除操作

極限之旅發表於2020-06-19

Mybatisplus的AR模式

Active Record(活動記錄),是一種領域模型模式,特點是一個模型類對應關係型資料庫中的一個表,而模型類的一個例項對應表中的一行記錄。ActiveRecord 一直廣受動態語言( PHP 、 Ruby 等)的喜愛,而 Java 作為準靜態語言,對於 ActiveRecord 往往只能感嘆其優雅,所以 MP 也在 AR 道路上進行了一定的探索,僅僅需要讓實體類繼承 Model 類且實現主鍵指定方法,即可開啟 AR 之旅。
邏輯刪除

邏輯刪除的本質是修改操作,所謂的邏輯刪除其實並不是真正的刪除,而是在表中將對應的是否刪除標識(is_delete)或者說是狀態欄位(status)做修改操作。比如0是未刪除,1是刪除。在邏輯上資料是被刪除的,但資料本身依然存在庫中。
對應的SQL語句:update 表名 set is_delete = 1 where id = 1;語句表示,在該表中將id為1的資訊進行邏輯刪除,那麼客戶端進行查詢id為1的資訊,伺服器就不會提供資訊。倘若想繼續為客戶端提供該資訊,可將 is_delete 更改為 0 。

一般商城網站,要分析客戶的資料等,都會大量使用邏輯刪除,所以,這肯定是要掌握了,下面,直接上程式碼:

entity

@Data
//對應資料庫的表名
@TableName("tbl_item")
//繼承Model類,開始AR模式
public class Items extends Model<Items>{
//    主鍵自增
    @TableId(type = IdType.AUTO)
    private Integer id;
    private String picture;
    private String name;
    private Double price;
    //指定邏輯欄位,1表示邏輯刪除狀態,0表示邏輯未刪除
    @TableLogic
    private Integer logic;
}

mapper

@Repository
public interface ItemsMapper extends BaseMapper<Items> {
}

service

@Service
public class ItemsService extends ServiceImpl<ItemsMapper,Items> {
    @Resource
    private ItemsMapper itemsMapper;
    public void delete(String id){
        itemsMapper.deleteById(id);
        System.out.println("邏輯刪除單個商品成功!");
    }

    public void remove(String ids) {
        if (ids!=null && !ids.equals("")){
            String[] idArray=ids.split(",");
            itemsMapper.deleteBatchIds(Arrays.asList(idArray));
            System.out.println("邏輯批量刪除商品成功!");
        }
    }
}

controller

@Controller
@RequestMapping("/items")
public class ItemsController {
    @Resource
    private ItemsService itemsService;
    //顯示商品列表資訊
    @RequestMapping("/list")
    public String list(Model model){
        List<Items> items = itemsService.list();
        model.addAttribute("items",items);
        return "item";
    }
    //單個刪除
    @ResponseBody
    @RequestMapping("/delete")
    public String delete(String id){
        if(id!=null && !id.equals("")){
            itemsService.delete(id);
        }
        return "success";
    }
    //批量刪除
    @ResponseBody
    @RequestMapping("/remove")
    public String remove(String ids){
        itemsService.remove(ids);
        return "success";
    }
}

只有一個頁面是用來展示商品資訊的

item.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>商品列表</title>
    <!--<link rel="shortcut icon" href="/shopping/image/favicon.ico">-->
    <link rel="stylesheet" href="/shopping/css/style.css" th:href="@{/css/style.css}">
    <script src="/shopping/js/jquery-3.4.1.min.js" th:src="@{/js/jquery-3.4.1.min.js}"></script>
    <script src="/shopping/js/script.js" th:src="@{/js/script.js}"></script>
    <link rel="icon" th:href="@{/image/favicon.ico}" type="image/x-icon"/>
    <script th:inline="javascript">
        var contextPath = [[${#request.getContextPath()}]];
    </script>
</head>
<body>
<table>
    <caption>商品列表</caption>
    <tr>
        <th><input type="checkbox" id="cb" th:onclick="|toggle()|"></th>
        <th>編號</th>
        <th>圖片</th>
        <th>名稱</th>
        <th>單價</th>
        <th>操作</th>
    </tr>
    <tr class="itemList" th:each="item,iter:${items}">
        <td>
            <input type="checkbox" class="orderList" th:name="cks" th:value="${item.id}">
        </td>
        <td th:text="${iter.index}+1"></td>
        <td><a href="/logic/image/${cart.picture}" th:href="@{'/image/'+${item.picture}}" target="_blank"> <img
                src="/logic/image/${cart.picture}" th:src="@{'/image/'+${item.picture}}"></a>
        </td>
        <td th:text="${item.name}"></td>
        <td th:text="${item.price}"></td>
        <td>
            <input type='button' value='刪除' class='delBtn' th:onclick="|removeCartItem(${item.id})|">
        </td>
    </tr>
    <tr class="itemList">
        <!-- 合併單元格 -->
        <th colspan="6"><input type="button" value="刪除選中" class='reBtn'  th:onclick="|deleteItems()|">
        </th>
    </tr>
</table>
</body>
</html>

其中,有一個js檔案

script.js

//刪除單個商品
function removeCartItem(id){
    // alert(id);
    var r=confirm("確定要刪除該商品嗎?");
    //提交到後臺進行非同步邏輯刪除
    if(r){
        $.ajax({
            url:contextPath+'/items/delete',
            data:{'id':id},
            method:'post',
            success:function (data) {
                if (data=='success'){
                    window.location.href=contextPath+'/items/list';
                }
            }
        })
     }
}

//批量刪除商品
function deleteItems() {
    // var r=confirm("確定刪除這些商品嗎?");
    // if(r){
    //         alert(ids);
    // }
    //判斷是否選擇了商品
    var count=0;
    //儲存選中的商品id
    var ids='';
    var cks=document.getElementsByName("cks");
    for (var i=0;i<cks.length;i++){
        if (cks[i].checked){
            count++;
            ids+=cks[i].value+',';
        }
    }
    if (count==0 || count==undefined){
        alert("請先選擇商品,再進行刪除!");
    }
    else{
        var r=confirm("確定刪除這些商品嗎?");
        if(r){
            // alert(ids.substring(0,ids.length-1));
            $.ajax({
                url:contextPath+'/items/remove',
                data:{'ids':ids.substring(0,ids.length-1)},
                method:'post',
                success:function (data) {
                    if (data=='success'){
                        window.location.href=contextPath+'/items/list';
                    }
                }
            })
        }
    }
}
//頁面載入完畢事件
$(function () {
    //給所有圖片新增滑鼠懸浮事件
    $("img").hover(function () {
        $(this).css("width","150px").css("height","150px");
    },function () {
        $(this).css("width","100px").css("height","100px");
    });
    //獲取所有的行,新增滑鼠懸停事件
    $(".itemList").hover(function () {
        $(this).css("backgroundColor", "aliceblue");
    },function () {
        $(this).css("backgroundColor", "white");
    });
    //給單個刪除按鈕新增滑鼠懸浮事件
    $(".delBtn").hover(function () {
        $(this).css("backgroundColor","green");
    },function () {
        //滑鼠移開時背景是綠色
        $(this).css("backgroundColor","red");
    });
    //給批量刪除按鈕新增懸浮事件
    $(".reBtn").hover(function () {
        $(this).css("backgroundColor","red");
    },function () {
        //滑鼠移開時背景是綠色
        $(this).css("backgroundColor","green");
    });
});
//全選和反選,保證每個商品的核取方塊狀態和最頂部的核取方塊狀態一致即可
function toggle() {
        if ($("#cb").is(":checked")) {
            $(".orderList").each(function(){
                $(this).get(0).checked=true;//全選
            })
        } else {
            $(".orderList").each(function () {
                $(this).get(0).checked=false;//反選
            })
        }
}

spring配置檔案

application.yml

#伺服器配置
server:
  port: 8888
  servlet:
    context-path: /logic
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/shopping?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong
    username: root
    password: 資料庫密碼
    driver-class-name: com.mysql.cj.jdbc.Driver
  mvc:
    static-path-pattern: /**
#Mybatisplus配置
mybatis-plus:
  type-aliases-package: com.wxb.logicdelete.entity    #實體類包掃描
  global-config:
      db-config:
#        logic-delete-field: flag  #全域性邏輯刪除欄位值 3.3.0開始支援,詳情看下面。
          logic-delete-value: 1 # 邏輯已刪除值(預設為 1)
          logic-not-delete-value: 0 # 邏輯未刪除值(預設為 0)

對了,在專案啟動類中還要配置mapper包掃描

package com.wxb.logicdelete;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.wxb.logicdelete.mapper")
public class LogicDeleteApplication {

    public static void main(String[] args) {
        SpringApplication.run(LogicDeleteApplication.class, args);
    }

}

資料庫表設計

然後,啟動專案,訪問,最開始應該是這樣的頁面

然後可以點選刪除或刪除選中按鈕進行邏輯刪除了,比如:我先刪除一個iphone11之後頁面就沒有了

但是資料庫表中實質是更新操作,並沒有刪除記錄,而是把邏輯欄位logic的值更新為1了

然後也可以根據核取方塊選中的進行批量的邏輯刪除,比如,我就刪掉索尼X8000G和EPSON投影儀

資料庫也是批量根據id進行更新

進行了兩次刪除之後,後臺也列印了兩條日誌

好了,完成

相關文章