成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

SpringBootJPA中delete的使用方法

本篇內容介紹了“SpringBoot JPA中delete的使用方法”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

創(chuàng)新互聯(lián)主要從事做網(wǎng)站、網(wǎng)站設計、網(wǎng)頁設計、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務。立足成都服務靈丘,10年網(wǎng)站建設經(jīng)驗,價格優(yōu)惠、服務專業(yè),歡迎來電咨詢建站服務:18982081108

常見db中的四個操作curd,前面的幾篇博文分別介紹了insert,update,接下來我們看下delete的使用姿勢,通過JPA可以怎樣刪除數(shù)據(jù)

一般來講是不建議物理刪除(直接從表中刪除記錄)數(shù)據(jù)的,在如今數(shù)據(jù)就是錢的時代,更常見的做法是在表中添加一個表示狀態(tài)的字段,然后通過修改這個字段來表示記錄是否有效,從而實現(xiàn)邏輯刪除;這么做的原因如下

  • 物理刪除,如果出問題恢復比較麻煩

  • 無法保證代碼一定準確,在出問題的時候,刪錯了數(shù)據(jù),那就gg了

  • 刪除數(shù)據(jù),會導致重建索引

  • Innodb數(shù)據(jù)庫對于已經(jīng)刪除的數(shù)據(jù)只是標記為刪除,并不真正釋放所占用的磁盤空間,這就導致InnoDB數(shù)據(jù)庫文件不斷增長,也會導致表碎片

  • 邏輯刪除,保留數(shù)據(jù),方便后續(xù)針對數(shù)據(jù)的挖掘或者分析

<!-- more -->

I. 環(huán)境準備

在開始之前,當然得先準備好基礎環(huán)境,如安裝測試使用MySQL,創(chuàng)建SpringBoot項目工程,設置好配置信息等,關于搭建項目的詳情可以參考前一篇文章

  • 190612-SpringBoot系列教程JPA之基礎環(huán)境搭建

下面簡單的看一下演示添加記錄的過程中,需要的配置

1. 表準備

沿用前一篇的表,結構如下

CREATE TABLE `money` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL DEFAULT '' COMMENT '用戶名',
  `money` int(26) NOT NULL DEFAULT '0' COMMENT '錢',
  `is_deleted` tinyint(1) NOT NULL DEFAULT '0',
  `create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
  `update_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間',
  PRIMARY KEY (`id`),
  KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;

2. 項目配置

配置信息,與之前有一點點區(qū)別,我們新增了更詳細的日志打印;本篇主要目標集中在添加記錄的使用姿勢,對于配置說明,后面單獨進行說明

## DataSource
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/story?useUnicode=true&characterEncoding=UTF-8&useSSL=false
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=
## jpa相關配置
spring.jpa.database=MYSQL
spring.jpa.hibernate.ddl-auto=none
spring.jpa.show-sql=true
spring.jackson.serialization.indent_output=true
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

3. 數(shù)據(jù)準備

數(shù)據(jù)修改嘛,所以我們先向表里面插入兩條數(shù)據(jù),用于后面的操作

INSERT INTO `money` (`id`, `name`, `money`, `is_deleted`, `create_at`, `update_at`)
VALUES
	(20, 'jpa 一灰灰5', 2323, 0, '2019-07-02 08:42:41', '2019-07-02 08:42:41'),
	(21, 'jpa 一灰灰6', 2333, 0, '2019-07-02 08:42:41', '2019-07-02 08:42:41'),
	(22, 'jpa 一灰灰7', 6666, 0, '2019-07-02 08:42:41', '2019-07-02 08:42:41'),
	(23, 'jpa 一灰灰8', 2666, 0, '2019-07-02 08:42:41', '2019-07-02 08:42:41');

SpringBoot JPA中delete的使用方法

II. Delete使用教程

下面談及到的刪除,都是物理刪除,可以理解為直接將某些記錄從表中抹除掉(并不是說刪了就完全沒有辦法恢復)針對CURD四種操作而言,除了read之外,另外三個insert,update,delete都會加寫鎖(一般來將會涉及到行鎖和gap鎖,從后面也會看到,這三個操作要求顯示聲明事物)

1. 表關聯(lián)POJO

前面插入篇已經(jīng)介紹了POJO的逐步創(chuàng)建過程,已經(jīng)對應的注解含義,下面直接貼出成果

@Data
@DynamicUpdate
@DynamicInsert
@Entity
@Table(name = "money")
public class MoneyPO {
    @Id
    // 如果是auto,則會報異常 Table 'mysql.hibernate_sequence' doesn't exist
    // @GeneratedValue(strategy = GenerationType.AUTO)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;

    @Column(name = "name")
    private String name;

    @Column(name = "money")
    private Long money;

    @Column(name = "is_deleted")
    private Byte isDeleted;

    @Column(name = "create_at")
    @CreatedDate
    private Timestamp createAt;

    @Column(name = "update_at")
    @CreatedDate
    private Timestamp updateAt;

}

上面類中的幾個注解,說明如下

  • @Data 屬于lombok注解,與jpa無關,自動生成getter/setter/equals/hashcode/tostring等方法

  • @Entity, @Table jpa注解,表示這個類與db的表關聯(lián),具體匹配的是表 money

  • @Id @GeneratedValue 作用與自增主鍵

  • @Column表明這個屬性與表中的某列對應

  • @CreateDate根據(jù)當前時間來生成默認的時間戳

2. Repository API聲明

接下來我們新建一個api繼承自CurdRepository,然后通過這個api來與數(shù)據(jù)庫打交道

public interface MoneyDeleteRepository extends CrudRepository<MoneyPO, Integer> {
    /**
     * 查詢測試
     * @param id
     * @return
     */
    List<MoneyPO> queryByIdGreaterThanEqual(int id);
}

3. 使用姿勢

先寫一個用于查詢數(shù)據(jù)的方法,用于校驗我們執(zhí)行刪除之后,是否確實被刪除了

private void showLeft() {
    List<MoneyPO> records = moneyDeleteRepository.queryByIdGreaterThanEqual(20);
    System.out.println(records);
}

在執(zhí)行下面操作之前,先調用上面的,輸出結果如

[MoneyPO(id=20, name=jpa 一灰灰5, money=2323, isDeleted=0, createAt=2019-07-02 08:42:41.0, updateAt=2019-07-02 08:42:41.0), MoneyPO(id=21, name=jpa 一灰灰6, money=2333, isDeleted=0, createAt=2019-07-02 08:42:41.0, updateAt=2019-07-02 08:42:41.0), MoneyPO(id=22, name=jpa 一灰灰7, money=6666, isDeleted=0, createAt=2019-07-02 08:42:41.0, updateAt=2019-07-02 08:42:41.0), MoneyPO(id=23, name=jpa 一灰灰8, money=2666, isDeleted=0, createAt=2019-07-02 08:42:41.0, updateAt=2019-07-02 08:42:41.0)]
a. 根據(jù)主鍵id進行刪除

這種應該屬于最常見的刪除方式了,為了避免誤刪,通過精確的主鍵id來刪除記錄,是一個非常好的使用姿勢,CrudRepository這個接口已經(jīng)提供了對應的方法,所以我們可以直接使用

private void deleteById() {
    // 直接根據(jù)id進行刪除
    moneyDeleteRepository.deleteById(21);
    showLeft();
}

執(zhí)行完畢之后,輸出結果如下,對比前面的輸出可以知道 id=21 的記錄被刪除了

[MoneyPO(id=20, name=jpa 一灰灰5, money=2323, isDeleted=0, createAt=2019-07-02 08:42:41.0, updateAt=2019-07-02 08:42:41.0), MoneyPO(id=22, name=jpa 一灰灰7, money=6666, isDeleted=0, createAt=2019-07-02 08:42:41.0, updateAt=2019-07-02 08:42:41.0), MoneyPO(id=23, name=jpa 一灰灰8, money=2666, isDeleted=0, createAt=2019-07-02 08:42:41.0, updateAt=2019-07-02 08:42:41.0)]

然后一個疑問自然而然的來了,如果這個id對應的記錄不存在,會怎樣?

把上面代碼再執(zhí)行一次,發(fā)現(xiàn)拋了異常

SpringBoot JPA中delete的使用方法

為什么會這樣呢?我們debug進去,調用的實現(xiàn)是默認的 SimpleJpaRepository,其源碼如

// 類為: org.springframework.data.jpa.repository.support.SimpleJpaRepository
@Transactional
public void deleteById(ID id) {

	Assert.notNull(id, ID_MUST_NOT_BE_NULL);

	delete(findById(id).orElseThrow(() -> new EmptyResultDataAccessException(
			String.format("No %s entity with id %s exists!", entityInformation.getJavaType(), id), 1)));
}

@Transactional
public void delete(T entity) {

	Assert.notNull(entity, "The entity must not be null!");
	em.remove(em.contains(entity) ? entity : em.merge(entity));
}

從源碼可以看出,這個是先通過id進行查詢,如果對應的記錄不存在時,直接拋異常;當存在時,走remove邏輯;

如果我們希望刪除一個不存在的數(shù)據(jù)時,不要報錯,可以怎么辦?

  • 自定義實現(xiàn)一個繼承SimpleJpaRepository的類,覆蓋刪除方法

@Repository
@Transactional(readOnly = true)
public class MoneyDeleteRepositoryV2 extends SimpleJpaRepository<MoneyPO, Integer> {

    @Autowired
    public MoneyDeleteRepositoryV2(EntityManager em) {
        this(JpaEntityInformationSupport.getEntityInformation(MoneyPO.class, em), em);
    }

    public MoneyDeleteRepositoryV2(JpaEntityInformation<MoneyPO, ?> entityInformation, EntityManager entityManager) {
        super(entityInformation, entityManager);
    }

    public MoneyDeleteRepositoryV2(Class<MoneyPO> domainClass, EntityManager em) {
        super(domainClass, em);
    }

    @Override
    public void deleteById(Integer id) {
        Optional<MoneyPO> rec = findById(id);
        rec.ifPresent(super::delete);
    }
}

然后再調用上面的方法就可以了,不演示具體的測試case了,源碼可以到項目工程中查看 ???? 源碼

b. 條件判斷刪除

雖然根據(jù)id進行刪除比較穩(wěn)妥,但也無法避免某些情況下需要根據(jù)其他的字段來刪除,比如我們希望刪除名為 jpa 一灰灰7的數(shù)據(jù),這時則需要我們在MoneyDeleteRepository新增一個方法

/**
 * 根據(jù)name進行刪除
 *
 * @param name
 */
void deleteByName(String name);

這里比較簡單的提一下這個方法的命名規(guī)則,后面在查詢這一篇會更加詳細的說明;

  • delete 表示執(zhí)行的是刪除操作

  • By 表示根據(jù)某個字段來進行條件限定

  • Name 這個有POJO中的屬性匹配

上面這個方法,如果翻譯成sql,相當于 delete from money where name=xx

調用方式和前面一樣,如下

private void deleteByName() {
    moneyDeleteRepository.deleteByName("jpa 一灰灰7");
    showLeft();
}

然后我們執(zhí)行上面的測試,發(fā)現(xiàn)并不能成功,報錯了

SpringBoot JPA中delete的使用方法

通過前面update的學習,知道需要顯示加一個事物的注解,我們這里直接加在Repository

/**
 * 根據(jù)name進行刪除
 *
 * @param name
 */
@Transactional
void deleteByName(String name);

然后再次執(zhí)行輸出如下,這里我們把sql的日志也打印了

Hibernate: select moneypo0_.id as id1_0_, moneypo0_.create_at as create_a2_0_, moneypo0_.is_deleted as is_delet3_0_, moneypo0_.money as money4_0_, moneypo0_.name as name5_0_, moneypo0_.update_at as update_a6_0_ from money moneypo0_ where moneypo0_.name=?
Hibernate: delete from money where id=?
Hibernate: select moneypo0_.id as id1_0_, moneypo0_.create_at as create_a2_0_, moneypo0_.is_deleted as is_delet3_0_, moneypo0_.money as money4_0_, moneypo0_.name as name5_0_, moneypo0_.update_at as update_a6_0_ from money moneypo0_ where moneypo0_.id>=?
[MoneyPO(id=20, name=jpa 一灰灰5, money=2323, isDeleted=0, createAt=2019-07-02 08:42:41.0, updateAt=2019-07-02 08:42:41.0), MoneyPO(id=23, name=jpa 一灰灰8, money=2666, isDeleted=0, createAt=2019-07-02 08:42:41.0, updateAt=2019-07-02 08:42:41.0)]

從最終剩余的記錄來看,name為jpa 一灰灰7的被刪除了,再看一下前面刪除的sql,會發(fā)現(xiàn)一個有意思的地方,deleteByName 這個方法,翻譯成sql變成了兩條

  • select * from money where name=xxx 先根據(jù)name查詢記錄

  • delete from money where id = xxx 根據(jù)前面查詢記錄的id,刪除記錄

c. 比較刪除

接下來演示一個刪除money在[2000,3000]區(qū)間的記錄,這時我們新增的放入可以是

/**
 * 根據(jù)數(shù)字比較進行刪除
 *
 * @param low
 * @param big
 */
@Transactional
void deleteByMoneyBetween(Long low, Long big);

通過方法命名也可以簡單知道上面這個等同于sql delete from money where money between xxx and xxx

測試代碼為

private void deleteByCompare() {
    moneyDeleteRepository.deleteByMoneyBetween(2000L, 3000L);
    showLeft();
}

輸出日志

Hibernate: select moneypo0_.id as id1_0_, moneypo0_.create_at as create_a2_0_, moneypo0_.is_deleted as is_delet3_0_, moneypo0_.money as money4_0_, moneypo0_.name as name5_0_, moneypo0_.update_at as update_a6_0_ from money moneypo0_ where moneypo0_.money between ? and ?
Hibernate: delete from money where id=?
Hibernate: delete from money where id=?
Hibernate: select moneypo0_.id as id1_0_, moneypo0_.create_at as create_a2_0_, moneypo0_.is_deleted as is_delet3_0_, moneypo0_.money as money4_0_, moneypo0_.name as name5_0_, moneypo0_.update_at as update_a6_0_ from money moneypo0_ where moneypo0_.id>=?
[]

從拼接的sql可以看出,上面的邏輯等同于,先執(zhí)行了查詢,然后根據(jù)id一個一個進行刪除....

4. 小結

我們通過聲明方法的方式來實現(xiàn)條件刪除;需要注意

  • 刪除需要顯示聲明事物 @Transactional

  • 刪除一個不存在的記錄,會拋異常

  • 聲明刪除方法時,實際等同于先查詢記錄,然后根據(jù)記錄的id進行精準刪除

“SpringBoot JPA中delete的使用方法”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關的知識可以關注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質量的實用文章!

本文名稱:SpringBootJPA中delete的使用方法
網(wǎng)頁URL:http://jinyejixie.com/article2/peodoc.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站排名、網(wǎng)站建設、云服務器網(wǎng)站設計、外貿建站

廣告

聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站建設
射阳县| 合水县| 伊金霍洛旗| 瑞安市| 封开县| 利川市| 白山市| 赣州市| 伊春市| 昌吉市| 常宁市| 苗栗县| 秭归县| 页游| 加查县| 增城市| 廊坊市| 兰州市| 延寿县| 三穗县| 肃宁县| 嘉善县| 资阳市| 曲松县| 五寨县| 象山县| 霍邱县| 枞阳县| 兖州市| 陆良县| 镇沅| 武邑县| 潼关县| 泾阳县| 景谷| 西青区| 外汇| 英吉沙县| 天台县| 乌兰浩特市| 原阳县|