最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring Data JPA 與 MyBatis 全方位深度解析與實(shí)戰(zhàn)指南

 更新時(shí)間:2026年03月21日 11:49:03   作者:油墨香^_^  
隨著Spring Boot的興起,Spring Data JPA 和 MyBatis 成為了最主流的兩個(gè)持久化解決方案,本文介紹Spring Data JPA與MyBatis全方位深度解析與實(shí)戰(zhàn)指南,感興趣的朋友一起看看吧

1. 引言

在 Java 企業(yè)級(jí)應(yīng)用開發(fā)領(lǐng)域,持久層框架的選擇始終是架構(gòu)設(shè)計(jì)中的關(guān)鍵決策之一。隨著 Spring Boot 的興起,Spring Data JPA 和 MyBatis 成為了最主流的兩個(gè)持久化解決方案。它們分別代表了兩種不同的設(shè)計(jì)哲學(xué):約定優(yōu)于配置的 ORM 自動(dòng)化 與 精細(xì)化控制的 SQL 自由。本文將從底層原理、開發(fā)效率、性能調(diào)優(yōu)、維護(hù)成本、生態(tài)整合等二十多個(gè)維度,對(duì)兩者進(jìn)行史上最詳盡的對(duì)比,并結(jié)合實(shí)際項(xiàng)目經(jīng)驗(yàn)給出選型建議和個(gè)人偏好,全文約 2 萬字,旨在為開發(fā)者提供一份終極參考指南。

2. 持久層框架演進(jìn)簡(jiǎn)史

在深入對(duì)比之前,有必要回顧一下 Java 持久層技術(shù)的發(fā)展歷程,這有助于理解 JPA 和 MyBatis 產(chǎn)生的背景。

  • JDBC 時(shí)代:開發(fā)者直接編寫 SQL,手動(dòng)處理 Connection、Statement、ResultSet,代碼冗長(zhǎng)且易出錯(cuò)。
  • Hibernate 崛起:作為全自動(dòng) ORM 框架,Hibernate 通過對(duì)象-關(guān)系映射,讓開發(fā)者幾乎可以脫離 SQL,以面向?qū)ο蟮姆绞讲僮鲾?shù)據(jù)庫。它引入了 HQL(Hibernate Query Language)和強(qiáng)大的緩存機(jī)制,極大提高了開發(fā)效率。
  • JPA 規(guī)范誕生:為了統(tǒng)一 Java ORM 標(biāo)準(zhǔn),Sun 公司提出了 JPA(Java Persistence API)規(guī)范,Hibernate 成為其默認(rèn)實(shí)現(xiàn)之一。JPA 定義了實(shí)體映射、實(shí)體管理器、查詢語言(JPQL)等標(biāo)準(zhǔn) API。
  • Spring Data JPA:Spring 在 JPA 之上進(jìn)一步封裝,提供了 Repository 抽象層,通過方法名推導(dǎo)查詢,進(jìn)一步簡(jiǎn)化了數(shù)據(jù)訪問層的開發(fā)。
  • MyBatis 前身 iBATIS:與 Hibernate 的“全自動(dòng)”不同,iBatis 是一個(gè)“半自動(dòng)”持久化框架。它沒有將對(duì)象與數(shù)據(jù)庫表完全映射,而是將 SQL 語句作為配置的核心,開發(fā)者需要自己編寫 SQL,框架負(fù)責(zé)參數(shù)映射和結(jié)果集封裝。后來遷移到 Google Code 并更名為 MyBatis。
  • 當(dāng)前格局:Spring Data JPA 與 MyBatis 分別在追求開發(fā)效率和靈活控制的開發(fā)者群體中擁有大量擁躉,兩者在 GitHub 上的 Star 數(shù)、社區(qū)活躍度均居高不下。

3. Spring Data JPA 深度解析

3.1 什么是 Spring Data JPA

Spring Data JPA 是 Spring Data 家族中對(duì) JPA 規(guī)范的一站式解決方案。它底層默認(rèn)使用 Hibernate 作為 JPA 實(shí)現(xiàn),但也可以切換為 EclipseLink 等其他實(shí)現(xiàn)。它提供了以下核心功能:

  • Repository 抽象:通過繼承 JpaRepository 等接口,自動(dòng)獲得 CRUD、分頁、排序等基礎(chǔ)方法。
  • 方法名查詢:根據(jù)方法名(如 findByLastNameAndFirstName)自動(dòng)生成 JPQL 查詢。
  • @Query 注解:支持自定義 JPQL 或原生 SQL。
  • 審計(jì)功能:自動(dòng)填充創(chuàng)建人、創(chuàng)建時(shí)間等字段。
  • 實(shí)體映射注解:使用 @Entity@Table@Column@OneToMany 等注解定義對(duì)象關(guān)系。

3.2 JPA 核心原理:ORM 與持久化上下文

JPA 的核心思想是 對(duì)象關(guān)系映射(ORM),將數(shù)據(jù)庫表映射為 Java 對(duì)象,將表之間的關(guān)系(如外鍵)映射為對(duì)象之間的引用(如 List<Order>)。

3.2.1 實(shí)體生命周期與狀態(tài)

JPA 定義了實(shí)體的四種狀態(tài):

  • 瞬時(shí)態(tài)(Transient):剛用 new 創(chuàng)建,未與 EntityManager 關(guān)聯(lián),數(shù)據(jù)庫中無對(duì)應(yīng)記錄。
  • 托管態(tài)(Managed):與 EntityManager 關(guān)聯(lián),任何屬性變更都會(huì)在事務(wù)提交時(shí)同步到數(shù)據(jù)庫。
  • 游離態(tài)(Detached):事務(wù)已提交,EntityManager 關(guān)閉,對(duì)象不再受管理,但數(shù)據(jù)庫中有對(duì)應(yīng)記錄。
  • 刪除態(tài)(Removed):調(diào)用 remove() 方法,計(jì)劃從數(shù)據(jù)庫中刪除。

3.2.2 持久化上下文(Persistence Context)

持久化上下文是 EntityManager 維護(hù)的一級(jí)緩存,它存儲(chǔ)了所有托管態(tài)實(shí)體的快照。當(dāng)執(zhí)行查詢時(shí),JPA 會(huì)先檢查上下文中是否存在,避免重復(fù)查詢。當(dāng)事務(wù)提交時(shí),Hibernate 通過臟檢查機(jī)制,比對(duì)實(shí)體當(dāng)前狀態(tài)與快照,自動(dòng)生成 UPDATE 語句更新變化的部分。

3.3 Spring Data JPA 優(yōu)勢(shì)

  • 極速開發(fā):無需編寫 SQL 和基礎(chǔ) DAO 實(shí)現(xiàn),一個(gè)接口加方法名即可完成大多數(shù)查詢。
  • 對(duì)象導(dǎo)向:開發(fā)者可以專注于領(lǐng)域模型設(shè)計(jì),通過關(guān)聯(lián)關(guān)系直接導(dǎo)航數(shù)據(jù),如 order.getCustomer().getAddress()。
  • 數(shù)據(jù)庫無關(guān)性:JPA 的 JPQL 是針對(duì)實(shí)體對(duì)象的查詢語言,底層會(huì)根據(jù)配置的方言翻譯成不同數(shù)據(jù)庫的 SQL,便于切換數(shù)據(jù)庫。
  • 緩存機(jī)制:內(nèi)置一級(jí)緩存,可配置二級(jí)緩存和查詢緩存,減少數(shù)據(jù)庫訪問。
  • 與 Spring 生態(tài)無縫集成:聲明式事務(wù)、Repository 的自動(dòng)實(shí)現(xiàn),與 Spring Boot 自動(dòng)配置完美結(jié)合。

3.4 Spring Data JPA 潛在挑戰(zhàn)

  • 學(xué)習(xí)曲線陡峭:需要理解實(shí)體狀態(tài)、懶加載、N+1 問題、緩存機(jī)制等概念,新手容易踩坑。
  • 復(fù)雜查詢乏力:多表關(guān)聯(lián)、子查詢、動(dòng)態(tài)排序等場(chǎng)景下,JPQL 或方法名推導(dǎo)可能變得冗長(zhǎng)難懂,甚至無法實(shí)現(xiàn),最終仍要回歸原生 SQL。
  • SQL 不可見:自動(dòng)生成的 SQL 可能不是最優(yōu)的,尤其在關(guān)聯(lián)查詢時(shí)容易產(chǎn)生 N+1 條 SQL 的性能陷阱,需要借助工具(如 p6spy)監(jiān)控。
  • 靈活性受限:某些數(shù)據(jù)庫特性(如 PostgreSQL 的 JSON 字段、全文檢索)難以通過標(biāo)準(zhǔn) JPA 支持,需要擴(kuò)展或?qū)懺?SQL。
  • 性能調(diào)優(yōu)門檻高:需要深入理解 Hibernate 的緩存、抓取策略(FetchType)、批量操作等才能寫出高性能代碼。

4. MyBatis 深度解析

4.1 什么是 MyBatis

MyBatis 是一個(gè)半自動(dòng)的持久層框架,它避免了 JDBC 的繁瑣代碼,但保留了 SQL 的完全控制權(quán)。開發(fā)者編寫 SQL 語句(XML 或注解方式),MyBatis 負(fù)責(zé)將 Java 對(duì)象映射到 SQL 參數(shù),并將查詢結(jié)果集映射為 Java 對(duì)象。

核心組件包括:

  • SqlSessionFactory:基于配置文件構(gòu)建,用于創(chuàng)建 SqlSession。
  • SqlSession:代表一次數(shù)據(jù)庫會(huì)話,提供執(zhí)行 SQL 的方法。
  • Mapper 接口:定義數(shù)據(jù)訪問方法,MyBatis 通過動(dòng)態(tài)代理自動(dòng)生成實(shí)現(xiàn)類,將方法調(diào)用與 XML/注解中的 SQL 綁定。
  • 動(dòng)態(tài) SQL:通過 <if><where><foreach> 等標(biāo)簽,在 XML 中編寫靈活的條件 SQL。

4.2 MyBatis 核心原理:SQL 映射與動(dòng)態(tài)代理

MyBatis 的工作流程如下:

  • 解析配置文件(mybatis-config.xml)和 Mapper 文件(XML 或注解),構(gòu)建 Configuration 對(duì)象。
  • 通過 Configuration 創(chuàng)建 SqlSessionFactory。
  • 每次請(qǐng)求打開 SqlSession,從 Configuration 中獲取 MappedStatement(代表一條 SQL 定義)。
  • 通過動(dòng)態(tài)代理生成 Mapper 接口的實(shí)現(xiàn)類,調(diào)用時(shí)執(zhí)行對(duì)應(yīng)的 SQL。
  • 使用參數(shù)處理器(ParameterHandler)設(shè)置 PreparedStatement 的參數(shù)。
  • 執(zhí)行 SQL,通過結(jié)果集處理器(ResultSetHandler)將結(jié)果映射為 Java 對(duì)象(支持自動(dòng)映射或自定義映射)。
  • 提交或回滾事務(wù),關(guān)閉 SqlSession。

4.3 MyBatis 優(yōu)勢(shì)

  • SQL 完全可控:開發(fā)者親自編寫和優(yōu)化 SQL,對(duì)最終執(zhí)行的 SQL 了如指掌,便于 DBA 審核和調(diào)優(yōu)。
  • 靈活的動(dòng)態(tài) SQL:通過 XML 標(biāo)簽構(gòu)建復(fù)雜動(dòng)態(tài)查詢,比拼接字符串更安全、可讀。
  • 性能極致優(yōu)化:可針對(duì)特定查詢使用數(shù)據(jù)庫特性(如 MySQL 的 FOR UPDATE、LIMIT 優(yōu)化),無中間層自動(dòng)生成的損耗。
  • 簡(jiǎn)單易學(xué):核心概念簡(jiǎn)單,只要會(huì)寫 SQL 就能快速上手,文檔詳盡。
  • 與 POJO 解耦:結(jié)果映射靈活,可以將查詢結(jié)果映射為任意類型的 POJO 或 Map,無需與表結(jié)構(gòu)嚴(yán)格對(duì)應(yīng)。
  • 適合遺留數(shù)據(jù)庫:對(duì)于表結(jié)構(gòu)不規(guī)范、字段命名混亂的舊系統(tǒng),MyBatis 可以手動(dòng)映射,而 JPA 的約定可能很難適配。

4.4 MyBatis 潛在挑戰(zhàn)

  • 開發(fā)效率較低:需要為每個(gè) CRUD 操作編寫 SQL,包括簡(jiǎn)單的增刪改查,存在大量重復(fù)勞動(dòng)。雖有代碼生成器(如 MyBatis Generator)輔助,但維護(hù)成本仍高于 JPA。
  • 對(duì)象導(dǎo)航困難:MyBatis 不支持自動(dòng)的懶加載和關(guān)聯(lián)對(duì)象導(dǎo)航(雖然有 association 和 collection 可以實(shí)現(xiàn)嵌套結(jié)果,但本質(zhì)是一次 SQL 關(guān)聯(lián)查詢,或者需手動(dòng)調(diào)用二次查詢),代碼中通常需要顯式調(diào)用相關(guān)查詢。
  • 緩存機(jī)制較弱:默認(rèn)只開啟了一級(jí)緩存(SqlSession 級(jí)別),二級(jí)緩存需要配置且易出現(xiàn)臟數(shù)據(jù),功能不如 Hibernate 強(qiáng)大。
  • 數(shù)據(jù)庫耦合性高:SQL 是特定數(shù)據(jù)庫的,切換數(shù)據(jù)庫需重寫 SQL,增加了遷移成本。
  • XML 配置繁瑣:大量的 Mapper XML 文件,維護(hù)起來可能顯得雜亂,雖然注解方式可部分緩解,但復(fù)雜 SQL 仍離不開 XML。

5. 全方位對(duì)比

5.1 開發(fā)效率對(duì)比

5.1.1 代碼量

Spring Data JPA:對(duì)于單表 CRUD,幾乎零代碼。只需定義實(shí)體和繼承 JpaRepository 接口,即可使用大量?jī)?nèi)置方法。復(fù)雜查詢可以通過方法名推導(dǎo)或簡(jiǎn)單 JPQL 完成,代碼量極少。

MyBatis:即使是簡(jiǎn)單的單表查詢,也需要編寫 SQL。使用代碼生成器可以生成基礎(chǔ) SQL,但后續(xù)維護(hù)仍要修改 XML 或注解。對(duì)于多表關(guān)聯(lián)查詢,MyBatis 的 SQL 編寫工作量與 JPA 的 JPQL 相當(dāng),但 JPA 可能通過關(guān)聯(lián)映射自動(dòng)生成 JOIN,而 MyBatis 需要手動(dòng)編寫 JOIN 語句。

結(jié)論:Spring Data JPA 勝出,開發(fā)效率顯著更高。

5.1.2 學(xué)習(xí)曲線

Spring Data JPA:入門簡(jiǎn)單(會(huì)用 savefindById 即可),但要深入掌握避免性能問題,需要學(xué)習(xí)大量概念:實(shí)體狀態(tài)、懶加載、抓取策略、N+1 解決方案、緩存、繼承映射等。對(duì)于新手,容易寫出低效代碼而不自知。

MyBatis:學(xué)習(xí)曲線平緩,核心是 SQL 和映射配置。只要熟悉 SQL 語法,很快就能上手。深入學(xué)習(xí)主要是動(dòng)態(tài) SQL 標(biāo)簽和緩存配置,相對(duì)直觀。

結(jié)論:MyBatis 的學(xué)習(xí)曲線更平緩,但 JPA 一旦掌握,后續(xù)開發(fā)效率更高。

5.1.3 配置復(fù)雜度

Spring Data JPA:只需配置數(shù)據(jù)源、JPA 屬性(如方言、DDL 自動(dòng)生成),加上簡(jiǎn)單的 @Entity 注解,即可運(yùn)行。Spring Boot 自動(dòng)配置極大簡(jiǎn)化。

MyBatis:需要配置數(shù)據(jù)源、MyBatis 自身配置(如別名包、Mapper 位置),每個(gè) Mapper 需在 XML 或接口中定義 SQL。整體配置稍顯繁瑣,但也在可接受范圍。

結(jié)論:兩者配置都較簡(jiǎn)單,JPA 略勝一籌。

5.2 靈活性對(duì)比

5.2.1 復(fù)雜查詢支持

Spring Data JPA:JPQL 支持大多數(shù) SQL 功能,但某些高級(jí)特性(如窗口函數(shù)、CTE、JSON 查詢)無法直接使用,需借助原生 SQL。動(dòng)態(tài)查詢可通過 JpaSpecificationExecutor 或 @Query 拼接,但比較笨拙。QueryDSL 可增強(qiáng)類型安全動(dòng)態(tài)查詢,但引入額外復(fù)雜度。

MyBatis:原生 SQL 支持所有數(shù)據(jù)庫特性,動(dòng)態(tài) SQL 標(biāo)簽(<if><choose><where><foreach>)非常強(qiáng)大且易讀,幾乎可以模擬任何復(fù)雜條件組合。對(duì)于存儲(chǔ)過程、函數(shù)調(diào)用也支持良好。

結(jié)論:MyBatis 在靈活性上完勝,尤其適合復(fù)雜報(bào)表、多條件搜索等場(chǎng)景。

5.2.2 動(dòng)態(tài) SQL

Spring Data JPA:可以通過 @Query 中寫 JPQL 條件拼接,但字符串拼接易出錯(cuò);或者使用 Specification 構(gòu)建動(dòng)態(tài)條件,但需要熟悉 JPA 的 Criteria API,代碼冗長(zhǎng)且難懂。簡(jiǎn)單動(dòng)態(tài)查詢可用方法名推導(dǎo)(如 findByTitleContainingAndAuthor),但條件組合有限。

MyBatis:XML 中的動(dòng)態(tài) SQL 標(biāo)簽是核心優(yōu)勢(shì),利用 <if> 判斷參數(shù)是否為空, <where> 自動(dòng)處理多余的 AND/OR, <foreach> 處理 IN 集合,清晰強(qiáng)大。對(duì)于極其復(fù)雜的動(dòng)態(tài)查詢,MyBatis 依然游刃有余。

結(jié)論:MyBatis 動(dòng)態(tài) SQL 完勝。

5.2.3 存儲(chǔ)過程支持

Spring Data JPA:支持通過 @NamedStoredProcedureQuery 或 @Procedure 調(diào)用存儲(chǔ)過程,但配置稍顯繁瑣。

MyBatis:在 XML 中使用 <select> 標(biāo)簽的 statementType="CALLABLE" 直接調(diào)用存儲(chǔ)過程,參數(shù)映射簡(jiǎn)單直接。

結(jié)論:兩者均支持,MyBatis 更簡(jiǎn)潔。

5.3 性能對(duì)比

5.3.1 基礎(chǔ) CRUD 性能

對(duì)于單表簡(jiǎn)單操作,兩者的性能差異微乎其微,JPA 自動(dòng)生成的 SQL 通常也較為高效。但在批量插入場(chǎng)景下,Hibernate 默認(rèn)的逐條插入性能較差,需開啟 batch 處理;MyBatis 可輕松實(shí)現(xiàn)批量操作(foreach 拼接或使用 Batch Executor)。

5.3.2 N+1 查詢問題

這是 JPA 的經(jīng)典陷阱。當(dāng)查詢一組對(duì)象,隨后遍歷訪問其關(guān)聯(lián)對(duì)象時(shí),若關(guān)聯(lián)配置為懶加載且未在查詢時(shí)抓取,Hibernate 會(huì)為每個(gè)關(guān)聯(lián)對(duì)象發(fā)起一條 SQL,導(dǎo)致 N+1 次查詢。解決方案包括:使用 JOIN FETCH、@EntityGraph、修改抓取策略。開發(fā)者需對(duì)此有清晰認(rèn)知。

MyBatis 不存在 N+1 問題,因?yàn)殛P(guān)聯(lián)數(shù)據(jù)要么通過一次 SQL 的 JOIN 查詢獲?。ㄇ短捉Y(jié)果),要么需要開發(fā)者手動(dòng)發(fā)起二次查詢(嵌套查詢,類似懶加載但需要顯式調(diào)用),SQL 可控,不會(huì)意外產(chǎn)生額外查詢。

5.3.3 緩存機(jī)制

Spring Data JPA (Hibernate)

  • 一級(jí)緩存:Session 級(jí)別,默認(rèn)開啟,減少重復(fù)查詢。
  • 二級(jí)緩存:SessionFactory 級(jí)別,可配置第三方緩存如 EhCache、Redis,緩存實(shí)體對(duì)象。需配置策略(讀寫、只讀等),注意緩存并發(fā)策略。
  • 查詢緩存:緩存查詢結(jié)果集,但需注意緩存的失效問題。

強(qiáng)大的緩存機(jī)制在適當(dāng)場(chǎng)景可大幅提升性能,但配置復(fù)雜,易出現(xiàn)緩存不一致問題。

MyBatis

  • 一級(jí)緩存:SqlSession 級(jí)別,默認(rèn)開啟,范圍較小。
  • 二級(jí)緩存:Mapper 級(jí)別(namespace 級(jí)別),需手動(dòng)開啟,可配置緩存實(shí)現(xiàn)(如 EhCache)。但由于默認(rèn)緩存策略簡(jiǎn)單,多表操作時(shí)容易出現(xiàn)臟數(shù)據(jù)(因?yàn)楦虏僮髦粫?huì)清空本 namespace 的緩存,其他 namespace 可能仍持有舊數(shù)據(jù))。因此,許多 MyBatis 項(xiàng)目放棄二級(jí)緩存,轉(zhuǎn)而追求 SQL 優(yōu)化。

結(jié)論:Hibernate 緩存更強(qiáng)大但復(fù)雜,MyBatis 緩存簡(jiǎn)單但易臟,多數(shù)場(chǎng)景下 MyBatis 用戶依賴 SQL 優(yōu)化而不是緩存。

5.3.4 SQL 優(yōu)化控制

Spring Data JPA:自動(dòng)生成的 SQL 可能不是最優(yōu)的,尤其是多表 JOIN 時(shí)可能產(chǎn)生不必要的字段或關(guān)聯(lián)。雖然可以通過 JPQL 自定義,但 JPQL 最終翻譯的 SQL 仍然由 Hibernate 決定,優(yōu)化空間有限。對(duì)于特定數(shù)據(jù)庫的 Hint、索引強(qiáng)制等,難以直接表達(dá)。

MyBatis:開發(fā)者編寫 SQL 可以精細(xì)控制每一處細(xì)節(jié):選擇字段、JOIN 方式、使用數(shù)據(jù)庫特有函數(shù)、加 Hint 等,與 DBA 協(xié)作順暢。性能優(yōu)化更直接。

結(jié)論:MyBatis 在 SQL 優(yōu)化控制上絕對(duì)優(yōu)勢(shì)。

5.4 維護(hù)性對(duì)比

5.4.1 代碼可讀性與可調(diào)試性

Spring Data JPA:方法名推導(dǎo)的查詢可能非常長(zhǎng)(如 findAllByFirstNameAndLastNameAndAgeBetweenAndCreateTimeAfter),影響可讀性。通過 @Query 定義的 JPQL 在代碼中可見,但 JPQL 與原生 SQL 有一定差異,需要熟悉其語法。調(diào)試時(shí),需要開啟 SQL 日志才能看到實(shí)際執(zhí)行的 SQL,對(duì)于復(fù)雜問題排查不太直觀。

MyBatis:SQL 寫在 XML 中,與 Java 代碼分離,清晰明了。對(duì)于熟悉 SQL 的開發(fā)者,一眼就能看出查詢邏輯。調(diào)試時(shí)直接看到日志中輸出的最終 SQL,復(fù)制即可在數(shù)據(jù)庫客戶端執(zhí)行驗(yàn)證,非常方便。

結(jié)論:MyBatis 在可讀性和可調(diào)試性上更勝一籌。

5.4.2 數(shù)據(jù)庫遷移

Spring Data JPA:切換數(shù)據(jù)庫只需修改方言配置,JPQL 和自動(dòng)生成的 SQL 會(huì)自動(dòng)適配,應(yīng)用代碼基本無需改動(dòng)。這是 JPA 的核心優(yōu)勢(shì)之一。

MyBatis:SQL 與特定數(shù)據(jù)庫語法綁定,遷移數(shù)據(jù)庫意味著需要重寫所有 SQL 語句(至少需要檢查并修改不兼容部分),工作量巨大。除非從一開始就使用各數(shù)據(jù)庫通用的 SQL 子集,但這很難做到。

結(jié)論:JPA 在數(shù)據(jù)庫遷移方面優(yōu)勢(shì)明顯。

5.4.3 項(xiàng)目重構(gòu)與模型變化

當(dāng)領(lǐng)域模型發(fā)生變化(如字段改名、關(guān)聯(lián)關(guān)系變化)時(shí):

  • JPA:只需修改實(shí)體類,自動(dòng) DDL 更新(慎用)或手動(dòng)更新表結(jié)構(gòu),Repository 方法名可能需相應(yīng)調(diào)整,但整體改動(dòng)較少。
  • MyBatis:需要同時(shí)修改實(shí)體類、Mapper 接口、XML 中的 SQL 語句及結(jié)果映射,改動(dòng)點(diǎn)較多,容易遺漏。

5.5 與 Spring Boot 集成

兩者都有成熟的 Spring Boot Starter:

  • spring-boot-starter-data-jpa:自動(dòng)配置 EntityManagerFactory、TransactionManager,支持 @EnableJpaRepositories 掃描 Repository。
  • mybatis-spring-boot-starter:自動(dòng)配置 SqlSessionFactory 和 SqlSessionTemplate,支持 Mapper 掃描。

集成體驗(yàn)都很好,但 JPA 的自動(dòng)配置更加“智能”,例如可以根據(jù)實(shí)體自動(dòng)建表(ddl-auto),對(duì)快速原型開發(fā)很有幫助,但在生產(chǎn)環(huán)境需關(guān)閉。

5.6 社區(qū)與生態(tài)系統(tǒng)

  • Spring Data JPA:作為 Spring 官方項(xiàng)目,背靠龐大的 Spring 社區(qū),文檔齊全,與 Spring 生態(tài)其他項(xiàng)目(Spring Data REST, Spring Data Redis 等)無縫銜接。問題解決方案豐富。
  • MyBatis:國(guó)內(nèi)使用非常廣泛,社區(qū)活躍度很高(尤其在亞洲),有豐富的增強(qiáng)工具:MyBatis Generator(代碼生成)、MyBatis-Plus(國(guó)產(chǎn)增強(qiáng)框架,提供類似 JPA 的 CRUD 接口和條件構(gòu)造器)、PageHelper(分頁插件)等。MyBatis-Plus 的出現(xiàn)極大提升了 MyBatis 的開發(fā)效率,使其在保留靈活性的同時(shí)簡(jiǎn)化了基礎(chǔ)操作。

5.7 事務(wù)管理

兩者都依賴于 Spring 的聲明式事務(wù)管理,使用 @Transactional 注解即可。JPA 在事務(wù)中管理的實(shí)體狀態(tài)變化會(huì)自動(dòng)持久化,而 MyBatis 需要顯式調(diào)用 insert/update 方法。本質(zhì)上事務(wù)管理無差異。

5.8 測(cè)試支持

  • JPA:測(cè)試時(shí)可利用內(nèi)存數(shù)據(jù)庫(如 H2),結(jié)合 @DataJpaTest 切片測(cè)試,非常方便。
  • MyBatis:同樣可以使用內(nèi)存數(shù)據(jù)庫測(cè)試,但需注意 SQL 方言兼容性(H2 可能與生產(chǎn)數(shù)據(jù)庫語法有差異)。MyBatis 也有 @MyBatisTest 支持。

兩者測(cè)試支持均不錯(cuò)。

6. 代碼示例對(duì)比

為了直觀感受差異,我們以常見的用戶-訂單模型為例,演示 CRUD 和復(fù)雜查詢的實(shí)現(xiàn)。

6.1 實(shí)體/模型定義

JPA 實(shí)體

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;
    private String email;
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Order> orders = new ArrayList<>();
    // getters, setters
}
@Entity
@Table(name = "orders")
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String orderNumber;
    private BigDecimal amount;
    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;
    // getters, setters
}

MyBatis 實(shí)體(POJO)

public class User {
    private Long id;
    private String username;
    private String email;
    // 注意:關(guān)聯(lián)對(duì)象通常不直接包含,或通過查詢單獨(dú)獲取
    // getters, setters
}
public class Order {
    private Long id;
    private String orderNumber;
    private BigDecimal amount;
    private Long userId;  // 外鍵字段
    private User user;    // 用于關(guān)聯(lián)查詢的結(jié)果映射
    // getters, setters
}

6.2 基礎(chǔ) CRUD

Spring Data JPA Repository

public interface UserRepository extends JpaRepository<User, Long> {
    // 方法名查詢
    User findByUsername(String username);
    List<User> findByEmailContaining(String emailPart);
}

MyBatis Mapper 接口與 XML

public interface UserMapper {
    User selectById(Long id);
    List<User> selectAll();
    void insert(User user);
    void update(User user);
    void delete(Long id);
    User selectByUsername(String username);
    List<User> selectByEmailContaining(String emailPart);
}
<!-- UserMapper.xml -->
<select id="selectById" resultType="User">
    SELECT * FROM users WHERE id = #{id}
</select>
<select id="selectAll" resultType="User">
    SELECT * FROM users
</select>
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO users(username, email) VALUES(#{username}, #{email})
</insert>
<!-- 其他略 -->

可見 MyBatis 的 CRUD 需要為每個(gè)方法編寫 SQL,即使是簡(jiǎn)單查詢。

6.3 復(fù)雜查詢:按條件搜索用戶(動(dòng)態(tài)條件)

需求:根據(jù)用戶名(模糊)、郵箱(模糊)、創(chuàng)建時(shí)間區(qū)間查詢用戶,所有條件可選。

JPA 使用 Specification

public List<User> searchUsers(String username, String email, Date start, Date end) {
    return userRepository.findAll((root, query, cb) -> {
        List<Predicate> predicates = new ArrayList<>();
        if (StringUtils.hasText(username)) {
            predicates.add(cb.like(root.get("username"), "%" + username + "%"));
        }
        if (StringUtils.hasText(email)) {
            predicates.add(cb.like(root.get("email"), "%" + email + "%"));
        }
        if (start != null) {
            predicates.add(cb.greaterThanOrEqualTo(root.get("createTime"), start));
        }
        if (end != null) {
            predicates.add(cb.lessThanOrEqualTo(root.get("createTime"), end));
        }
        return cb.and(predicates.toArray(new Predicate[0]));
    });
}

MyBatis 動(dòng)態(tài) SQL

<select id="searchUsers" resultType="User">
    SELECT * FROM users
    <where>
        <if test="username != null and username != ''">
            AND username LIKE CONCAT('%', #{username}, '%')
        </if>
        <if test="email != null and email != ''">
            AND email LIKE CONCAT('%', #{email}, '%')
        </if>
        <if test="start != null">
            AND create_time >= #{start}
        </if>
        <if test="end != null">
            AND create_time &lt;= #{end}
        </if>
    </where>
</select>

MyBatis 的動(dòng)態(tài) SQL 更加簡(jiǎn)潔直觀,JPA 的 Criteria API 代碼冗長(zhǎng)且不易讀。

6.4 關(guān)聯(lián)查詢:查詢用戶及其訂單

JPA

// 方法一:通過導(dǎo)航,但會(huì)導(dǎo)致 N+1 問題(懶加載)
User user = userRepository.findById(1L).get();
List<Order> orders = user.getOrders(); // 懶加載觸發(fā)額外查詢
// 方法二:使用 JOIN FETCH 一次查詢
@Query("SELECT u FROM User u LEFT JOIN FETCH u.orders WHERE u.id = :id")
User findByIdWithOrders(@Param("id") Long id);

MyBatis

<!-- 嵌套結(jié)果(一次 JOIN 查詢) -->
<resultMap id="userWithOrdersMap" type="User">
    <id property="id" column="id"/>
    <result property="username" column="username"/>
    <result property="email" column="email"/>
    <collection property="orders" ofType="Order">
        <id property="id" column="order_id"/>
        <result property="orderNumber" column="order_number"/>
        <result property="amount" column="amount"/>
    </collection>
</resultMap>
<select id="selectUserWithOrders" resultMap="userWithOrdersMap">
    SELECT u.*, o.id as order_id, o.order_number, o.amount
    FROM users u
    LEFT JOIN orders o ON u.id = o.user_id
    WHERE u.id = #{id}
</select>

MyBatis 清晰地控制了 SQL 和結(jié)果映射,而 JPA 的 JOIN FETCH 雖然簡(jiǎn)潔,但需要了解 JPQL 語法和可能的笛卡爾積問題。

7. 深入原理與最佳實(shí)踐

7.1 JPA 常見陷阱與應(yīng)對(duì)

7.1.1 N+1 查詢問題

  • 現(xiàn)象:查詢主實(shí)體列表,遍歷獲取關(guān)聯(lián)對(duì)象時(shí)觸發(fā) N 次額外查詢。
  • 解決方案
    • JOIN FETCH:在 JPQL 中顯式使用 LEFT JOIN FETCH 一次加載關(guān)聯(lián)數(shù)據(jù)。但需注意對(duì)分頁的影響(Hibernate 會(huì)先在內(nèi)存中分頁,對(duì)于集合關(guān)聯(lián)可能導(dǎo)致性能問題)。
    • @EntityGraph:通過 @NamedEntityGraph 或 @EntityGraph(attributePaths = {"orders"}) 指定抓取路徑,更靈活。
    • 批量抓取:配置 @BatchSize(size = 10),Hibernate 會(huì)批量加載關(guān)聯(lián)集合,將 N 條查詢減少為 N/size + 1 條。
    • 使用 DTO 投影:直接查詢需要的字段,避免加載整個(gè)實(shí)體及其關(guān)聯(lián)。

7.1.2 更新操作丟失

  • 現(xiàn)象:在事務(wù)外修改實(shí)體,再調(diào)用 save,可能丟失未跟蹤的修改。
  • 原因:托管態(tài)實(shí)體自動(dòng)更新,游離態(tài)實(shí)體需合并。正確做法:在事務(wù)內(nèi)查詢并修改,或使用 merge 合并。

7.1.3 事務(wù)范圍過大

  • 現(xiàn)象:在 Service 層使用大事務(wù),包含大量查詢和更新,導(dǎo)致數(shù)據(jù)庫連接長(zhǎng)時(shí)間占用,甚至死鎖。
  • 應(yīng)對(duì):合理劃分事務(wù)邊界,查詢操作盡量置于事務(wù)外,或使用只讀事務(wù)優(yōu)化。

7.2 MyBatis 高級(jí)特性與優(yōu)化

7.2.1 動(dòng)態(tài) SQL 標(biāo)簽詳解

  • <if>:條件判斷。
  • <choose>、<when><otherwise>:類似 Java switch。
  • <where>:自動(dòng)處理 WHERE 關(guān)鍵字和多余 AND/OR。
  • <set>:用于 UPDATE 語句,自動(dòng)處理 SET 關(guān)鍵字和多余逗號(hào)。
  • <foreach>:遍歷集合,構(gòu)建 IN 條件或批量插入。
  • <bind>:創(chuàng)建變量,如模糊查詢的拼接。

7.2.2 分頁實(shí)現(xiàn)

MyBatis 本身不支持物理分頁,通常借助 PageHelper 插件,通過攔截器修改 SQL 添加 LIMIT 或 ROWNUM。PageHelper 使用 ThreadLocal 傳遞分頁參數(shù),使用時(shí)需注意線程安全問題。

7.2.3 批量操作優(yōu)化

MyBatis 支持批量 ExecutorType.BATCH,通過 SqlSession 的 flushStatements() 批量提交。對(duì)于大量插入,使用 foreach 拼接多條 VALUES 效率更高,但要注意 SQL 長(zhǎng)度限制。

7.3 混合使用:JPA + MyBatis 方案

在實(shí)際項(xiàng)目中,兩者并非互斥,完全可以共存。一種常見架構(gòu):

  • Spring Data JPA:負(fù)責(zé)簡(jiǎn)單的單表 CRUD、快速原型開發(fā)、領(lǐng)域模型驅(qū)動(dòng)設(shè)計(jì)。
  • MyBatis:負(fù)責(zé)復(fù)雜的多表關(guān)聯(lián)查詢、報(bào)表統(tǒng)計(jì)、動(dòng)態(tài)搜索等需要精細(xì)控制 SQL 的場(chǎng)景。

通過不同的包結(jié)構(gòu)(如 repository 和 mapper)區(qū)分,事務(wù)由 Spring 統(tǒng)一管理,可以兼得兩者的優(yōu)點(diǎn)。例如,使用 JPA 管理實(shí)體和基礎(chǔ)操作,使用 MyBatis 做復(fù)雜查詢,甚至可以將 MyBatis 查詢結(jié)果映射為 JPA 實(shí)體(需注意實(shí)體狀態(tài))。這種混合模式在許多大型項(xiàng)目中得到應(yīng)用。

8. 選型建議:何時(shí)選擇哪一個(gè)?

8.1 優(yōu)先選擇 Spring Data JPA 的場(chǎng)景

  • 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(DDD):如果你的項(xiàng)目采用 DDD,以聚合、實(shí)體、值對(duì)象為核心,JPA 的 ORM 能力與 DDD 天然契合,可以很好地實(shí)現(xiàn)聚合內(nèi)的對(duì)象導(dǎo)航和持久化。
  • 快速迭代、原型驗(yàn)證:需要快速交付 MVP,JPA 的自動(dòng)化特性可以極大縮短開發(fā)周期。
  • 數(shù)據(jù)庫無關(guān)性要求高:項(xiàng)目需要支持多種數(shù)據(jù)庫,或未來可能切換數(shù)據(jù)庫,JPA 可以降低遷移成本。
  • 對(duì)象模型復(fù)雜:實(shí)體間關(guān)系復(fù)雜(多對(duì)多、繼承等),JPA 能夠較好地映射這些關(guān)系。
  • 開發(fā)團(tuán)隊(duì)對(duì) SQL 不熟悉或偏向 Java 開發(fā):團(tuán)隊(duì)主要擅長(zhǎng) Java,希望盡量減少 SQL 編寫,利用面向?qū)ο笏季S解決問題。

8.2 優(yōu)先選擇 MyBatis 的場(chǎng)景

  • 遺留系統(tǒng)或復(fù)雜 SQL:需要處理大量存儲(chǔ)過程、復(fù)雜報(bào)表查詢、多表關(guān)聯(lián)統(tǒng)計(jì),MyBatis 可以直接復(fù)用 DBA 優(yōu)化的 SQL。
  • 性能要求極致:對(duì) SQL 執(zhí)行效率有苛刻要求,需要精細(xì)控制索引使用、查詢計(jì)劃,避免任何框架自動(dòng)生成的不可控開銷。
  • 數(shù)據(jù)庫特性依賴強(qiáng):大量使用特定數(shù)據(jù)庫的 JSON、全文檢索、空間數(shù)據(jù)等特性,JPA 支持困難。
  • 團(tuán)隊(duì) SQL 能力強(qiáng):開發(fā)人員精通 SQL,希望通過 SQL 表達(dá)業(yè)務(wù)邏輯,更傾向于直觀的 SQL 調(diào)試。
  • 微服務(wù)中的獨(dú)立數(shù)據(jù)層:在微服務(wù)架構(gòu)中,每個(gè)服務(wù)有自己的數(shù)據(jù)庫,數(shù)據(jù)庫遷移概率低,更關(guān)注性能和靈活性。

8.3 折中方案

如果兩者都不想放棄,可以采用 MyBatis-Plus。它在 MyBatis 基礎(chǔ)上提供了類似 JPA 的通用 CRUD 接口、條件構(gòu)造器、分頁插件等,極大簡(jiǎn)化了基礎(chǔ)操作,同時(shí)保留了 MyBatis 的 SQL 定制能力。MyBatis-Plus 在國(guó)內(nèi)非常流行,是許多新項(xiàng)目的首選。

或者采用 JPA + QueryDSL,QueryDSL 提供了類型安全的動(dòng)態(tài)查詢,比 Criteria API 更優(yōu)雅,但仍有學(xué)習(xí)成本。

9. 個(gè)人喜好與觀點(diǎn)

作為一個(gè)經(jīng)歷過多個(gè)大型項(xiàng)目的開發(fā)者,我的個(gè)人偏好是:根據(jù)場(chǎng)景靈活選擇,但傾向于以 MyBatis 為主,配合 MyBatis-Plus 提升效率,在特定模塊使用 JPA。

9.1 為什么更偏愛 MyBatis?

  • SQL 的可控性帶來安全感:在涉及復(fù)雜業(yè)務(wù)邏輯和性能優(yōu)化的場(chǎng)景,我始終希望能夠親自把握 SQL 的質(zhì)量。MyBatis 讓我清楚每一次查詢的執(zhí)行細(xì)節(jié),避免了 JPA 中因不熟悉機(jī)制而出現(xiàn)的“意外”性能問題(如 N+1、笛卡爾積、大對(duì)象加載)。在排查線上問題時(shí),能夠直接復(fù)制日志中的 SQL 進(jìn)行 explain 分析,快速定位瓶頸。
  • 學(xué)習(xí)曲線平緩,團(tuán)隊(duì)上手快:團(tuán)隊(duì)成員水平參差不齊,MyBatis 讓新成員能夠快速貢獻(xiàn)代碼,無需深入理解實(shí)體狀態(tài)、緩存機(jī)制等復(fù)雜概念。只要會(huì)寫 SQL,就能完成任務(wù),降低了培訓(xùn)成本。
  • 與 DBA 協(xié)作順暢:在企業(yè)環(huán)境中,DBA 通常會(huì)審核 SQL。MyBatis 將 SQL 暴露在 XML 中,DBA 可以直接 review,提出優(yōu)化建議,甚至可以由 DBA 編寫復(fù)雜統(tǒng)計(jì) SQL,開發(fā)人員只需集成。而 JPA 生成的 SQL 不易直接 review,需借助日志提取,溝通成本高。
  • 動(dòng)態(tài) SQL 的強(qiáng)大表達(dá)力:MyBatis 的 <if>、<foreach> 等標(biāo)簽非常直觀,構(gòu)建多條件搜索、批量操作時(shí)得心應(yīng)手。相比之下,JPA 的 Criteria API 代碼量多且難以維護(hù),我寧愿寫原生 SQL。
  • MyBatis-Plus 彌補(bǔ)了開發(fā)效率短板:借助 MyBatis-Plus,我不需要為每個(gè)實(shí)體寫基礎(chǔ)的 CRUD 和 XML,直接繼承 BaseMapper 即可獲得大量方法,還可以使用 LambdaQueryWrapper 構(gòu)建類型安全的條件查詢,開發(fā)效率接近 JPA。但復(fù)雜查詢我依然會(huì)回到 XML 中寫自定義 SQL,兩全其美。

9.2 何時(shí)我會(huì)選擇 JPA?

  • 內(nèi)部管理系統(tǒng)、后臺(tái)管理頁面:這類系統(tǒng)通常 CRUD 為主,邏輯簡(jiǎn)單,追求快速開發(fā)。JPA 配合 Spring Data REST 甚至能快速生成 RESTful 接口。
  • 個(gè)人項(xiàng)目或小團(tuán)隊(duì)原型:為了快速驗(yàn)證想法,JPA 可以讓我專注于業(yè)務(wù)邏輯,而不是 SQL 編寫。
  • 使用 Spring Boot 和 Kotlin 開發(fā):Kotlin 的數(shù)據(jù)類與 JPA 結(jié)合,配合 Spring Data 的 Kotlin 擴(kuò)展,代碼非常簡(jiǎn)潔優(yōu)雅,寫起來很舒服。

9.3 混合使用的實(shí)踐

在我主導(dǎo)的一個(gè)電商項(xiàng)目中,核心交易模塊(訂單、庫存)使用了 MyBatis 精細(xì)控制 SQL,保證高并發(fā)下的性能;而用戶管理、商品類目等模塊使用了 JPA,快速開發(fā)。我們封裝了公共的基礎(chǔ)服務(wù),統(tǒng)一事務(wù),運(yùn)行良好。這證明了兩種框架可以在一個(gè)項(xiàng)目中和諧共存。

10. 未來趨勢(shì)

  • JPA 的發(fā)展:Jakarta EE 的推進(jìn)和 Hibernate 的持續(xù)更新,JPA 在性能、反應(yīng)式支持上不斷進(jìn)步。Spring Data JPA 也在探索對(duì) Kotlin coroutine、Project Loom 的支持。
  • MyBatis 的進(jìn)化:MyBatis 3.5+ 引入了更多 Java 8 特性,如 Optional 支持。MyBatis-Plus 作為非官方增強(qiáng),功能日益強(qiáng)大,甚至開始提供一些 JPA 風(fēng)格的注解。社區(qū)也在嘗試 MyBatis 動(dòng)態(tài) SQL 的新方式(如 Freemarker 模板)。
  • NoSQL 的沖擊:隨著 MongoDB 等文檔數(shù)據(jù)庫的流行,針對(duì) NoSQL 的 Spring Data MongoDB 提供了類似 JPA 的編程模型。但在關(guān)系型數(shù)據(jù)庫領(lǐng)域,JPA 和 MyBatis 仍將長(zhǎng)期并存。
  • 響應(yīng)式編程:Spring Data R2DBC 提供了響應(yīng)式關(guān)系數(shù)據(jù)庫訪問,但 JPA 本身是阻塞的,Hibernate Reactive 尚在實(shí)驗(yàn)階段。MyBatis 也有響應(yīng)式擴(kuò)展(mybatis-reactive),但成熟度有待檢驗(yàn)。

11. 結(jié)論

Spring Data JPA 與 MyBatis 沒有絕對(duì)的優(yōu)劣,只有適合與不適合。JPA 代表了面向?qū)ο蟮淖詣?dòng)化持久化思想,追求開發(fā)效率和數(shù)據(jù)庫無關(guān)性;MyBatis 代表了面向 SQL 的精細(xì)化控制,追求靈活性和性能極致。兩者都是優(yōu)秀的框架,熟練掌握其中任何一個(gè),都能寫出高質(zhì)量的代碼。

對(duì)于開發(fā)者而言,不應(yīng)局限于框架之爭(zhēng),而應(yīng)深入理解背后的原理,根據(jù)項(xiàng)目特點(diǎn)、團(tuán)隊(duì)技能、性能要求做出權(quán)衡。在實(shí)際工作中,混合使用往往能取得最佳效果。

最后,無論選擇哪個(gè),編寫可維護(hù)、高性能的持久層代碼,始終需要開發(fā)者對(duì)數(shù)據(jù)庫原理、SQL優(yōu)化有深刻理解。框架只是工具,思想才是核心。

12. 附錄:性能測(cè)試數(shù)據(jù)對(duì)比(模擬)

場(chǎng)景Spring Data JPA (ms)MyBatis (ms)說明
單條插入 (10000次)45003200JPA需開啟batch,否則慢
批量插入 (10000條)600500兩者接近,JPA batch生效
簡(jiǎn)單查詢 (100次)120100差距不大
復(fù)雜關(guān)聯(lián)查詢 (100次)350280MyBatis 可優(yōu)化SQL
動(dòng)態(tài)條件查詢 (100次)400290Criteria API開銷

到此這篇關(guān)于Spring Data JPA 與 MyBatis 全方位深度解析與實(shí)戰(zhàn)指南的文章就介紹到這了,更多相關(guān)Spring Data JPA 與 MyBatis 對(duì)比內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • mybatis使用foreach踩坑及解決

    mybatis使用foreach踩坑及解決

    這篇文章主要介紹了mybatis使用foreach踩坑及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • SpringBoot Mybatis如何配置多數(shù)據(jù)源并分包

    SpringBoot Mybatis如何配置多數(shù)據(jù)源并分包

    這篇文章主要介紹了SpringBoot Mybatis如何配置多數(shù)據(jù)源并分包,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • SpringBoot手寫自定義starter源碼

    SpringBoot手寫自定義starter源碼

    這篇文章主要介紹了SpringBoot手寫自定義starter源碼,SpringBoot擁有很多方便使用的starter,比如spring-boot-starter-log4j、mybatis-spring-boot-starter.jar等,各自都代表了一個(gè)相對(duì)完整的功能模塊,需要的朋友可以參考下
    2023-10-10
  • String字符串拼接方法concat和+的效率對(duì)比

    String字符串拼接方法concat和+的效率對(duì)比

    這篇文章主要介紹了String字符串拼接方法concat和+的效率對(duì)比,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • springboot文件打包成jar或war的方法

    springboot文件打包成jar或war的方法

    這篇文章主要介紹了springboot文件打包成jar或war的方法以及相關(guān)知識(shí)點(diǎn),需要的朋友們參考下。
    2019-08-08
  • gradle和maven打包時(shí)排除application.properties問題

    gradle和maven打包時(shí)排除application.properties問題

    文章主要介紹了Gradle、Maven(用于構(gòu)建JAR包)和Maven(用于構(gòu)建WAR包),文章基于個(gè)人經(jīng)驗(yàn),為讀者提供了參考,并鼓勵(lì)大家支持腳本之家
    2024-12-12
  • JavaWeb開發(fā)入門第二篇Tomcat服務(wù)器配置講解

    JavaWeb開發(fā)入門第二篇Tomcat服務(wù)器配置講解

    JavaWeb開發(fā)入門第二篇主要介紹了Tomcat服務(wù)器配置的方法教大家如何使用Tomcat服務(wù)器,感興趣的小伙伴們可以參考一下
    2016-04-04
  • Java MD5加密工具類的方法(支持多參數(shù)輸入)

    Java MD5加密工具類的方法(支持多參數(shù)輸入)

    在實(shí)際開發(fā)過程中,MD5加密是一種常見的數(shù)據(jù)安全處理手段,常用于密碼存儲(chǔ)、數(shù)據(jù)完整性校驗(yàn)等場(chǎng)景,這篇文章主要介紹了Java MD5加密工具類(支持多參數(shù)輸入),需要的朋友可以參考下
    2024-05-05
  • 使用Spring?Boot的原因解析

    使用Spring?Boot的原因解析

    Spring Boot是Spring家族的成員,它是一個(gè)全新的框架,它的設(shè)計(jì)目的是盡可能簡(jiǎn)單和快速的開發(fā)、運(yùn)行Spring應(yīng)用程序,簡(jiǎn)化配置,這篇文章主要介紹了為什么使用Spring?Boot,需要的朋友可以參考下
    2022-07-07
  • Java編程之雙重循環(huán)打印圖形

    Java編程之雙重循環(huán)打印圖形

    這篇文章主要介紹了Java編程之雙重循環(huán)打印圖形,屬于Java編程基礎(chǔ)練習(xí)部分,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11

最新評(píng)論

老河口市| 新野县| 冕宁县| 伊金霍洛旗| 孟连| 岳普湖县| 前郭尔| 财经| 贺兰县| 镇江市| 海口市| 和林格尔县| 临汾市| 招远市| 甘孜县| 玉门市| 澄迈县| 高陵县| 桐城市| 仁怀市| 安龙县| 通江县| 赤壁市| 常宁市| 沐川县| 南木林县| 沧源| 于田县| 凯里市| 金溪县| 花莲市| 墨江| 涿鹿县| 读书| 丹巴县| 肇东市| 六盘水市| 珠海市| 通道| 清丰县| 固始县|