Hibernate 使用詳解

在現代的Java開發中,數據持久化是一個至關重要的環節。而在眾多持久化框架中,Hibernate以其強大的功能和靈活性,成為了開發者們的首選工具。本文將詳細介紹Hibernate的原理、實現過程以及其使用方法,希望能為廣大開發者提供一些有價值的參考。

1. 什么是Hibernate

Hibernate是一個對象關系映射(ORM)框架,它將Java類與數據庫表映射起來,從而實現數據持久化。Hibernate通過提供一種透明的持久化機制,使開發者可以通過面向對象的方式操作數據庫,而無需編寫大量的SQL代碼。它支持多種數據庫,并且能夠根據需求自動生成SQL語句,大大簡化了數據庫操作的復雜性。

2. Hibernate的核心組件

要深入了解Hibernate,首先需要認識其核心組件:

  1. Configuration:配置Hibernate,加載Hibernate配置文件和映射文件,創建SessionFactory。
  2. SessionFactory:負責初始化Hibernate,創建Session對象。是線程安全的,可以被多個線程共享使用。
  3. Session:代表與數據庫的一次會話,用于執行CRUD(增刪改查)操作。Session不是線程安全的,每個線程應該有自己的Session實例。
  4. Transaction:用于管理事務。可以顯式地開啟、提交和回滾事務。
  5. Query:用于執行數據庫查詢,支持HQL(Hibernate Query Language)和原生SQL。

3. Hibernate的配置

在使用Hibernate之前,我們需要進行一些基本的配置。通常,Hibernate的配置文件有兩種:hibernate.cfg.xmlhibernate.properties。下面我們來看看一個簡單的hibernate.cfg.xml示例:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration><session-factory><!-- JDBC Database connection settings --><property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property><property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mydatabase</property><property name="hibernate.connection.username">root</property><property name="hibernate.connection.password">password</property><!-- JDBC connection pool settings --><property name="hibernate.c3p0.min_size">5</property><property name="hibernate.c3p0.max_size">20</property><property name="hibernate.c3p0.timeout">300</property><property name="hibernate.c3p0.max_statements">50</property><property name="hibernate.c3p0.idle_test_period">3000</property><!-- SQL dialect --><property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property><!-- Echo all executed SQL to stdout --><property name="hibernate.show_sql">true</property><!-- Drop and re-create the database schema on startup --><property name="hibernate.hbm2ddl.auto">update</property><!-- Names the annotated entity class --><mapping class="com.example.MyEntity"/></session-factory>
</hibernate-configuration>

在這個配置文件中,我們定義了數據庫連接屬性、連接池設置、SQL方言、SQL輸出以及實體類的映射。通過這些配置,Hibernate可以自動管理數據庫連接并生成相應的SQL語句。

4. 實體類映射

實體類是Hibernate進行對象關系映射的核心。每個實體類對應數據庫中的一個表,每個類的屬性對應表中的列。通過注解或XML配置,我們可以指定這些映射關系。以下是一個簡單的實體類示例:

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;@Entity
public class MyEntity {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;private String description;// Getters and setterspublic Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}
}

在這個示例中,我們使用了JPA注解來定義實體類的映射關系。@Entity表示這是一個實體類,@Id表示主鍵,@GeneratedValue定義了主鍵的生成策略。此外,類中的屬性會自動映射到對應的數據庫列。

5. Hibernate的基本操作

5.1 保存實體

保存實體是將對象持久化到數據庫中的過程。通過Session對象,我們可以輕松地將實體保存到數據庫中。下面是一個示例:

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;public class HibernateSaveExample {public static void main(String[] args) {// 創建SessionFactorySessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();// 獲取SessionSession session = sessionFactory.openSession();// 開始事務session.beginTransaction();// 創建實體對象MyEntity myEntity = new MyEntity();myEntity.setName("Example Name");myEntity.setDescription("Example Description");// 保存實體session.save(myEntity);// 提交事務session.getTransaction().commit();// 關閉Sessionsession.close();}
}

在這個示例中,我們首先創建了一個SessionFactory對象,然后通過SessionFactory獲取一個Session對象。接著,開啟事務,創建實體對象,并使用session.save方法將實體保存到數據庫中。最后,提交事務并關閉Session

5.2 查詢實體

Hibernate提供了多種查詢方式,包括HQL、Criteria API和原生SQL。下面我們以HQL為例,演示如何查詢實體:

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;import java.util.List;public class HibernateQueryExample {public static void main(String[] args) {// 創建SessionFactorySessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();// 獲取SessionSession session = sessionFactory.openSession();// 開始事務session.beginTransaction();// 執行HQL查詢List<MyEntity> results = session.createQuery("from MyEntity", MyEntity.class).list();// 輸出結果for (MyEntity entity : results) {System.out.println(entity.getName() + ": " + entity.getDescription());}// 提交事務session.getTransaction().commit();// 關閉Sessionsession.close();}
}

在這個示例中,我們使用session.createQuery方法執行了一條簡單的HQL查詢,獲取了所有MyEntity對象,并打印出它們的名稱和描述。

5.3 更新實體

更新實體是修改已存在的持久化對象。通過Session對象,我們可以輕松地更新實體。下面是一個示例:

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;public class HibernateUpdateExample {public static void main(String[] args) {// 創建SessionFactorySessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();// 獲取SessionSession session = sessionFactory.openSession();// 開始事務session.beginTransaction();// 獲取實體對象MyEntity myEntity = session.get(MyEntity.class, 1L);if (myEntity != null) {// 更新實體屬性myEntity.setDescription("Updated Description");// 更新實體session.update(myEntity);}// 提交事務session.getTransaction().commit();// 關閉Sessionsession.close();}
}

在這個示例中,我們首先通過session.get方法獲取一個持久化的MyEntity對象,然后修改其屬性,并使用session.update方法將修改后的實體更新到數據庫中。

5.4 刪除實體

刪除實體是從數據庫中移除持久化對象的過程。通過Session對象,我們可以輕松地刪除實體。下面是一個示例:

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;public class HibernateDeleteExample {public static void main(String[] args) {// 創建SessionFactorySessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();// 獲取SessionSession session = sessionFactory.openSession();// 開始事務session.beginTransaction();// 獲取實體對象MyEntity myEntity = session.get(MyEntity.class, 1L);if (myEntity != null) {// 刪除實體session.delete(myEntity);}// 提交事務session.getTransaction().commit();// 關閉Sessionsession.close();}
}

在這個示例中,我們首先通過session.get方法獲取一個持久化的MyEntity對象,然后使用session.delete方法將其從數據庫中刪除。

6. 事務管理

事務管理是保證數據一致性的關鍵。Hibernate提供了簡單易用的事務管理接口。以下是一個示例:

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;public class HibernateTransactionExample {public static void main(String[] args) {// 創建SessionFactorySessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();// 獲取SessionSession session = sessionFactory.openSession();Transaction transaction = null;try {// 開始事務transaction = session.beginTransaction();// 執行一些數據庫操作MyEntity myEntity = new MyEntity();myEntity.setName("Transactional Name");myEntity.setDescription("Transactional Description");session.save(myEntity);// 提交事務transaction.commit();} catch (Exception e) {if (transaction != null) {// 回滾事務transaction.rollback();}e.printStackTrace();} finally {// 關閉Sessionsession.close();}}
}

在這個示例中,我們使用session.beginTransaction方法開始事務,并在出現異常時回滾事務。這樣可以確保在發生錯誤時,數據庫不會處于不一致的狀態。

7. 高級特性

7.1 一級緩存和二級緩存

Hibernate的緩存機制能夠顯著提高應用程序的性能。Hibernate提供了一級緩存和二級緩存:

  • 一級緩存:是Session級別的緩存,在Session的生命周期內有效。每個Session都有自己的一級緩存。
  • 二級緩存:是SessionFactory級別的緩存,可以被多個Session共享。常用的二級緩存實現有Ehcache、OSCache等。

7.2 延遲加載

延遲加載(Lazy Loading)是Hibernate的一個重要特性。它允許我們在需要時才加載實體的屬性,從而提高性能。可以通過在實體類的屬性上使用@Basic(fetch = FetchType.LAZY)注解來實現延遲加載。例如:

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Basic;
import javax.persistence.FetchType;@Entity
public class MyEntity {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;@Basic(fetch = FetchType.LAZY)private String description;// Getters and setterspublic Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}
}

在這個示例中,description屬性會在第一次訪問時才被加載。

7.3 級聯操作

級聯操作允許我們在操作一個實體時,自動操作與之關聯的其他實體。可以通過@OneToMany@ManyToOne@OneToOne@ManyToMany注解的cascade屬性來實現。例如:

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.OneToMany;
import javax.persistence.CascadeType;
import java.util.Set;@Entity
public class MyEntity {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;@OneToMany(cascade = CascadeType.ALL)private Set<RelatedEntity> relatedEntities;// Getters and setterspublic Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Set<RelatedEntity> getRelatedEntities() {return relatedEntities;}public void setRelatedEntities(Set<RelatedEntity> relatedEntities) {this.relatedEntities = relatedEntities;}
}

在這個示例中,當我們保存或刪除MyEntity對象時,relatedEntities集合中的所有RelatedEntity對象也會被相應地保存或刪除。

8. 實戰演練:構建一個簡單的博客系統

為了更好地理解Hibernate的使用,我們將通過一個簡單的博客系統示例來演示其應用。

8.1 創建實體類

我們需要創建三個實體類:UserPostComment

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.OneToMany;
import java.util.Set;@Entity
public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String username;private String password;@OneToMany(mappedBy = "user")private Set<Post> posts;// Getters and setters// ...
}@Entity
public class Post {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String title;private String content;@ManyToOneprivate User user;@OneToMany(mappedBy = "post", cascade = CascadeType.ALL)private Set<Comment> comments;// Getters and setters// ...
}@Entity
public class Comment {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String content;@ManyToOneprivate Post post;// Getters and setters// ...
}

8.2 配置Hibernate

我們需要在hibernate.cfg.xml中配置這些實體類:

<hibernate-configuration><session-factory><!-- JDBC Database connection settings --><property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property><property name="hibernate.connection.url">jdbc:mysql://localhost:3306/blog</property><property name="hibernate.connection.username">root</property><property name="hibernate.connection.password">password</property><!-- JDBC connection pool settings --><property name="hibernate.c3p0.min_size">5</property><property name="hibernate.c3p0.max_size">20</property><property name="hibernate.c3p0.timeout">300</property><property name="hibernate.c3p0.max_statements">50</property><property name="hibernate.c3p0.idle_test_period">3000</property><!-- SQL dialect --><property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property><!-- Echo all executed SQL to stdout --><property name="hibernate.show_sql">true</property><!-- Drop and re-create the database schema on startup --><property name="hibernate.hbm2ddl.auto">update</property><!-- Names the annotated entity class --><mapping class="com.example.User"/><mapping class="com.example.Post"/><mapping class="com.example.Comment"/></session-factory>
</hibernate-configuration>

8.3 實現業務邏輯

我們將實現一些基本的業務邏輯,例如創建用戶、發布文章和添加評論。

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;public class BlogApplication {private static SessionFactory sessionFactory;public static void main(String[] args) {// 初始化SessionFactorysessionFactory = new Configuration().configure().buildSessionFactory();// 創建用戶User user = createUser("john_doe", "password123");// 發布文章Post post = createPost(user, "My First Post", "This is the content of my first post.");// 添加評論addComment(post, "Great post!");// 關閉SessionFactorysessionFactory.close();}public static User createUser(String username, String password) {Session session = sessionFactory.openSession();session.beginTransaction();User user = new User();user.setUsername(username);user.setPassword(password);session.save(user);session.getTransaction().commit();session.close();return user;}public static Post createPost(User user, String title, String content) {Session session = sessionFactory.openSession();session.beginTransaction();Post post = new Post();post.setTitle(title);post.setContent(content);post.setUser(user);session.save(post);session.getTransaction().commit();session.close();return post;}public static void addComment(Post post, String content) {Session session = sessionFactory.openSession();session.beginTransaction();Comment comment = new Comment();comment.setContent(content);comment.setPost(post);session.save(comment);session.getTransaction().commit();session.close();}
}

通過這個簡單的博客系統示例,我們可以看到如何使用Hibernate進行基本的CRUD操作,以及如何處理實體之間的關系。

結語

Hibernate作為一個強大的ORM框架,通過提供透明的持久化機制,大大簡化了Java開發者對數據庫的操作。本文詳細介紹了Hibernate的原理、配置、基本操作、高級特性以及一個實際的應用示例,希望能幫助讀者更好地理解和使用Hibernate。在實際開發中,Hibernate不僅能提高開發效率,還能有效地管理數據的一致性和完整性,是Java開發者不可或缺的利器。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/92916.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/92916.shtml
英文地址,請注明出處:http://en.pswp.cn/web/92916.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【圖像算法 - 13】基于 YOLO12 與 OpenCV 的實時目標點擊跟蹤系統(系統介紹 + 源碼詳細)

基于 YOLO12 與 OpenCV 的實時點擊目標跟蹤系統 在計算機視覺領域&#xff0c;目標檢測與跟蹤是兩個核心任務。本文將介紹一個結合 YOLO 目標檢測模型與 OpenCV 跟蹤算法的實時目標跟蹤系統&#xff0c;該系統允許用戶通過鼠標交互選擇特定目標進行持續跟蹤&#xff0c;支持多…

【數據庫】 MySQL 表的操作詳解

在 MySQL 數據庫的日常開發與維護中&#xff0c;表的操作是最基礎且最常用的部分。本文將從 創建表、查看表結構、修改表 以及 刪除表 等方面進行詳細講解&#xff0c;并附上對應的 SQL 語句示例&#xff0c;方便在實際項目中直接應用。一、創建表 1.1 創建表語法 CREATE TABLE…

DiT: Transformer上的擴散模型

論文&#xff08;ICCV 2023&#xff09;&#xff1a;Scalable Diffusion Models with Transformers 代碼和工程網頁&#xff1a;https://www.wpeebles.com/DiT.html DiTs&#xff08;Diffusion Transformers&#xff09;是首個基于Transformer架構的擴散模型&#xff01;它在…

MySQL 索引:索引為什么使用 B+樹?(詳解B樹、B+樹)

文章目錄一、二叉查找樹(BST)&#xff1a;不平衡二、平衡二叉樹(AVL)&#xff1a;旋轉耗時三、紅黑樹&#xff1a;樹太高由一個例子總結索引的特點基于哈希表實現的哈希索引高效的查找方式&#xff1a;二分查找基于二分查找思想的二叉查找樹升級版的BST樹&#xff1a;AVL 樹四、…

ESP32入門開發·VScode空白項目搭建·點亮一顆LED燈

目錄 1. 環境搭建 2. 創建項目 3. 調試相關介紹 4. 代碼編寫 4.1 包含頭文件 4.2 引腳配置 4.3 設置輸出電平 4.4 延時函數 4.5 調試 1. 環境搭建 默認已經搭建好環境&#xff0c;如果未搭建好可參考&#xff1a; ESP32入門開發Windows平臺下開發環境的搭建…

ONLYOFFICE AI 智能體上線!與編輯器、新的 AI 提供商等進行智能交互

ONLYOFFICE AI 插件?迎來重要更新&#xff0c;帶來了新功能和更智能的交互體驗。隨著 AI 智能體&#xff08;現為測試版&#xff09;的上線、帶來更多 AI 提供商支持以及其他新功能&#xff0c;AI 插件已經成為功能強大的文檔智能助理。 關于 ONLYOFFICE ONLYOFFICE 文檔是多…

【C++進階學習】第十一彈——C++11(上)——右值引用和移動語義

前言&#xff1a; 前面我們已經將C的重點語法講的大差不差了&#xff0c;但是在C11版本之后&#xff0c;又出來了很多新的語法&#xff0c;其中有一些作用還是非常大的&#xff0c;今天我們就先來學習其中一個很重要的點——右值引用以及它所擴展的移動定義 目錄 一、左值引用和…

【IoTDB】363萬點/秒寫入!IoTDB憑何領跑工業時序數據庫賽道?

【作者主頁】Francek Chen 【專欄介紹】???大數據與數據庫應用??? 大數據是規模龐大、類型多樣且增長迅速的數據集合&#xff0c;需特殊技術處理分析以挖掘價值。數據庫作為數據管理的關鍵工具&#xff0c;具備高效存儲、精準查詢與安全維護能力。二者緊密結合&#xff0…

IEEE 2025 | 重磅開源!SLAM框架用“法向量+LRU緩存”,將三維重建效率飆升72%!

一、前言 當前研究領域在基于擴散模型的文本到圖像生成技術方面取得了顯著進展&#xff0c;尤其在視覺條件控制方面。然而&#xff0c;現有方法&#xff08;如ControlNet&#xff09;在組合多個視覺條件時存在明顯不足&#xff0c;主要表現為獨立控制分支在去噪過程中容易引入…

無人機遙控器教練模式技術要點

一、技術要點1.控制權仲裁機制&#xff1a;核心功能&#xff1a;清晰定義主控權歸屬邏輯&#xff08;默認為學員&#xff0c;但教練隨時可接管&#xff09;。切換方式&#xff1a;通常通過教練遙控器上的物理開關&#xff08;瞬時或鎖定型&#xff09;或軟件按鈕觸發。切換邏輯…

【跨服務器的數據自動化下載--安裝公鑰,免密下載】

跨服務器的數據自動化下載功能介紹&#xff1a;上代碼&#xff1a;發現好久沒寫csdn了&#xff0c;說多了都是淚~~ 以后會更新一些自動化工作的腳本or 小tricks&#xff0c;歡迎交流。分享一個最近在業務上寫的較為實用的自動化腳本&#xff0c;可以批量從遠端服務器下載指定數…

C++-->stl: list的使用

前言list的認識list是可以在固定時間&#xff08;O&#xff08;1&#xff09;&#xff09;內在任意位置進行插入和刪除的序列式容器&#xff0c;并且該容器可以前后雙向迭代。 2. list的底層是雙向鏈表結構&#xff0c;雙向鏈表中每個元素存儲在互不相關的獨立節點中&#xff0…

本地WSL部署接入 whisper + ollama qwen3:14b 總結字幕

1. 實現功能 M4-1 接入 whisper ollama qwen3:14b 總結字幕 自動下載視頻元數據如果有字幕&#xff0c;只下載字幕使用 ollama 的 qwen3:14b 對字幕內容進行總結 2.運行效果 source /root/anaconda3/bin/activate ytdlp &#x1f50d; 正在提取視頻元數據… &#x1f4dd; 正在…

《Linux運維總結:Shell腳本高級特性之變量間接調用》

總結&#xff1a;整理不易&#xff0c;如果對你有幫助&#xff0c;可否點贊關注一下&#xff1f; 更多詳細內容請參考&#xff1a;Linux運維實戰總結 一、變量間接調用 在Shell腳本中&#xff0c;變量間接調用是一種高級特性&#xff0c;它允許你通過另一個變量的值來動態地訪問…

ABP VNext + Akka.NET:高并發處理與分布式計算

ABP VNext Akka.NET&#xff1a;高并發處理與分布式計算 &#x1f680; 用 Actor 模型把高并發寫入“分片→串行化”&#xff0c;把鎖與競態壓力轉回到代碼層面的可控順序處理&#xff1b;依托 Cluster.Sharding 橫向擴容&#xff0c;Persistence 宕機可恢復&#xff0c;Strea…

[激光原理與應用-250]:理論 - 幾何光學 - 透鏡成像的優缺點,以及如克服缺點

透鏡成像是光學系統中應用最廣泛的技術&#xff0c;其通過折射原理將物體信息轉換為圖像&#xff0c;但存在像差、環境敏感等固有缺陷。以下是透鏡成像的優缺點及針對性改進方案&#xff1a;一、透鏡成像的核心優點高效集光能力透鏡通過曲面設計將分散光線聚焦到一點&#xff0…

測試匠談 | AI語音合成之大模型性能優化實踐

「測試匠談」是優測云服務平臺傾心打造的內容專欄&#xff0c;匯集騰訊各大產品的頂尖技術大咖&#xff0c;為大家傾囊相授開發測試領域的知識技能與實踐&#xff0c;讓測試工作變得更加輕松高效。 本期嘉賓介紹 Soren&#xff0c;騰訊TEG技術事業群質量工程師&#xff0c;負責…

用天氣預測理解分類算法-從出門看天氣到邏輯回歸

一、生活中的決策難題&#xff1a;周末郊游的「天氣判斷」 周末計劃郊游時&#xff0c;你是不是總會打開天氣預報反復確認&#xff1f;看到 "25℃、微風、無雨" 就興奮收拾行李&#xff0c;看到 "35℃、暴雨" 就果斷取消計劃。這個判斷過程&#xff0c;其…

HTTPS服務

HTTPS服務 一、常見的端口 http ------ 80 明文 https ------ 443 數據加密 dns ------ 53 ssh ------ 22 telent ------ 23 HTTPS http ssl或者tls &#xff08;安全模式&#xff09; 二、原理&#xff1a; c&#xff08;客戶端…

【Android筆記】Android 自定義 TextView 實現垂直漸變字體顏色(支持 XML 配置)

Android 自定義 TextView 實現垂直漸變字體顏色&#xff08;支持 XML 配置&#xff09; 在 Android UI 設計中&#xff0c;字體顏色的漸變效果能讓界面看起來更加精致與現代。常見的漸變有從左到右、從上到下等方向&#xff0c;但 Android 的 TextView 默認并不支持垂直漸變。…