將應用程序進行Spring6遷移的最佳使用方式
介紹
在本文中,我們將了解如何將現(xiàn)有應用程序遷移到Spring 6以及如何充分利用此升級。
本文中的提示基于我在Hypersistence Optimizer和高性能 Java Persistence 項目中添加對 Spring 6 的支持所做的工作。
Java17
首先,Spring 6 將最低 Java 版本提升到 17 個,這太棒了,因為你現(xiàn)在可以使用文本塊和記錄。
文本塊
多虧了文本塊,您的注釋將更具可讀性:@Query
@Query(""" select p from Post p left join fetch p.comments where p.id between :minId and :maxId """) List<Post> findAllWithComments( @Param("minId") long minId, @Param("maxId") long maxId );
有關 Java 文本塊的更多詳細信息,請查看本文。
記錄
Java Records 非常適合 DTO 投影。例如,你可以像這樣定義 aclass:PostRecord
public record PostCommentRecord( Long id, String title, String review ) {}
然后,您可以使用 Spring Data JPA 查詢方法獲取對象:PostCommentRecord
@Query(""" select new PostCommentRecord( p.id as id, p.title as title, c.review as review ) from PostComment c join c.post p where p.title like :postTitle order by c.id """) List<PostCommentRecord> findCommentRecordByTitle( @Param("postTitle") String postTitle );
我們之所以可以在 JPQL 構造函數(shù)表達式中使用 theJava 的簡單名稱,是因為我從Hibernate Type 項目中注冊了以下內容:PostCommentRecordClassClassImportIntegrator
properties.put( "hibernate.integrator_provider", (IntegratorProvider) () -> Collections.singletonList( new ClassImportIntegrator( List.of( PostCommentRecord.class ) ) ) );
有關 Java 記錄的更多詳細信息,請查看本文。
這還不是全部!Java 17 改進了 forand 的錯誤消息,并添加了模式匹配 forand。NullPointerExceptionswitchinstanceOf
JPA 3.1
默認情況下,Spring 6 使用 Hibernate 6.1,而 Hibernate 6.1 又使用 Jakarta Persistence 3.1。
現(xiàn)在,3.0版本標志著從Java持久性到Jakarta Patersistence的遷移,因此,出于這個原因,您必須將軟件包導入替換為命名空間。javax.persistencejakarta.persistence
這是遷移到 JPA 3 必須進行的最重要的更改。與此同時,發(fā)布了3.1版本,但這個版本只包括Hibernate已經支持的一些小改進。
UUID 實體屬性
例如,JPA 3 現(xiàn)在支持基本類型:UUID
@Column( name = "external_id", columnDefinition = "UUID NOT NULL" ) private UUID externalId;
您甚至可以將它們用作實體標識符:
@Id @GeneratedValue(strategy = GenerationType.UUID) private UUID id;
但這只是一個糟糕的主意,因為使用 anfor 主鍵會導致很多問題:UUID
- 索引頁將很少填充,因為每個新的 UUID 都將在 B+樹聚集索引中隨機添加。
- 由于主鍵值的隨機性,將會有更多的頁面拆分
- UUID很大,需要的字節(jié)數(shù)是列的兩倍。它不僅影響主鍵,還影響所有關聯(lián)的外鍵。
bigint
此外,如果您使用的是SQL Server,MySQL或MariaDB,則默認表將被組織為聚簇索引,從而使所有這些問題變得更糟。
因此,最好避免使用 for 實體標識符。如果您確實需要從應用程序生成唯一標識符,那么最好使用64 位時間排序的隨機 TSID。UUID
新的 JPQL 函數(shù)
JPQL 通過許多新功能得到了增強,例如,,,,,,數(shù)字函數(shù)。CEILINGFLOOREXPLNPOWERROUNDSIGN
但是,我發(fā)現(xiàn)最有用的是日期/時間函數(shù):EXTRACT
List<Post> posts = entityManager.createQuery(""" select p from Post p where EXTRACT(YEAR FROM createdOn) = :year """, Post.class) .setParameter("year", Year.now().getValue()) .getResultList();
這很有用,因為日期/時間處理通常需要特定于數(shù)據(jù)庫的函數(shù),并且擁有一個可以呈現(xiàn)適當?shù)奶囟ㄓ跀?shù)據(jù)庫的函數(shù)的泛型函數(shù)肯定很方便。
可自動關閉的實體管理器和實體管理器工廠
雖然Hibernateand已經擴展了接口,但現(xiàn)在JPAand也遵循了這種做法:SessionSessionFactoryAutoClosableEntityManagerEntityManagerFactory
Although you might rarely need to rely on that because Spring takes care of the on your behalf, it’s very handy when you have to process the programmatically.EntityManagerEntityManager
冬眠 6
雖然Java 17和JPA 3.1為您帶來了一些功能,但Hibernate 6提供了大量的增強功能。
JDBC 優(yōu)化
以前,Hibernate使用關聯(lián)的列別名讀取JDBC列值,這被證明很慢。出于這個原因,Hibernate 6 已切換到按基礎 SQL 投影中的位置讀取基礎列值。ResultSet
除了速度更快之外,進行此更改還有一個非常好的副作用。基礎 SQL 查詢現(xiàn)在更具可讀性。
例如,如果您在 Hibernate 5 上運行此 JPQL 查詢:
Post post = entityManager.createQuery(""" select p from Post p join fetch p.comments where p.id = :id """, Post.class) .setParameter("id", 1L) .getSingleResult();
將執(zhí)行以下 SQL 查詢:
SELECT bidirectio0_.id AS id1_0_0_, comments1_.id AS id1_1_1_, bidirectio0_.title AS title2_0_0_, comments1_.post_id AS post_id3_1_1_, comments1_.review AS review2_1_1_, comments1_.post_id AS post_id3_1_0__, comments1_.id AS id1_1_0__ FROM post bidirectio0_ INNER JOIN post_comment comments1_ ON bidirectio0_.id=comments1_.post_id WHERE bidirectio0_.id=1
如果您在Hibernate 6上運行相同的JPQL,將如何改為運行以下SQL查詢:
SELECT p1_0.id, c1_0.post_id, c1_0.id, c1_0.review, p1_0.title FROM post p1_0 JOIN post_comment c1_0 ON p1_0.id=c1_0.post_id WHERE p1_0.id = 1
好多了,對吧?
語義查詢模型和條件查詢
Hibernate 6提供了一個全新的實體查詢解析器,能夠從JPQL和Criteria API生成規(guī)范模型,即語義查詢模型。
通過統(tǒng)一實體查詢模型,現(xiàn)在可以使用 Jakarta 持久性不支持的功能(如派生表或公用表表達式)來增強條件查詢。
有關 Hibernate 語義查詢模型的更多詳細信息,請查看本文。
舊的休眠標準已被刪除,但標準 API 已通過 提供許多新功能得到增強。HibernateCriteriaBuilder
例如,您可以使用函數(shù)進行不區(qū)分大小寫的 LIKE 匹配:ilike
HibernateCriteriaBuilder builder = entityManager .unwrap(Session.class) .getCriteriaBuilder(); CriteriaQuery<Post> criteria = builder.createQuery(Post.class); Root<Post> post = criteria.from(Post.class); ParameterExpression<String> parameterExpression = builder .parameter(String.class); List<Post> posts = entityManager.createQuery( criteria .where( builder.ilike( post.get(Post_.TITLE), parameterExpression) ) .orderBy( builder.asc( post.get(Post_.ID) ) ) ) .setParameter(parameterExpression, titlePattern) .setMaxResults(maxCount) .getResultList();
但是,這只是一個基本示例。使用新的,您現(xiàn)在可以渲染:HibernateCriteriaBuilder
方言增強功能
在Hibernate 5中,您必須根據(jù)底層數(shù)據(jù)庫版本選擇大量版本,這在Hibernate 6中得到了極大的簡化:Dialect
此外,您甚至不需要在 Spring 配置中提供,因為它可以從 JDBC 解析。DialectDatabaseMetaData
有關此主題的更多詳細信息,請查看此文章。
自動重復數(shù)據(jù)刪除
您還記得在使用時為實體重復數(shù)據(jù)刪除提供關鍵字是多么煩人嗎?DISTINCTJOIN FETCH
List<Post> posts = entityManager.createQuery(""" select distinct p from Post p left join fetch p.comments where p.title = :title """, Post.class) .setParameter("title", "High-Performance Java Persistence") .setHint(QueryHints.HINT_PASS_DISTINCT_THROUGH, false) .getResultList();
如果你忘記發(fā)送提示,那么Hibernate 5會將關鍵字傳遞給SQL查詢,并導致執(zhí)行計劃運行一些額外的步驟,這些步驟只會讓你的查詢變慢:PASS_DISTINCT_THROUGHDISTINCT
Unique (cost=23.71..23.72 rows=1 width=1068) (actual time=0.131..0.132 rows=2 loops=1) -> Sort (cost=23.71..23.71 rows=1 width=1068) (actual time=0.131..0.131 rows=2 loops=1) Sort Key: p.id, pc.id, p.created_on, pc.post_id, pc.review Sort Method: quicksort Memory: 25kB -> Hash Right Join (cost=11.76..23.70 rows=1 width=1068) (actual time=0.054..0.058 rows=2 loops=1) Hash Cond: (pc.post_id = p.id) -> Seq Scan on post_comment pc (cost=0.00..11.40 rows=140 width=532) (actual time=0.010..0.010 rows=2 loops=1) -> Hash (cost=11.75..11.75 rows=1 width=528) (actual time=0.027..0.027 rows=1 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 9kB -> Seq Scan on post p (cost=0.00..11.75 rows=1 width=528) (actual time=0.017..0.018 rows=1 loops=1) Filter: ( (title)::text = 'High-Performance Java Persistence eBook has been released!'::text ) Rows Removed by Filter: 3
有關 JPA 中如何工作的更多詳細信息,請同時閱讀本文。
DISTINCT
情況不再如此,因為現(xiàn)在實體對象引用重復數(shù)據(jù)刪除是自動完成的,因此您的查詢不再需要關鍵字:JOIN FETCHDISTINCT
List<Post> posts = entityManager.createQuery(""" select p from Post p left join fetch p.comments where p.title = :title """, Post.class) .setParameter("title", "High-Performance Java Persistence") .getResultList();
結論
Spring 6 真的值得升級到。除了受益于Java 17提供的所有語言優(yōu)化之外,所有其他框架依賴項還提供了大量新功能,這些依賴項已集成到Spring 6中。
例如,Hibernate 6提供了許多優(yōu)化和新功能,可以滿足您的許多日常數(shù)據(jù)訪問需求。
到此這篇關于將應用程序進行Spring6遷移的最佳方式的文章就介紹到這了,更多相關Spring6遷移的最佳方式內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
關于Java中配置ElasticSearch集群環(huán)境賬號密碼的問題
這篇文章主要介紹了Java中配置ElasticSearch集群環(huán)境賬號密碼的問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-04-04java開發(fā)使用StringUtils.split避坑詳解
這篇文章主要為大家介紹了java開發(fā)使用StringUtils.split避坑詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-11-11