JPA使用-實體類上常用註解

  • 2019 年 12 月 19 日
  • 筆記

@SQLDelete

場景描述

JPA中提供了簡單的CRUD操作,其中刪除操作是物理刪除,但是實際應用中,系統中的數據是一種資源,不能直接刪除,應該做到邏輯刪除,JPA中刪除操作是不可取的。

場景示例

調用JPA的刪除方法,如下程式碼所示:

@Testpublic void testJpaDelete() {  //此處根據id刪除角色資訊  roleRepository.deleteById(1);}

執行上面的測試方法,數據表中主鍵為1的數據,已經被刪除掉,看下JPA的執行SQL如下所示:

delete from role where id=?

此語句為JPA刪除操作的默認執行語句。

解決方案

JPA的默認刪除方法,並不可取,可以在Role實體上加上@SQLDelete註解,並寫SQL語句,如下所示:

@SQLDelete(sql = "update role set is_deleted = 1 where id = ?")

上面的註解代表著,只要執行JPA的刪除操作,執行的SQL語句為我們自己定義的SQL語句。

測試一下

 @Testpublic void testJpaDelete() {  roleRepository.deleteById(2);}

結果列印的SQL執行語句,如下所示

update role set is_deleted = 1 where id = ?

@DynamicInsert

場景描述

在JPA中添加/更新都是使用save()方法,一般情況下,創建數據表的時候,會給某些欄位設置默認的值,避免在插入的時候手動賦值,如創建時間,是否刪除等等。

save方法會把沒有值的對象,默認賦空值,造成,原數據表的默認值失效。

場景示例

添加一個角色,如下所求

@Testpublic void testJpaAdd() {  Role role = new Role();  role.setRoleName("小碼農薛堯");  roleRepository.save(role);}

RoleAddDto對象

/** * @description: * @author: Simon.Xue * @date: 2019-02-17 22:15 **/@Datapublic class RoleAddDto implements Serializable {    /**     * 角色名     */    private String roleName;}

Role數據表的結構為

create table role(  id int not null auto_increment,  role_name varchar(32) not null comment '角色名',  create_time timestamp default current_timestamp comment '創建時間',  update_time timestamp default current_timestamp on update current_timestamp comment '更新時間',  is_deleted int default 0 comment '是否刪除',  primary key (id)) character set utf8mb4  comment '角色表';

從上面數據表的定義語句,我們可以看出來,是否刪除是有默認值0的,但是我們實現執行後的結果為

附:執行sql語句如下

insert into role (create_time, is_deleted, role_name, update_time) values (?, ?, ?, ?)

解決方案

在Role實體類上加上@DynamicUpdate註解,告訴JPA沒有值的屬性不用賦NULL值,重新添加角色如下圖所示

附:執行sql語句如下

insert into role (role_name) values (?)

@DynamicUpdate

場景描述

在JPA的使用過程中,我們常遇到更新資料庫中記錄的數據,一般情況下,我們只會把更新的值傳給save()方法,但是該方法會把沒有更新的值全部覆蓋掉。

場景示例

更新上個例子中id為8的數據,把角色名改成小明的秘密,如下所示

@Testpublic void testJpaUpdate() {  Role role = new Role();  role.setId(8);  role.setRoleName("小明的秘密");  roleRepository.save(role);}

上面第8條數據更新後,is_deleted的值被賦值為NULL

附:執行sql的語句如下:

update role set create_time=?, is_deleted=?, role_name=?, update_time=? where id=?

解決方案

在Role實體上添加@DynamicUpdate註解,重新更新第8條記錄,執行的sql語句如下

update role set create_time=?, update_time=? where id=?

@ Where

場景描述

一般情況下,查詢語句都是要帶上查詢條件,如過濾掉刪除的數據,把沒有刪除的數據查詢出來,但是JPA默認是沒有帶有任何條件。

解決方案

在實體上添加@Where註解,如下所示

@Data@Table(name = "role")@SQLDelete(sql = "update role set is_deleted = 1 where id = ?")@Entity@Accessors(chain = true)@DynamicInsert@DynamicUpdate@Where(clause = "is_deleted = 0")public class Role implements Serializable {    @Id    @GeneratedValue(strategy = GenerationType.IDENTITY)    private Integer id;      private String roleName;      private LocalDateTime createTime;    private LocalDateTime updateTime;    private Integer isDeleted;}

只要JPA調用任何Role的查詢條件都會默認帶上is_deleted = 0,如下圖所示