我喜歡看到EclipseLink仍然是Java持久性創新的中心,并且他們正在努力及時采用最新的動態更新。 總的來說,我為一個較為保守的行業工作,我正在尋找的主要新功能是多租戶。 您可以從幻燈片中猜測,該字段中的某些內容應該已經可以與最新的EclipseLink 2.3.0一起使用。
多租戶將是什么樣子?
讓我們開始看什么Oracle的琳達DeMichiel在過去幾年的JavaOne(對比宣布博客-后 ),也讓我們了解一下什么的早期草案(PDF)的JPA 2.1規范所提供的。 較容易的部分是早期草案。 在任何情況下,沒有一行提到“ Multitenan [t | cy]”。 因此,對于進一步的迭代來說,這顯然仍然是一件大事。 在JavaOne策略主題演講 (幻燈片41,42)和JavaOne技術主題演講(PDF) (幻燈片25)中可以找到更多信息。 通用Java EE 7方法將為不同租戶支持同一應用程序的單獨隔離實例。 映射應由容器完成,并以某種方式可供應用程序使用。 直到今天,這都是非常模糊的,幻燈片中唯一可用的具體代碼示例使用兩個注釋@Multitenant和@TenantDiscriminatorColumn引用了一些明顯的JPA相關示例。 嗯 這看起來對您不熟悉嗎?
今天有什么可能?
是的! EclipseLink(從2.??3.0版開始-Indigo)使用承租人區分符列支持共享的多承租人表,從而允許將一個應用程序重新用于多個承租人并將其所有數據放置在一起。 所有租戶共享相同的架構而彼此之間不知道,并且可以照常使用非多租戶實體類型。 但是請注意,這只是數據多租戶的一種可能方法。 這通常稱為“專用數據庫”,因為所有租戶的數據都進入一個單獨的數據庫中! 以下是基本原則: –應用程序實例處理多個租戶 – JPA必須隔離每個租戶的緩存 您可以在專用的EclipseLink Wiki頁面上查看所有詳細信息。 想要試駕嗎? 開始吧。 像往常一樣先決條件(NetBeans,GlassFish,MySQL,如果需要更多幫助,請比較舊文章。)。 確保具有正確的EclipseLink依賴項(至少2.3.0)! 通過向導創建一個新實體,設置數據源和persistence.xml并將其命名為“客戶”。
@Entity
public class Customer implements Serializable {
//...
}
如果啟動您的應用程序,則會看到EclipseLink在數據庫中創建類似這樣的內容。

讓我們使其成為一個多租戶實體。 添加以下注釋:
@Entity
@Multitenant
@TenantDiscriminatorColumn(name = "companyId", contextProperty = "company-tenant.code")
public class Customer implements Serializable {
//...
}
有多種用法選項可用于如何在具有@Multitenant實體類型的應用程序中使用EclipseLink JPA持久性單元。 由于不同的租戶將只能訪問其行,因此必須配置持久層,以使來自不同租戶的實體不會出現在同一緩存中。 如果您比較詳細的方法(專用PC,每個租戶PC,每個租戶PU),您會發現,到今天為止,您可以通過容器管理的PC或PU注入實現兩種可能的選擇。 讓我們首先嘗試最簡單的方法。
專用持久性單元
在這種用法中,每個租戶都定義了一個持久性單元,應用程序/容器必須為其租戶請求正確的PersistenceContext或PersistenceUnit。 只有一個持久性單元,沒有共享的內容。 繼續上面的示例,然后將以下屬性添加到persistence.xml中:
<property name="company-tenant.code" value="TENANT1" />
試試看,比較表。

如您所見,現在您有了companyId列。 如果插入一些數據,它將始終被在persistence.xml中分配的屬性值填充。 使用@PersistenceContext或@PersistenceUnit訪問您的實體。 使用這種方法,您可以像平常一樣為應用程序共享一個緩存。
![]() |
具有共享緩存的@PersistenceContext(來源:S.Smith) |
每個租戶的持久性上下文
如果不想每個應用程序有一個租戶,則可以決定在persistence.xml中具有一個持久性單元定義,并在應用程序中具有一個共享的持久性單元(EntityManagerFactory和緩存)。 在這種情況下,需要在運行時為每個EntityManager指定承租人上下文。 在這種情況下,您可以使用常規實體類型的共享緩存,但是@Multitenant類型必須在緩存中受到保護。 您可以通過指定一些屬性來做到這一點:
@PersistenceUnit
EntityManagerFactory emf;
Map props = new HashMap();
props.put("company-tenant.code", "TENANT2");
props.put(PersistenceUnitProperties.MULTITENANT_SHARED_EMF, true);
EntityManager em = emf.createEntityManager(props);
![]() |
每個租戶共享@PersistenceUnit(來源:S.Smith) |
鑒別方法
上面的示例使用單個區分符租戶列。 您可以通過指定primaryKey屬性,將discriminator列添加到PK,如下所示:
@TenantDiscriminatorColumn(name = "companyId", contextProperty = "company-tenant.code", primaryKey = true)
如果執行以下操作,則也可能使用多個表使用多個租戶區分符列:
@Entity
@SecondaryTable(name = "TENANTS")
@Multitenant
@TenantDiscriminatorColumns({@TenantDiscriminatorColumn(name = "TENANT_ID", contextProperty = "company-tenant.id", length = 20, primaryKey = true),@TenantDiscriminatorColumn(name = "TENANT_CODE", contextProperty = "company-tenant.code", discriminatorType = DiscriminatorType.STRING, table = "TENANTS")
})
這將導致輔助租戶表。

其他物品
與往常一樣,您也只能在persistence.xml中進行完整的配置。 作為參考,請查看已經提到的Wiki頁面。 最后一件事很有趣。 您也可以將“租戶區分符”列與您的實體對應。 您只需確保未更新或插入它即可。
@Basic@Column(name = "TENANT_ID", insertable = false, updatable = false)private int tenantId;public int getTenantId() {return tenantId;}
查看調試輸出,您可以了解幕后情況:
INFO:獲取EntityManager
INFO:插入測試客戶
FEIN:插入客戶(ID,TENANT_ID)值(?,?) 綁定=> [1,2] FEIN:插入租戶(ID,TENANT_CODE)的值(?,?) 綁定=> [1,TENANT2] FEIN:從客戶t0,租戶t1中選擇t0.ID,t1.TENANT_CODE,t0.TENANT_ID,t1.ID((((t1.ID = t0.ID)和(t1.TENANT_CODE =?)))和(t0.TENANT_ID =?)) 綁定=> [TENANT2,2]
是否對更多Java EE 7和JPA 2.1好東西感興趣? 使用EclipseLink JPA 2.1項目的開發狀態Wiki頁面保持更新。
參考: Java EE 7的最高峰–來自我們JCG合作伙伴的 EclipseLink的多租戶示例 ? Markus Eisele在Enterprise Software Development with Java博客上。
翻譯自: https://www.javacodegeeks.com/2012/02/sneak-peak-at-java-ee-7-multitenant.html