欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

分享JPA的幾個小技巧

 更新時間:2021年03月12日 09:59:41   作者:小姐姐味道  
這篇文章主要分享了JPA的幾個小技巧,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下

關(guān)系型數(shù)據(jù)庫其實很討人厭,尤其是在你使用數(shù)據(jù)庫驅(qū)動的開發(fā)模式時。需要首先把表給創(chuàng)建好了,然后再使用代碼生成器反向生成一堆幾乎無法可讀的代碼。當字段有變更的時候,又是一番折騰。

這其中的典型,就是MyBatis,所以催生了更加簡潔的MyBatis Plus。

了解到一些大廠(阿里、騰訊、抖音等),JPA的使用也越來越廣泛了,包括我們公司,這是把合適的工具放到了合適的地方。如果想要快速開發(fā),JPA無疑是一個比較好的選擇。你無需關(guān)注數(shù)據(jù)庫表的結(jié)構(gòu),使用代碼驅(qū)動即可完成工作,管它后面是MySQL還是Oracle。JPA把數(shù)據(jù)庫相關(guān)的知識給弱化了,讓你專注于業(yè)務(wù)開發(fā)。

我個人曾是非常排斥JPA這種弱化SQL的工具的,這源于對早起Hibernate版本的錯誤認識。但嘗試過mybatis、spring-data-jdbc、jooq后,發(fā)現(xiàn)這個東西是真的香!一個遲到的贊,送給JPA。

這對一些管理系統(tǒng)來說,非常合適。因為性能并不是這些系統(tǒng)主要的痛點,業(yè)務(wù)復(fù)雜性才是。

本文將介紹一個簡單的實體類,需要準備哪些基本字段。這些字段,又是如何在代碼中被使用的。

1. 基本字段介紹

首先看一下我們的基礎(chǔ)定義類。

代碼不多,信息卻不少。

下面來一行行解析。

@Data

Data注解是屬于lombok類的,lombok是地球人都知道的代碼簡化工具,提供了非常多的注解。如果你不想記憶太多的注解,直接加上一個Data,是最偷懶的選擇。

@MappedSuperclass

這個注解是JPA的,用來標識父類。標注為@MappedSuperclass的類將不是一個完整的實體類,不會映射到數(shù)據(jù)庫表,但是它的屬性都將映射到子類的數(shù)據(jù)庫字段中。放在這里再合適不過了。

@EntityListeners(AuditingEntityListener.class)

開啟自動審計功能,這個和下面的兩個日期字段是相互配合的,我們稍后介紹。

@JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler"}) //直接使用bean時,避免json序列號失敗

有時候,我們想要再controller層直接使用JPA的實體。但JPA內(nèi)部其實是有很多附加變量的,比如hibernateLazyInitializer。

為了讓實體在json序列化的時候能夠正常進行,需要忽略這兩個字段。所以這個注解,是屬于jackson json的。

2. 自定義ID生成器

JPA其實提供了非常多的ID生成策略。不過,在互聯(lián)網(wǎng)應(yīng)用下,應(yīng)用較多的還是雪花算法,因為它有著良好的擴展性,在數(shù)據(jù)遷移的時候也不會有很多沖突。

為了指定雪花算法,我們需要下面幾行代碼。

 static final String ID_GEN = "cn.xjjdog.bcmall.utils.db.DistributedId";
 @Id
 @GenericGenerator(name = "IdGen", strategy = ID_GEN)
 @GeneratedValue(generator = "IdGen")

其中的一個關(guān)鍵,就是使用我們名稱叫做IdGen的ID生成器。這里的代碼,是有一點小遺憾的。由于JVM類加載的緣故,我們無法在注解中直接使用類的名稱(*.class.getName()) 來獲取它的包路徑,只能作為字符串寫死在這里。

下面我們就來看一下這個ID生成器的處理。

public class DistributedId implements IdentifierGenerator {
 @Override
 public Serializable generate(SharedSessionContractImplementor sharedSessionContractImplementor, Object obj) throws HibernateException {
  if (obj == null) throw new HibernateException(new NullPointerException()) ;
  if ((((AbstractEntity) obj).getId()) == null) {
   return String.valueOf(Snowflake.createId());
  } else {
   return ((AbstractEntity) obj).getId();
  }
 }
}

代碼如上。在直接使用之前,我們還做了一點小處理。當我們判斷實體的ID為空的時候,才使用雪花算法構(gòu)造一個新的ID;否則使用實體原來設(shè)置好的ID,保持不變。

為什么這樣做?因為這是有需求的。像訂單這種業(yè)務(wù),你需要先生成一個訂單號,然后再更新一些數(shù)據(jù)庫信息,發(fā)布一些消息等;而不是在保存動作出發(fā)的時候才生成一個。

如果你不做上面代碼的處理。JPA將每次保存的時候都自動生成一個,覆蓋了你原有的。我就在這里吃過虧,通過debug代碼才進行的修復(fù)。

3. 自動填充字段

上面說到createdDatelastModifiedDate兩個字段,其實在使用的時候,是不需要手動去設(shè)值的。這兩個值,將通過審計功能自動完成。

@EntityListeners(AuditingEntityListener.class)

當然,我們還要用特有的注解,來標識這兩個字段。

/**
* 創(chuàng)建時間
*/
@CreatedDate
private Date createdDate;

/**
 * 更新時間
*/
@LastModifiedDate
private Date lastModifiedDate;

最后,不要忘了在全局配置中通過Config開啟這個功能。

@Configuration
@EnableJpaAuditing
public class JpaConfig {
}

當然,審計是不能沒有用戶的。所以這個系列還有@CreatedBy注解,用來標注是誰創(chuàng)建的。你需要在代碼中組裝它們,比如下面的代碼,就是從Spring Sercurity中獲取用戶信息。

@Configuration
@Slf4j
public class UserAuditor implements AuditorAware<String> {
 @Override
 public Optional<String> getCurrentAuditor() {
  UserDetails user;
  try {
   user = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
   return Optional.ofNullable(user.getUsername());
  }catch (Exception e){
   return Optional.empty();
  }
 }
}

4. End

JPA寫管理系統(tǒng),真的是神器。當你不需要考慮極限的代碼效率時,是一個非常好的選擇。再看看最近的MyBatis版本,包括MyBatis Plus設(shè)計,很多東西已經(jīng)和JPA越來越像了。因為在設(shè)計上來說,JPA是最接近面向?qū)ο缶幊痰乃枷氲摹?/p>

B端復(fù)雜業(yè)務(wù)的技術(shù)棧,并不需要和C端的技術(shù)棧相雷同。JPA顯然通過極少的代碼和約定,就能把事情搞定,讓開發(fā)者真正的把重點關(guān)注到業(yè)務(wù)開發(fā)上來。后面的文章,我們還會用到MyBatis和MyBatis Plus,到時候,我們再詳細分析它們使用的場景。

以上就是分享JPA的幾個小技巧的詳細內(nèi)容,更多關(guān)于JPA 技巧的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Springboot+hibernate實現(xiàn)簡單的增刪改查示例

    Springboot+hibernate實現(xiàn)簡單的增刪改查示例

    今天小編就為大家分享一篇Springboot+hibernate實現(xiàn)簡單的增刪改查示例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-08-08
  • 一文精通Java 多線程之全方位解讀

    一文精通Java 多線程之全方位解讀

    Java 給多線程編程提供了內(nèi)置的支持。 一條線程指的是進程中一個單一順序的控制流,一個進程中可以并發(fā)多個線程,每條線程并行執(zhí)行不同的任務(wù),多線程是多任務(wù)的一種特別的形式,但多線程使用了更小的資源開銷
    2021-10-10
  • 單例模式 分析代碼優(yōu)化方法

    單例模式 分析代碼優(yōu)化方法

    這篇文章主要介紹了單例模式 分析代碼優(yōu)化方法,需要的朋友可以參考下
    2015-04-04
  • spring-retry組件的使用教程

    spring-retry組件的使用教程

    Spring Retry的主要目的是為了提高系統(tǒng)的可靠性和容錯性,當方法調(diào)用失敗時,Spring Retry可以在不影響系統(tǒng)性能的情況下,自動進行重試,從而減少故障對系統(tǒng)的影響,這篇文章主要介紹了spring-retry組件的使用,需要的朋友可以參考下
    2023-06-06
  • JSONObject?toJSONString錯誤的解決

    JSONObject?toJSONString錯誤的解決

    這篇文章主要介紹了JSONObject?toJSONString錯誤的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • 詳解Java面向?qū)ο缶幊讨鄳B(tài)

    詳解Java面向?qū)ο缶幊讨鄳B(tài)

    這篇文章主要為大家介紹了Java面向?qū)ο缶幊讨鄳B(tài),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-01-01
  • Java1.8中LocalDate方法使用總結(jié)

    Java1.8中LocalDate方法使用總結(jié)

    LocalDate是Java8中的一個日期類,用于表示年月日,它是不可變的,線程安全的,下面這篇文章主要給大家介紹了關(guān)于Java1.8中LocalDate方法使用的相關(guān)資料,需要的朋友可以參考下
    2024-03-03
  • Java中兩個字符串進行大小比較的方法

    Java中兩個字符串進行大小比較的方法

    這篇文章主要介紹了Java中兩個字符串進行大小比較,符串是否相等比較,只能使用equals()方法,不能使用“==”,本文通過示例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2022-12-12
  • SpringBoot整合resilience4j實現(xiàn)接口限流

    SpringBoot整合resilience4j實現(xiàn)接口限流

    最近在開發(fā)項目的時候,需要用到限流的功能,本文主要介紹了SpringBoot整合resilience4j實現(xiàn)接口限流,具有一定的參考價值,感興趣的可以了解一下
    2024-01-01
  • java8新特性-Stream入門學習心得

    java8新特性-Stream入門學習心得

    這篇文章主要介紹了java8新特性-Stream入門學習心得,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03

最新評論