使用NCache實現Hibernate第二層缓存

在這個教程中,我們將探讨如何在Hibernate中使用NCache實現第二層緩存。

我們將建立一個Java應用程序與Hibernate。然後我們將配置NCache作為第二層緩存。最後,我們將測試實現,看看緩存如何減少數據庫負載並提高性能。

基礎知識

在深入开展實現之前,讓我們先了解Hibernate、NCache和Hibernate第二層緩存的基础知識。

Hibernate

Hibernate是一個開源的對應關係映射(ORM)框架,用於Java應用程序。它通過將Java物件映射到數據庫表以及相反的操作,簡化了數據庫交雲的開發。

為了提高性能,Hibernate提供兩層緩存:

1. 第一層緩存

第一層緩存與Hibernate會話相關聯,並且是默認启用的。它存放會在會話中取得的物件,並免除了為同一物件多次訪問數據庫的需要。

第一層緩存限制於會話的作用範圍內,並不會在會話之間共享。

它也是非持久化的,當會話關閉或明確清除時會清空。

2. 第二層緩存

二级缓存跨會話共享,可以配置為在應用層級緩存數據。它通過將物件存放更長時間來減少數據庫擊打次數。

二级缓存需要明確配置,可以使用如NCache、Ehcache等各種缓存提供程序来实现。

NCache

NCache是为.NET和Java應用程序提供的分布式緩存解決方案。它提供一個記憶體數據存儲,可用于緩存經常访问的数据并提升應用性能。

NCache支持各種緩存結構,如复製、分区及客戶端緩存。

在Hibernate中,可以使用NCache作為二级緩存,以存儲和检索數據庫中的物件。

代码设置

首先,创建一个Java应用程序并设置Hibernate以與数据库交云。

我們將使用Maven來管理依賴和建造項目。应用程序將有一個实体类來定义数据和一个客户端类來與数据库交云。

首先,我們將在没有缓存的模式下测试应用程序以查看數據庫交云。然後,我們將配置NCache作為Hibernate的二级缓存,以便缓存实体物件並減少數據庫擊打。

依賴

我們將從在pom.xml文件中添加Hibernate和NCache所需的依賴開始:

<dependencies> <!-- Hibernate dependencies --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>6.6.1.Final</version> </dependency> <!-- NCache dependencies --> <dependency> <groupId>com.alachisoft.ncache</groupId> <artifactId>ncache-hibernate</artifactId> <version>5.3.3</version> </dependency> </dependencies>

请注意,此处提到的版本可能基于最新发布版本有所变动。请确保為您的項目使用適當的版本。

实体类

接下來,我們來創建一個实体類以表示我們想要緩存的數據。我們將定義一個簡單的Customer類,具有idname字段:

@Entity @Cacheable @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, region = "CustomerRegion") public class Customer { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; // 取得器和設置器 }

Customer類用@Entity@Cacheable注解標記,以將其定義為可緩存的实体。它有一個id字段,用@Id@GeneratedValue注解標記,以自動生成唯一标识符。

我們還使用@Cache注解來指定实体的緩存策略和地區。

NONSTRICT_READ_WRITE告訴Hibernate在数据被讀取或寫入時更新緩存,以達到最終一致性。

region屬性指定了將数据存放的緩存地區。

我們將配置NCache使用此地區來存放緩存數據。

Hibernate配置

我們需要配置Hibernate以與數據庫互動並啟用緩存。

讓我們在src/main/resources目錄中創建一個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> <property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property> <property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:xe</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">password</property> <property name="hibernate.dialect">org.hibernate.dialect.Oracle12cDialect</property> <property name="hibernate.hbm2ddl.auto">update</property> <property name="hibernate.show_sql">true</property> </session-factory> </hibernate-configuration>

在這個配置文件中,我們指定了數據庫連接詳細信息、方言和緩存設定。我們使用Oracle作為數據庫,並配置Hibernate自動更新架构。

客户端类

我們可以寫一個main類來使用Hibernate保存和取出Customer物件:

public class HibernateClient { public static void main(String[] args) { SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory(); Session session = sessionFactory.openSession(); Transaction transaction = session.beginTransaction(); Customer customer = new Customer(); customer.setName("John Doe"); session.save(customer); transaction.commit(); session.close(); session = sessionFactory.openSession(); transaction = session.beginTransaction(); Customer retrievedCustomer = session.get(Customer.class, customer.getId()); System.out.println("Retrieved Customer: " + retrievedCustomer.getName()); transaction.commit(); session.close(); session = sessionFactory.openSession(); transaction = session.beginTransaction(); retrievedCustomer = session.get(Customer.class, customer.getId()); System.out.println("Retrieved Customer: " + retrievedCustomer.getName()); transaction.commit(); session.close(); } }

在這個客戶端類別中,我們使用Hibernate配置來創建一個SessionFactory,並打開一個會話以與數據庫交互动。我們將Customer物件保存到數據庫中,並使用id取出它。

然後我們在兩個分開的會話中两次調用retrieveCustomer方法,以查看沒有缓存情況下的數據庫交互助用工序。

我們將發現,為了取出同一個物件,數據庫被擊打两次:

如我們所見,Hibernate查詢被执行了两次。

設定NCache服務器

要在Hibernate中使用NCache作為第二層緩存,我們需要設定一個NCache服務器並配置它來存儲緩存數據。

NCache提供一個可在Windows和Linux服務器上安裝的分佈式緩存解決方案。我們將創建一個緩存叢集並用NCache配置它。一旦設定好緩存叢集,我們就可以從我們的Java應用程序中連接到它。

在Hibernate中启用NCache作為第二層緩存

一旦設定好NCache服務器,我們可以配置Hibernate以使用NCache作為第二層緩存提供者。我們將更新Hibernate配置文件並指定緩存設定以啟用緩存。

啟用緩存區節點

更新 hibernate.cfg.xml 文件中的快取設定,以啟用 NCache 作為二級快取提供者:

<hibernate-configuration> <session-factory> <property name="hibernate.cache.use_second_level_cache">true</property> <property name="hibernate.cache.region.factory_class">com.alachisoft.ncache.NCacheRegionFactory</property> ... </session-factory> </hibernate-configuration>

在這裡,我們將 hibernate.cache.use_second_level_cache 屬性設為 true 以啟用二級快取。我們還指定了 hibernate.cache.region.factory_class 屬性以使用 NCacheRegionFactory,這是一個 JCacheRegionFactory 的實現,作為快取提供者。

配置 NCache 屬性

NCache 提供了一組屬性來配置 Hibernate 中的快取設定。我們可以在 ncache-hibernate.xml 文件中指定這些屬性:

<configuration> <application-config application-id="myapp" enable-cache-exception="true" default-region-name="DefaultRegion" key-case-sensitivity="false"> <cache-regions> <region name="CustomerRegion" cache-name="demoCache" priority="AboveNormal" expiration-type="Sliding" expiration-period="8"/> <region name="DefaultRegion" cache-name="demoCache" priority="default" expiration-type="None" expiration-period="0"/> </cache-regions> <database-dependencies> <dependency entity-name="hibernator.BLL.Customer" type="oledb" sql-statement="SELECT CustomerID FROM Customers WHERE CustomerID ='?';" cache-key-format="Customers#[pk]" connection-string="Provider=SQLOLEDB;Data Source=20.200.20.40,1433;Initial Catalog=Northwind;User ID=john;Password=1234;"/> </database-dependencies> </application-config> </configuration>

在這個配置文件中,我們定義了 CustomerRegion 快取區域,包含快取名稱、優先級、過期類型和過期時間。我們將 expiration-type 設置為 Sliding,過期時間為 8 秒。這意味著快取資料在 8 秒的非活動後將過期並從快取中移除。

此外,我們定義了一個 DefaultRegion,為其他未指定快取區域的實體提供預設設定。這用於作為未明確配置實體的後備區域。

擁有多個快取區域允許我們根據不同實體的需求定義不同的快取設定。

接下來的数据库依赖用于Customers实体,以保持缓存与数据库的同步,并在数据库发生更改时更新或删除缓存数据。

我们指定SQL语句以从Customers表中检索CustomerID,以及连接到数据库的连接字符串。

缓存键格式指定基于实体的主键如何生成缓存键。

测试

现在我们已经配置了NCache作为Hibernate的二级缓存,让我们测试应用程序,看看缓存如何提高性能。我们将再次运行客户端类,并观察在启用缓存时数据库的交互。

当我们运行客户端类时,我们会发现第一次调用检索Customer对象时会击数据库以获取数据。然而,第二次调用检索同一对象时,将从缓存中获取,而不是再次击数据库。这展示了缓存如何通过从缓存中提供数据来减轻数据库负载并提高性能。

使用NCache与Hibernate的好处

使用NCache作为Hibernate的二级缓存提供了许多好处:

  • 提升性能:NCache為快取數據提供快速的記憶體存儲,減少延遲並提升吞吐量。它還提供背景更新快取的异步操作,減少對應用性能的影響。
  • 可擴展性:隨著應用程式的擴展,NCache可以水平擴展以處理大量的數據和用戶請求。它可以在叢林中部署並支持像是快取複製和分区等特性來分布負載。
  • 靈活性:NCache提供各種快取結構和配置來滿足不同的應用需求。此外,由於使用了快取區域,不同的实体可以根据其需求拥有不同的快取設定。這讓快取行為有更細緻的控制。
  • 同步:NCache提供數據庫同步的選項,以保持快取與數據庫的同步。這確保了快取數據是最新且反映了在數據庫中做出的最新變更。

總結

在這個教程中,我們探索了使用NCache為Java應用程式實現第二層快取的方法。

我們從了解Hibernate、NCache和Hibernate第二層快取的基本概念開始。然後,我們為Java應用程式設定Hibernate並將NCache設定為第二層快取。最後,我們測試了實現並查看快取如何通過減少數據庫命中次數並從快取中提供數據來提升性能。

通過使用NCache與Hibernate,開發者可以通過應用分布式快取的威力,提升應用程式的性能、可伸縮性和可靠性。NCache提供了一個健全的快取解決方案,它與Hibernate和其他Java框架無縫整合,使其成為Java應用程式中快取數據的理想選擇。

Source:
https://dzone.com/articles/implement-hibernate-second-level-cache-with-ncache